diff --git a/api/src/database/system-data/fields/collections.yaml b/api/src/database/system-data/fields/collections.yaml index 5ff74b85a5..637ac47a54 100644 --- a/api/src/database/system-data/fields/collections.yaml +++ b/api/src/database/system-data/fields/collections.yaml @@ -64,7 +64,23 @@ fields: interface: system-language width: half - field: translation - name: translation + name: Collection Name + type: string + meta: + interface: text-input + width: half + options: + placeholder: Enter a translation... + - field: singular + name: Singular Unit + type: string + meta: + interface: text-input + width: half + options: + placeholder: Enter a translation... + - field: plural + name: Plural Unit type: string meta: interface: text-input diff --git a/app/src/displays/related-values/related-values.vue b/app/src/displays/related-values/related-values.vue index 9931835ce4..9866cae0d6 100644 --- a/app/src/displays/related-values/related-values.vue +++ b/app/src/displays/related-values/related-values.vue @@ -7,8 +7,11 @@ > @@ -31,6 +34,7 @@ import { defineComponent, computed, PropType, Ref } from '@vue/composition-api'; import getRelatedCollection from '@/utils/get-related-collection'; import useCollection from '@/composables/use-collection'; import ValueNull from '@/views/private/components/value-null'; +import { i18n } from '@/lang'; export default defineComponent({ components: { ValueNull }, @@ -71,7 +75,25 @@ export default defineComponent({ return props.template || `{{ ${primaryKeyField.value!.field} }}`; }); - return { relatedCollection, primaryKeyField, getLinkForItem, _template }; + const unit = computed(() => { + if (Array.isArray(props.value)) { + if (props.value.length === 1) { + if (i18n.te(`collection_names_singular.${relatedCollection.value}`)) { + return i18n.t(`collection_names_singular.${relatedCollection.value}`); + } else { + return i18n.t('item'); + } + } else { + if (i18n.te(`collection_names_plural.${relatedCollection.value}`)) { + return i18n.t(`collection_names_plural.${relatedCollection.value}`); + } else { + return i18n.t('items'); + } + } + } + }); + + return { relatedCollection, primaryKeyField, getLinkForItem, _template, unit }; function getLinkForItem(item: any) { if (!relatedCollection.value || !primaryKeyField.value) return null; diff --git a/app/src/lang/translations/en-US.yaml b/app/src/lang/translations/en-US.yaml index 08d3a5c2a6..59f4f9c020 100644 --- a/app/src/lang/translations/en-US.yaml +++ b/app/src/lang/translations/en-US.yaml @@ -483,6 +483,8 @@ operators: has: Contains some of these keys loading: Loading... drop_to_upload: Drop to Upload +item: Item +items: Items upload_file: Upload File upload_file_indeterminate: Uploading File... upload_file_success: File Uploaded @@ -602,6 +604,8 @@ adding_user: Adding User unknown_user: Unknown User creating_in: 'Creating Item in {collection}' editing_in: 'Editing Item in {collection}' +creating_unit: 'Creating {unit}' +editing_unit: 'Editing {unit}' editing_in_batch: 'Batch Editing {count} Items' no_options_available: No options available settings_data_model: Data Model @@ -690,7 +694,7 @@ fields: display_template: Display Template hidden: Hidden singleton: Singleton - translations: Collection Name Translations + translations: Collection Naming Translations archive_app_filter: Archive App Filter archive_value: Archive Value unarchive_value: Unarchive Value diff --git a/app/src/modules/collections/routes/item.vue b/app/src/modules/collections/routes/item.vue index a60c031e6c..7106ac8b81 100644 --- a/app/src/modules/collections/routes/item.vue +++ b/app/src/modules/collections/routes/item.vue @@ -299,6 +299,12 @@ export default defineComponent({ const leaveTo = ref(null); const title = computed(() => { + if (i18n.te(`collection_names_singular.${props.collection}`)) { + return isNew.value + ? i18n.t('creating_unit', { unit: i18n.t(`collection_names_singular.${props.collection}`) }) + : i18n.t('editing_unit', { unit: i18n.t(`collection_names_singular.${props.collection}`) }); + } + return isNew.value ? i18n.t('creating_in', { collection: collectionInfo.value?.name }) : i18n.t('editing_in', { collection: collectionInfo.value?.name }); diff --git a/app/src/stores/collections.ts b/app/src/stores/collections.ts index a60c19b978..975492d8b6 100644 --- a/app/src/stores/collections.ts +++ b/app/src/stores/collections.ts @@ -37,12 +37,18 @@ export const useCollectionsStore = createStore({ if (collection.meta && notEmpty(collection.meta.translations)) { for (let i = 0; i < collection.meta.translations.length; i++) { - const { language, translation } = collection.meta.translations[i]; + const { language, translation, singular, plural } = collection.meta.translations[i]; i18n.mergeLocaleMessage(language, { collection_names: { [collection.collection]: translation, }, + collection_names_singular: { + [collection.collection]: singular, + }, + collection_names_plural: { + [collection.collection]: plural, + }, }); } } diff --git a/app/src/types/collections.ts b/app/src/types/collections.ts index e13e620e56..7e670cfbab 100644 --- a/app/src/types/collections.ts +++ b/app/src/types/collections.ts @@ -3,6 +3,8 @@ import VueI18n from 'vue-i18n'; type Translations = { language: string; translation: string; + singular: string; + plural: string; }; export interface CollectionRaw { diff --git a/app/src/views/private/components/drawer-item/drawer-item.vue b/app/src/views/private/components/drawer-item/drawer-item.vue index dde2388079..b46cdeed6c 100644 --- a/app/src/views/private/components/drawer-item/drawer-item.vue +++ b/app/src/views/private/components/drawer-item/drawer-item.vue @@ -122,15 +122,18 @@ export default defineComponent({ const { info: collectionInfo } = useCollection(collection); const title = computed(() => { - if (props.primaryKey === '+') { - return i18n.t('creating_in', { - collection: junctionRelatedCollectionInfo?.value?.name || collectionInfo.value?.name, - }); + const collection = junctionRelatedCollectionInfo?.value || collectionInfo.value!; + const isNew = props.primaryKey === '+'; + + if (i18n.te(`collection_names_singular.${collection.collection}`)) { + return isNew + ? i18n.t('creating_unit', { unit: i18n.t(`collection_names_singular.${collection.collection}`) }) + : i18n.t('editing_unit', { unit: i18n.t(`collection_names_singular.${collection.collection}`) }); } - return i18n.t('editing_in', { - collection: junctionRelatedCollectionInfo?.value?.name || collectionInfo.value?.name, - }); + return isNew + ? i18n.t('creating_in', { collection: collection.name }) + : i18n.t('editing_in', { collection: collection.name }); }); const showDivider = computed(() => {