mirror of
https://github.com/directus/directus.git
synced 2026-02-02 01:25:00 -05:00
@@ -13,7 +13,8 @@ import {
|
||||
} from '@/stores';
|
||||
import { register as registerModules, unregister as unregisterModules } from '@/modules/register';
|
||||
|
||||
import { setLanguage, Language } from '@/lang';
|
||||
import { Language } from '@/lang';
|
||||
import { setLanguage } from '@/lang/set-language';
|
||||
|
||||
type GenericStore = {
|
||||
id: string;
|
||||
|
||||
@@ -7,19 +7,8 @@ import availableLanguages from './available-languages.yaml';
|
||||
import enUSBase from './translations/en-US.yaml';
|
||||
import dateFormats from './date-formats.yaml';
|
||||
|
||||
import { getModules } from '@/modules';
|
||||
import { getLayouts } from '@/layouts';
|
||||
import { getInterfaces } from '@/interfaces';
|
||||
import { getDisplays } from '@/displays';
|
||||
import { translate } from '@/utils/translate-object-values';
|
||||
|
||||
Vue.use(VueI18n);
|
||||
|
||||
const { modules, modulesRaw } = getModules();
|
||||
const { layouts, layoutsRaw } = getLayouts();
|
||||
const { interfaces, interfacesRaw } = getInterfaces();
|
||||
const { displays, displaysRaw } = getDisplays();
|
||||
|
||||
export const i18n = new VueI18n({
|
||||
locale: 'en-US',
|
||||
fallbackLocale: 'en-US',
|
||||
@@ -34,29 +23,6 @@ export type Language = keyof typeof availableLanguages;
|
||||
|
||||
export const loadedLanguages: Language[] = ['en-US'];
|
||||
|
||||
export async function setLanguage(lang: Language): Promise<boolean> {
|
||||
if (Object.keys(availableLanguages).includes(lang) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (loadedLanguages.includes(lang) === false) {
|
||||
const translations = await import(`@/lang/translations/${lang}.yaml`).catch((err) => console.warn(err));
|
||||
i18n.mergeLocaleMessage(lang, translations);
|
||||
loadedLanguages.push(lang);
|
||||
}
|
||||
|
||||
i18n.locale = lang;
|
||||
|
||||
(document.querySelector('html') as HTMLElement).setAttribute('lang', lang);
|
||||
|
||||
modules.value = translate(modulesRaw.value);
|
||||
layouts.value = translate(layoutsRaw.value);
|
||||
interfaces.value = translate(interfacesRaw.value);
|
||||
displays.value = translate(displaysRaw.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
|
||||
export function translateAPIError(error: RequestError | string) {
|
||||
|
||||
44
app/src/lang/set-language.ts
Normal file
44
app/src/lang/set-language.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import availableLanguages from './available-languages.yaml';
|
||||
import { i18n, Language, loadedLanguages } from './index';
|
||||
|
||||
import { getModules } from '@/modules';
|
||||
import { getLayouts } from '@/layouts';
|
||||
import { getInterfaces } from '@/interfaces';
|
||||
import { getDisplays } from '@/displays';
|
||||
import { translate } from '@/utils/translate-object-values';
|
||||
|
||||
import { useCollectionsStore, useFieldsStore } from '@/stores';
|
||||
|
||||
const { modules, modulesRaw } = getModules();
|
||||
const { layouts, layoutsRaw } = getLayouts();
|
||||
const { interfaces, interfacesRaw } = getInterfaces();
|
||||
const { displays, displaysRaw } = getDisplays();
|
||||
|
||||
export async function setLanguage(lang: Language): Promise<boolean> {
|
||||
const collectionsStore = useCollectionsStore();
|
||||
const fieldsStore = useFieldsStore();
|
||||
|
||||
if (Object.keys(availableLanguages).includes(lang) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (loadedLanguages.includes(lang) === false) {
|
||||
const translations = await import(`@/lang/translations/${lang}.yaml`).catch((err) => console.warn(err));
|
||||
i18n.mergeLocaleMessage(lang, translations);
|
||||
loadedLanguages.push(lang);
|
||||
}
|
||||
|
||||
i18n.locale = lang;
|
||||
|
||||
(document.querySelector('html') as HTMLElement).setAttribute('lang', lang);
|
||||
|
||||
modules.value = translate(modulesRaw.value);
|
||||
layouts.value = translate(layoutsRaw.value);
|
||||
interfaces.value = translate(interfacesRaw.value);
|
||||
displays.value = translate(displaysRaw.value);
|
||||
|
||||
collectionsStore.translateCollections();
|
||||
fieldsStore.translateFields();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -58,17 +58,15 @@ import { registerDisplays } from './displays/register';
|
||||
import App from './app.vue';
|
||||
|
||||
async function init() {
|
||||
const app = new Vue({
|
||||
render: (h) => h(App),
|
||||
router,
|
||||
i18n,
|
||||
});
|
||||
|
||||
await Promise.all([registerInterfaces(), registerDisplays(), registerLayouts(), loadModules()]);
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
app.$mount('#app');
|
||||
new Vue({
|
||||
render: (h) => h(App),
|
||||
router,
|
||||
i18n,
|
||||
}).$mount('#app');
|
||||
|
||||
console.timeEnd('🕓 Application Loaded');
|
||||
|
||||
|
||||
@@ -113,10 +113,17 @@
|
||||
</template>
|
||||
<template v-else-if="isNew === false && item">
|
||||
<div class="name type-label">
|
||||
{{ userName(item) }}<span v-if="item.title" class="title">, {{ item.title }}</span>
|
||||
{{ userName(item) }}
|
||||
<span v-if="item.title" class="title">, {{ item.title }}</span>
|
||||
</div>
|
||||
<div class="email">
|
||||
<v-icon name="alternate_email" small outline />
|
||||
{{ item.email }}
|
||||
</div>
|
||||
<div class="location" v-if="item.location">
|
||||
<v-icon name="place" small outline />
|
||||
{{ item.location }}
|
||||
</div>
|
||||
<div class="email"><v-icon name="alternate_email" small outline /> {{ item.email }}</div>
|
||||
<div class="location" v-if="item.location"><v-icon name="place" small outline /> {{ item.location }}</div>
|
||||
<v-chip :class="item.status" small v-if="roleName">{{ roleName }}</v-chip>
|
||||
</template>
|
||||
</div>
|
||||
@@ -169,7 +176,8 @@
|
||||
import { defineComponent, computed, toRefs, ref, watch } from '@vue/composition-api';
|
||||
|
||||
import UsersNavigation from '../components/navigation.vue';
|
||||
import { i18n, setLanguage } from '@/lang';
|
||||
import { i18n } from '@/lang';
|
||||
import { setLanguage } from '@/lang/set-language';
|
||||
import router from '@/router';
|
||||
import RevisionsDrawerDetail from '@/views/private/components/revisions-drawer-detail';
|
||||
import CommentsSidebarDetail from '@/views/private/components/comments-sidebar-detail';
|
||||
@@ -526,16 +534,16 @@ export default defineComponent({
|
||||
height: 112px;
|
||||
margin-bottom: var(--form-vertical-gap);
|
||||
padding: 20px;
|
||||
border-radius: calc(var(--border-radius) + 4px);
|
||||
background-color: var(--background-normal);
|
||||
border-radius: calc(var(--border-radius) + 4px);
|
||||
|
||||
.avatar {
|
||||
--v-icon-color: var(--foreground-subdued);
|
||||
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
margin-right: 16px;
|
||||
|
||||
@@ -32,8 +32,8 @@ export const useCollectionsStore = createStore({
|
||||
const collections: CollectionRaw[] = response.data.data;
|
||||
|
||||
this.state.collections = collections.map((collection: CollectionRaw) => {
|
||||
let name: string | VueI18n.TranslateResult;
|
||||
const icon = collection.meta?.icon || 'label';
|
||||
const name = formatTitle(collection.collection);
|
||||
|
||||
if (collection.meta && notEmpty(collection.meta.translations)) {
|
||||
for (let i = 0; i < collection.meta.translations.length; i++) {
|
||||
@@ -45,7 +45,22 @@ export const useCollectionsStore = createStore({
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...collection,
|
||||
name,
|
||||
icon,
|
||||
};
|
||||
});
|
||||
|
||||
this.translateCollections();
|
||||
},
|
||||
translateCollections() {
|
||||
this.state.collections = this.state.collections.map((collection: CollectionRaw) => {
|
||||
let name: string | VueI18n.TranslateResult;
|
||||
|
||||
if (i18n.te(`collection_names.${collection.collection}`)) {
|
||||
name = i18n.t(`collection_names.${collection.collection}`);
|
||||
} else {
|
||||
name = formatTitle(collection.collection);
|
||||
@@ -54,7 +69,6 @@ export const useCollectionsStore = createStore({
|
||||
return {
|
||||
...collection,
|
||||
name,
|
||||
icon,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -66,16 +66,16 @@ export const useFieldsStore = createStore({
|
||||
*/
|
||||
|
||||
this.state.fields = [...fields.map(this.parseField), fakeFilesField];
|
||||
|
||||
this.translateFields();
|
||||
},
|
||||
async dehydrate() {
|
||||
this.reset();
|
||||
},
|
||||
parseField(field: FieldRaw): Field {
|
||||
let name: string | VueI18n.TranslateResult;
|
||||
const name = formatTitle(field.field);
|
||||
|
||||
if (i18n.te(`fields.${field.collection}.${field.field}`)) {
|
||||
name = i18n.t(`fields.${field.collection}.${field.field}`);
|
||||
} else if (field.meta && notEmpty(field.meta.translations) && field.meta.translations.length > 0) {
|
||||
if (field.meta && notEmpty(field.meta.translations) && field.meta.translations.length > 0) {
|
||||
for (let i = 0; i < field.meta.translations.length; i++) {
|
||||
const { language, translation } = field.meta.translations[i];
|
||||
|
||||
@@ -87,10 +87,6 @@ export const useFieldsStore = createStore({
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
name = i18n.t(`fields.${field.collection}.${field.field}`);
|
||||
} else {
|
||||
name = formatTitle(field.field);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -98,6 +94,22 @@ export const useFieldsStore = createStore({
|
||||
name,
|
||||
};
|
||||
},
|
||||
translateFields() {
|
||||
this.state.fields = this.state.fields.map((field) => {
|
||||
let name: string | VueI18n.TranslateResult;
|
||||
|
||||
if (i18n.te(`fields.${field.collection}.${field.field}`)) {
|
||||
name = i18n.t(`fields.${field.collection}.${field.field}`);
|
||||
} else {
|
||||
name = formatTitle(field.field);
|
||||
}
|
||||
|
||||
return {
|
||||
...field,
|
||||
name,
|
||||
};
|
||||
});
|
||||
},
|
||||
async createField(collectionKey: string, newField: Field) {
|
||||
const stateClone = [...this.state.fields];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user