diff --git a/front/package.json b/front/package.json index e8a067306..e8e83853c 100644 --- a/front/package.json +++ b/front/package.json @@ -47,6 +47,7 @@ "universal-cookie": "4.0.4", "vue": "3.2.45", "vue-gettext": "2.1.12", + "vue-i18n": "9", "vue-router": "4.1.6", "vue-upload-component": "3.1.6", "vue-virtual-scroller": "2.0.0-beta.3", @@ -59,7 +60,7 @@ }, "devDependencies": { "@intlify/eslint-plugin-vue-i18n": "^2.0.0", - "@intlify/vite-plugin-vue-i18n": "^6.0.1", + "@intlify/vite-plugin-vue-i18n": "^6.0.3", "@types/diff": "5.0.2", "@types/dompurify": "2.4.0", "@types/howler": "2.2.7", diff --git a/front/src/components/Sidebar.vue b/front/src/components/Sidebar.vue index 3062e01d4..c896c37fe 100644 --- a/front/src/components/Sidebar.vue +++ b/front/src/components/Sidebar.vue @@ -2,7 +2,7 @@ import type { RouteRecordName } from 'vue-router' import { computed, ref, watch, watchEffect, onMounted } from 'vue' -import { SUPPORTED_LOCALES } from '~/init/locale' +import { setI18nLanguage, SUPPORTED_LOCALES } from '~/init/locale' import { useCurrentElement } from '@vueuse/core' import { setupDropdown } from '~/utils/fomantic' import { useRoute } from 'vue-router' @@ -32,7 +32,7 @@ defineProps() const store = useStore() const { theme } = useTheme() const themes = useThemeList() -const { t } = useI18n() +const { t, locale: i18nLocale } = useI18n() const route = useRoute() const isCollapsed = ref(true) @@ -101,9 +101,14 @@ const moderationNotifications = computed(() => + store.state.ui.notifications.pendingReviewRequests ) +const showLanguageModal = ref(false) +const locale = ref(i18nLocale.value) +watch(locale, (locale) => { + // setI18nLanguage(locale) +}) + const isProduction = import.meta.env.PROD const showUserModal = ref(false) -const showLanguageModal = ref(false) const showThemeModal = ref(false) const el = useCurrentElement() @@ -291,7 +296,7 @@ onMounted(() => { > -import { SUPPORTED_LOCALES } from '~/init/locale' +import { SUPPORTED_LOCALES, setI18nLanguage } from '~/init/locale' import { useI18n } from 'vue-i18n' import { computed } from 'vue' @@ -50,7 +50,7 @@ const labels = computed(() => ({ :key="key" :class="[{'active': $i18n.locale === key},'item']" :value="key" - @click="$i18n.locale = key" + @click="setI18nLanguage(key)" >{{ language }} diff --git a/front/src/init/locale.ts b/front/src/init/locale.ts index 613221085..5eabfb15c 100644 --- a/front/src/init/locale.ts +++ b/front/src/init/locale.ts @@ -9,9 +9,13 @@ import store from '~/store' import useLogger from '~/composables/useLogger' +import en from '../locales/en.json' + +const localeFactory = import.meta.glob('../locales/*.json') + const logger = useLogger() -const defaultLanguage = store.state.ui.currentLanguage ?? 'en_US' +const defaultLanguage = store.state.ui.currentLanguage ?? 'en' export const SUPPORTED_LOCALES = locales.reduce((map: Record, locale) => { map[locale.code] = locale.label return map @@ -22,22 +26,32 @@ export const i18n = createI18n({ globalInjection: true, fallbackLocale: 'en', legacy: false, - locale: 'en' + locale: 'en', + messages: { en } }) export const setI18nLanguage = async (locale: string) => { + console.debug(0) + if (locale === 'en') { + return + } + + console.debug(1) if (!Object.keys(SUPPORTED_LOCALES).includes(locale)) { throw new Error(`Unsupported locale: ${locale}`) } + console.debug(2) // load locale messages if (!i18n.global.availableLocales.includes(locale)) { try { - const { default: messages } = await import(`./locales/${locale}.json`) + console.debug(3) + const { default: messages } = await localeFactory[`../locales/${locale}.json`]() i18n.global.setLocaleMessage(locale, messages) await nextTick() } catch (error) { logger.warn(`Unsupported locale: ${locale}`) + logger.debug(error) } } @@ -72,6 +86,7 @@ export const install: InitModule = async ({ store, app }) => { // Handle language change watch(() => store.state.ui.currentLanguage, async (locale) => { + console.debug(locale) await store.dispatch('ui/currentLanguage', locale) await setI18nLanguage(locale) // TODO (wvffle): Set moment locale diff --git a/front/src/locales/en.json b/front/src/locales/en.json index 7ab2ee781..ecf5136db 100644 --- a/front/src/locales/en.json +++ b/front/src/locales/en.json @@ -196,7 +196,7 @@ "fediverse": { "title": "Fediverse object", "fieldLabel": "Fediverse object", - "fieldPlaceholder": "@username@example.com" + "fieldPlaceholder": "{'@'}username{'@'}example.com" } }, "header": { @@ -457,7 +457,7 @@ } }, "LibraryFollowButton": { - "button": { + "button": { "unfollow": "Unfollow", "cancel": "Cancel follow request", "follow": "Follow" @@ -1125,7 +1125,7 @@ "performAction": "Perform actions" }, "modal": { - "performAction": { + "performAction": { "header": "Do you want to launch {action} on {count} element? | Do you want to launch {action} on {count} elements?", "content": { "warning": "This may affect a lot of elements or have irreversible consequences, please double check this is really what you want." @@ -1309,7 +1309,7 @@ "favorites": "No favorites | {count} favorite | {count} favorites" }, "empty": { - "noFavorites": "No tracks have been added to your favorites yet" + "noFavorites": "No tracks have been added to your favorites yet" }, "ordering": { "label": "Ordering", @@ -1534,7 +1534,7 @@ "filter": "Remove filter" }, "message": { - "filter": "You are currently hiding content related to this artist." + "filter": "You are currently hiding content related to this artist." }, "link": { "filter": "Review my filters" @@ -3547,7 +3547,7 @@ }, "activity": { "firstSeen": "First seen", - "followers": "Followers" + "followers": "Followers" }, "audioContent": { "cachedSize": "Cached size", @@ -3576,7 +3576,7 @@ "delete": { "header": "Delete this tag?", "content": { - "warning": "The tag will be removed and unlinked from any existing entity. This action is irreversible." + "warning": "The tag will be removed and unlinked from any existing entity. This action is irreversible." } } @@ -3652,11 +3652,11 @@ "local": "Local", "uploadData": "Upload data", "activity": "Activity", - "audioContent": "Audio content" + "audioContent": "Audio content" }, "button": { "download": "Download", - "delete": "Delete" + "delete": "Delete" }, "link": { "django": "View in Django's admin", @@ -4005,7 +4005,7 @@ } }, "Plugins": { - "title": "Manage plugins" + "title": "Manage plugins" }, "ProfileActivity": { "header": { diff --git a/front/yarn.lock b/front/yarn.lock index bc73cdbed..2e452f9e0 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -1068,7 +1068,7 @@ resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.3.0-beta.10.tgz#e1e6c99b0f0a039e8fadc319b93314056f8e992e" integrity sha512-h93uAanbAt/XgjDHclrVB7xix6r7Uz11wx0iGNOCdHP7aA2LCJjUT3uNbekJjjbo+Fl5jzTSJZdm2SexzoqhRA== -"@intlify/vite-plugin-vue-i18n@^6.0.1": +"@intlify/vite-plugin-vue-i18n@^6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@intlify/vite-plugin-vue-i18n/-/vite-plugin-vue-i18n-6.0.3.tgz#57a6900de02a9829e52b16bf072768534c7664ef" integrity sha512-6SgNzPAOCR90wvt368lKzi7f/5ZEWJn22UCGvhFsP3XvKqlF3cVzojahgQ6o+LTdCkExeM6wPgd+haFf28E9VQ== @@ -1849,7 +1849,7 @@ "@vue/compiler-dom" "3.2.45" "@vue/shared" "3.2.45" -"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.4.5": +"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.2.1", "@vue/devtools-api@^6.4.5": version "6.4.5" resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.4.5.tgz#d54e844c1adbb1e677c81c665ecef1a2b4bb8380" integrity sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ== @@ -5223,6 +5223,16 @@ vue-gettext@2.1.12: resolved "https://registry.yarnpkg.com/vue-gettext/-/vue-gettext-2.1.12.tgz#444d3220149b17fa4c7caeded3f12d439b698f33" integrity sha512-7Kw36xtKvARp8ZafQGPK9WR6EM+dhFUikR5f0+etSkiHuvUM3yf1HsRDLYoLLdJ0AMaXxKwgekumzvCk6KX8rA== +vue-i18n@9: + version "9.2.2" + resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.2.2.tgz#aeb49d9424923c77e0d6441e3f21dafcecd0e666" + integrity sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ== + dependencies: + "@intlify/core-base" "9.2.2" + "@intlify/shared" "9.2.2" + "@intlify/vue-devtools" "9.2.2" + "@vue/devtools-api" "^6.2.1" + vue-observe-visibility@^2.0.0-alpha.1: version "2.0.0-alpha.1" resolved "https://registry.yarnpkg.com/vue-observe-visibility/-/vue-observe-visibility-2.0.0-alpha.1.tgz#1e4eda7b12562161d58984b7e0dea676d83bdb13"