@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
88 <NcDialog
99 :open =" open"
1010 size =" large"
11- :name =" title "
11+ :name =" t('profile_fields', 'Edit additional profile fields') "
1212 content-classes =" profile-fields-user-dialog__content"
1313 @update:open =" updateOpen" >
1414 <div class =" profile-fields-user-dialog" >
@@ -31,13 +31,13 @@ SPDX-License-Identifier: AGPL-3.0-or-later
3131
3232 <div v-if =" isLoading" class =" profile-fields-user-dialog__loading" >
3333 <NcLoadingIcon :size =" 32" />
34- <span >Loading profile fields for {{ userUid }}... </span >
34+ <span >{{ loadingMessage }}</span >
3535 </div >
3636
3737 <NcEmptyContent
3838 v-else-if =" editableFields.length === 0"
39- name =" No editable fields"
40- description =" Create and enable fields in the admin catalog. They will appear here automatically." />
39+ : name =" t('profile_fields', ' No editable fields') "
40+ : description =" t('profile_fields', ' Create and enable fields in the admin catalog. They will appear here automatically.') " />
4141
4242 <div v-else class =" profile-fields-user-dialog__list" >
4343 <article v-for =" field in editableFields" :key =" field.definition.id" class =" profile-fields-user-dialog__row" :class =" { 'profile-fields-user-dialog__row--error': fieldHasError(field) }" >
@@ -75,7 +75,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
7575 />
7676
7777 <div class =" profile-fields-user-dialog__visibility-control" :class =" { 'profile-fields-user-dialog__visibility-control--error': fieldHasError(field) }" >
78- <label class =" profile-fields-user-dialog__control-label" :for =" `profile-fields-user-dialog-visibility-${field.definition.id}`" >{{ visibilityControlLabel }}</label >
78+ <label class =" profile-fields-user-dialog__control-label" :for =" `profile-fields-user-dialog-visibility-${field.definition.id}`" >{{ t('profile_fields', 'Who can see this') }}</label >
7979 <NcSelect
8080 :input-id =" `profile-fields-user-dialog-visibility-${field.definition.id}`"
8181 :model-value =" visibilityOptionFor(field.definition.id)"
@@ -94,18 +94,18 @@ SPDX-License-Identifier: AGPL-3.0-or-later
9494
9595 <template #actions >
9696 <NcButton @click =" closeDialog" >
97- Cancel
97+ {{ t('profile_fields', ' Cancel') }}
9898 </NcButton >
9999 <NcButton variant =" primary" :disabled =" !hasPendingChanges || hasInvalidFields || isSavingAny || isLoading" @click =" saveAllFields" >
100- {{ isSavingAny ? ' Saving changes...' : ' Save changes' }}
100+ {{ isSavingAny ? t('profile_fields', ' Saving changes...') : t('profile_fields', ' Save changes') }}
101101 </NcButton >
102102 </template >
103103 </NcDialog >
104104</template >
105105
106106<script lang="ts">
107107import { computed , defineComponent , reactive , ref , watch } from ' vue'
108- import { t } from ' @nextcloud/l10n'
108+ import { n , t } from ' @nextcloud/l10n'
109109import NcAvatar from ' @nextcloud/vue/components/NcAvatar'
110110import { NcButton , NcDialog , NcEmptyContent , NcInputField , NcLoadingIcon , NcNoteCard , NcSelect } from ' @nextcloud/vue'
111111import { listAdminUserValues , listDefinitions , upsertAdminUserValue } from ' ../api'
@@ -144,7 +144,6 @@ export default defineComponent({
144144 ' update:open' : (value : boolean ) => typeof value === ' boolean' ,
145145 },
146146 setup(props : { open: boolean , userUid: string , userDisplayName: string }, { emit }: { emit: (event : ' update:open' , value : boolean ) => void }) {
147- const visibilityControlLabel = t (' profile_fields' , ' Who can see this' )
148147 const definitions = ref <FieldDefinition []>([])
149148 const userValues = ref <FieldValueRecord []>([])
150149 const isLoading = ref (false )
@@ -156,18 +155,20 @@ export default defineComponent({
156155 const userDraftValues = reactive <Record <number , string >>({})
157156 const userDraftVisibilities = reactive <Record <number , FieldVisibility >>({})
158157
159- const title = computed (() => ' Edit additional profile fields' )
160158 const headerUserName = computed (() => props .userDisplayName .trim () !== ' ' ? props .userDisplayName : props .userUid )
159+ const loadingMessage = computed (() => t (' profile_fields' , ' Loading profile fields for {userUid}...' , { userUid: props .userUid }))
161160 const editableFields = computed <AdminEditableField []>(() => buildAdminEditableFields (definitions .value , userValues .value ))
162161 const isSavingAny = computed (() => savingIds .value .length > 0 )
163162 const headerDescription = computed (() => {
164163 if (props .userUid === ' ' ) {
165- return ' Update additional profile fields for the selected account.'
164+ return t ( ' profile_fields ' , ' Update additional profile fields for the selected account.' )
166165 }
167166
168167 const count = editableFields .value .length
169- const label = count === 1 ? ' 1 editable field' : ` ${count } editable fields `
170- return ` ${label } for @${props .userUid }. `
168+ return n (' profile_fields' , ' {count} editable field for @{userUid}.' , ' {count} editable fields for @{userUid}.' , count , {
169+ count ,
170+ userUid: props .userUid ,
171+ })
171172 })
172173
173174 const clearRecord = (record : Record <string | number , unknown >) => {
@@ -177,15 +178,15 @@ export default defineComponent({
177178 }
178179
179180 const descriptionForType = (type : FieldType ): string => ({
180- text: ' Free text stored as a scalar value.' ,
181- number: ' Only numeric values are accepted.' ,
182- select: ' Choose one of the predefined options.' ,
181+ text: t ( ' profile_fields ' , ' Free text stored as a scalar value.' ) ,
182+ number: t ( ' profile_fields ' , ' Only numeric values are accepted.' ) ,
183+ select: t ( ' profile_fields ' , ' Choose one of the predefined options.' ) ,
183184 } as Record <FieldType , string >)[type ]
184185
185186 const placeholderForField = (type : FieldType ): string => ({
186- text: ' Enter a value' ,
187- number: ' Enter a number' ,
188- select: ' Select an option' ,
187+ text: t ( ' profile_fields ' , ' Enter a value' ) ,
188+ number: t ( ' profile_fields ' , ' Enter a number' ) ,
189+ select: t ( ' profile_fields ' , ' Select an option' ) ,
189190 } as Record <FieldType , string >)[type ]
190191
191192 const plainNumberPattern = / ^ -? \d + (\. \d + )? $ /
@@ -219,13 +220,13 @@ export default defineComponent({
219220 }
220221
221222 if (field .definition .type === ' number' && ! plainNumberPattern .test (rawValue )) {
222- return ` ${ field . definition . label } must be a plain numeric value.`
223+ return t ( ' profile_fields ' , ' {fieldLabel } must be a plain numeric value.' , { fieldLabel: field . definition . label })
223224 }
224225
225226 if (field .definition .type === ' select' ) {
226227 const options = field .definition .options ?? []
227228 if (! options .includes (rawValue )) {
228- return ` ${ field . definition . label } must be one of the allowed options.`
229+ return t ( ' profile_fields ' , ' {fieldLabel } must be one of the allowed options.' , { fieldLabel: field . definition . label })
229230 }
230231 }
231232
@@ -282,7 +283,7 @@ export default defineComponent({
282283 clearRecord (userDraftVisibilities )
283284 editableFields .value .forEach (normaliseDraft )
284285 } catch (error ) {
285- errorMessage .value = error instanceof Error ? error .message : ' Could not load profile fields for this user.'
286+ errorMessage .value = error instanceof Error ? error .message : t ( ' profile_fields ' , ' Could not load profile fields for this user.' )
286287 } finally {
287288 isLoading .value = false
288289 }
@@ -305,10 +306,12 @@ export default defineComponent({
305306
306307 const formatFieldErrorMessage = (field : AdminEditableField , message : string ) => {
307308 return ({
308- ' text fields expect a scalar value' : ` ${field .definition .label } must be plain text. ` ,
309- ' number fields expect a numeric value' : ` ${field .definition .label } must be a numeric value. ` ,
310- ' current_visibility is not supported' : ' The selected visibility is not supported.' ,
311- }[message ] ?? (message .includes (' is not a valid option' ) ? ` ${field .definition .label }: invalid option selected. ` : ` ${field .definition .label }: ${message } ` ))
309+ ' text fields expect a scalar value' : t (' profile_fields' , ' {fieldLabel} must be plain text.' , { fieldLabel: field .definition .label }),
310+ ' number fields expect a numeric value' : t (' profile_fields' , ' {fieldLabel} must be a numeric value.' , { fieldLabel: field .definition .label }),
311+ ' current_visibility is not supported' : t (' profile_fields' , ' The selected visibility is not supported.' ),
312+ }[message ] ?? (message .includes (' is not a valid option' )
313+ ? t (' profile_fields' , ' {fieldLabel}: invalid option selected.' , { fieldLabel: field .definition .label })
314+ : t (' profile_fields' , ' {fieldLabel}: {message}' , { fieldLabel: field .definition .label , message })))
312315 }
313316
314317 const extractApiMessage = (error : unknown ) => {
@@ -349,7 +352,7 @@ export default defineComponent({
349352 }
350353
351354 if (! plainNumberPattern .test (rawValue )) {
352- throw new Error (' Numeric fields only accept plain numbers.' )
355+ throw new Error (t ( ' profile_fields ' , ' Numeric fields only accept plain numbers.' ) )
353356 }
354357
355358 const numericValue = Number (rawValue )
@@ -397,7 +400,7 @@ export default defineComponent({
397400 userValues .value = nextValues
398401 normaliseDraft ({ definition: field .definition , value: saved })
399402 } catch (error ) {
400- userValueErrors [fieldId ] = formatFieldErrorMessage (field , extractApiMessage (error ) ?? ' Could not save this field value. Please try again.' )
403+ userValueErrors [fieldId ] = formatFieldErrorMessage (field , extractApiMessage (error ) ?? t ( ' profile_fields ' , ' Could not save this field value. Please try again.' ) )
401404 } finally {
402405 savingIds .value = savingIds .value .filter ((value : number ) => value !== fieldId )
403406 }
@@ -429,9 +432,9 @@ export default defineComponent({
429432 }
430433 })
431434
432- errorMessage .value = invalidChangedFields .length === 1
433- ? ' Fix the invalid field before saving. '
434- : ' Fix the invalid fields before saving. '
435+ errorMessage .value = n ( ' profile_fields ' , ' Fix the invalid field before saving. ' , ' Fix the invalid fields before saving. ' , invalidChangedFields .length , {
436+ count: invalidChangedFields . length ,
437+ })
435438 return
436439 }
437440
@@ -441,11 +444,11 @@ export default defineComponent({
441444
442445 const hasFieldErrors = changedFields .some ((field : AdminEditableField ) => Boolean (userValueErrors [field .definition .id ]))
443446 if (! hasFieldErrors ) {
444- successMessage .value = ` Saved profile fields for ${ props .userUid }. `
447+ successMessage .value = t ( ' profile_fields ' , ' Saved profile fields for {userUid}. ' , { userUid: props .userUid })
445448 } else {
446- errorMessage .value = changedFields .length === 1
447- ? ' The field could not be saved. '
448- : ' Some fields could not be saved. Review the messages below. '
449+ errorMessage .value = n ( ' profile_fields ' , ' The field could not be saved. ' , ' Some fields could not be saved. Review the messages below. ' , changedFields .length , {
450+ count: changedFields . length ,
451+ })
449452 }
450453 }
451454
@@ -465,12 +468,13 @@ export default defineComponent({
465468 )
466469
467470 return {
471+ t ,
468472 closeDialog ,
469473 editableFields ,
470474 errorMessage ,
471475 headerDescription ,
472476 headerUserName ,
473- visibilityControlLabel ,
477+ loadingMessage ,
474478 hasPendingChanges ,
475479 hasInvalidFields ,
476480 helperTextForField ,
@@ -480,7 +484,6 @@ export default defineComponent({
480484 placeholderForField ,
481485 saveAllFields ,
482486 successMessage ,
483- title ,
484487 updateOpen ,
485488 updateVisibility ,
486489 clearFieldError ,
0 commit comments