feat: i18n locales lazy loading (#482)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
This commit is contained in:
Martin DONADIEU 2023-03-27 18:17:23 +08:00 committed by GitHub
parent 2c00f8ba6d
commit c75bb79786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 429 additions and 511 deletions

View File

@ -13,7 +13,8 @@
"test:unit": "vitest",
"typecheck": "vue-tsc --noEmit",
"up": "taze major -I",
"postinstall": "npx simple-git-hooks"
"postinstall": "npx simple-git-hooks",
"sizecheck": "npx vite-bundle-visualizer"
},
"dependencies": {
"@unocss/reset": "^0.50.6",
@ -55,6 +56,7 @@
"unplugin-vue-components": "^0.24.1",
"unplugin-vue-macros": "^1.10.1",
"vite": "^4.2.0",
"vite-bundle-visualizer": "^0.6.0",
"vite-plugin-inspect": "^0.7.17",
"vite-plugin-pages": "^0.29.0",
"vite-plugin-pwa": "^0.14.4",

File diff suppressed because it is too large Load Diff

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>

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')
}