You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
import type { App } from 'vue'
|
|
import type { I18nOptions, Locale } from 'vue-i18n'
|
|
import { createI18n } from 'vue-i18n'
|
|
import { storeToRefs } from 'pinia'
|
|
import { localesMap } from './config'
|
|
|
|
const loadedLocalePool: string[] = []
|
|
|
|
// eslint-disable-next-line import/no-mutable-exports
|
|
export let i18n: ReturnType<typeof createI18n>
|
|
|
|
async function createI18nOptions(): Promise<I18nOptions> {
|
|
// saved locale
|
|
const localeStore = useLocaleStore()
|
|
const { fallback, availableLocales, getLocale } = storeToRefs(localeStore)
|
|
const locale = getLocale.value
|
|
|
|
return {
|
|
legacy: false,
|
|
locale,
|
|
fallbackLocale: unref(fallback),
|
|
messages: {},
|
|
availableLocales: unref(availableLocales),
|
|
sync: true,
|
|
silentTranslationWarn: false,
|
|
missingWarn: false,
|
|
silentFallbackWarn: true,
|
|
}
|
|
}
|
|
|
|
export function setI18nLanguage(lang: Locale) {
|
|
i18n.global.locale = lang
|
|
if (typeof document !== 'undefined') {
|
|
document.querySelector('html')?.setAttribute('lang', lang)
|
|
}
|
|
return lang
|
|
}
|
|
|
|
export async function loadLanguageAsync(lang: string): Promise<Locale> {
|
|
// If the same language
|
|
if (i18n.global.locale === lang) {
|
|
return setI18nLanguage(lang)
|
|
}
|
|
|
|
// If the language was already loaded
|
|
if (loadedLocalePool.includes(lang)) {
|
|
return setI18nLanguage(lang)
|
|
}
|
|
|
|
// If the language hasn't been loaded yet
|
|
const messages = await localesMap[lang]()
|
|
i18n.global.setLocaleMessage(lang, messages.default)
|
|
|
|
loadedLocalePool.push(lang)
|
|
|
|
return setI18nLanguage(lang)
|
|
}
|
|
|
|
export async function setupI18n(app: App) {
|
|
const options = await createI18nOptions()
|
|
i18n = createI18n(options)
|
|
await loadLanguageAsync(options.locale!)
|
|
|
|
app.use(i18n)
|
|
}
|