diff --git a/assets/modules/i18n.ts b/assets/modules/i18n.ts index e632a943..a3fc733a 100644 --- a/assets/modules/i18n.ts +++ b/assets/modules/i18n.ts @@ -1,22 +1,45 @@ import { type App } from "vue"; import { createI18n } from "vue-i18n"; import { locale } from "@/stores/settings"; +import type { Locale } from "vue-i18n"; -import messages from "@intlify/unplugin-vue-i18n/messages"; +const localesMap = Object.fromEntries( + Object.entries(import.meta.glob("../../locales/*.yml")).map(([path, loadLocale]) => [ + path.match(/([\w-]*)\.yml$/)?.[1], + loadLocale, + ]), +) as Record Promise<{ default: Record }>>; -const defaultLocale = messages?.hasOwnProperty(navigator.language) - ? navigator.language - : navigator.language.slice(0, 2); +export const availableLocales = Object.keys(localesMap); + +function setI18nLanguage(lang: Locale) { + i18n.global.locale.value = lang; + return lang; +} + +const loadedLanguages: string[] = []; +async function loadLanguage(lang: string): Promise { + if (i18n.global.locale.value === lang) return setI18nLanguage(lang); + if (loadedLanguages.includes(lang)) return setI18nLanguage(lang); + + const messages = await localesMap[lang](); + i18n.global.setLocaleMessage(lang, messages.default); + loadedLanguages.push(lang); + return setI18nLanguage(lang); +} const i18n = createI18n({ legacy: false, - locale: locale.value || defaultLocale, - fallbackLocale: "en", - messages, + locale: "", + messages: {}, }); -watch(locale, (value) => { - i18n.global.locale.value = value || defaultLocale; +watchEffect(() => { + loadLanguage( + locale.value || + [navigator.language, navigator.language.slice(0, 2)].find((l) => availableLocales.includes(l)) || + "en", + ); }); export const install = (app: App) => app.use(i18n); diff --git a/assets/pages/settings.vue b/assets/pages/settings.vue index f32d0d6d..9c4c5932 100644 --- a/assets/pages/settings.vue +++ b/assets/pages/settings.vue @@ -156,7 +156,9 @@ import { locale, } from "@/stores/settings"; -const { t, availableLocales } = useI18n(); +import { availableLocales } from "@/modules/i18n"; + +const { t } = useI18n(); setTitle(t("title.settings")); const { latest, hasUpdate } = useReleases();