feat: i18n locales lazy loading (#482)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
This commit is contained in:
Martin DONADIEUandAnthony Fu authored and GitHub committed 2023-03-27 12:17:23 +02:00
1 parent 2c00f8ba6d
commit c75bb79786
4 files changed
+429 -511

No files matched your search

+7 -3
View File
@@ -1,10 +1,14 @@
<script setup lang="ts">
const { t, availableLocales, locale } = useI18n()
import { availableLocales, loadLanguageAsync } from '~/modules/i18n'
const toggleLocales = () => {
const { t, locale } = useI18n()
const toggleLocales = async () => {
// change to some real logic
const locales = availableLocales
locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length]
const newLocale = locales[(locales.indexOf(locale.value) + 1) % locales.length]
await loadLanguageAsync(newLocale)
locale.value = newLocale
}
</script>
+39 -14
View File
@@ -1,3 +1,4 @@
import type { Locale } from 'vue-i18n'
import { createI18n } from 'vue-i18n'
import { type UserModule } from '~/types'
@@ -5,21 +6,45 @@ import { type UserModule } from '~/types'
// https://vitejs.dev/guide/features.html#glob-import
//
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
const messages = Object.fromEntries(
Object.entries(
import.meta.glob<{ default: any }>('../../locales/*.y(a)?ml', { eager: true }))
.map(([key, value]) => {
const yaml = key.endsWith('.yaml')
return [key.slice(14, yaml ? -5 : -4), value.default]
}),
)
const i18n = createI18n({
legacy: false,
locale: '',
messages: {},
})
const localesMap = Object.fromEntries(
Object.entries(import.meta.glob('../../locales/*.yml'))
.map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]),
) as Record<Locale, () => Promise<{ default: Record<string, string> }>>
export const availableLocales = Object.keys(localesMap)
const loadedLanguages: string[] = []
function setI18nLanguage(lang: Locale) {
i18n.global.locale.value = lang as any
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.value === lang)
return setI18nLanguage(lang)
// If the language was already loaded
if (loadedLanguages.includes(lang))
return setI18nLanguage(lang)
// If the language hasn't been loaded yet
const messages = await localesMap[lang]()
i18n.global.setLocaleMessage(lang, messages.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
}
export const install: UserModule = ({ app }) => {
const i18n = createI18n({
legacy: false,
locale: 'en',
messages,
})
app.use(i18n)
loadLanguageAsync('en')
}