Vue3 + vue-i18n 技术问题咨询:自动加载翻译等
Vue-I18n 常见问题解决方案
问题1:自动加载翻译文件
使用import.meta.glob自动加载locales下的翻译文件,核心是处理异步导入并整理成messages所需的键值对格式(键为语言标识,值为翻译内容)。
实现代码(src/i18n/index.ts)
import { createI18n } from 'vue-i18n' // 异步加载所有locale文件,使用glob的动态导入模式 const localeFiles = import.meta.glob('./locales/*.json', { eager: false }) async function loadMessages() { const messages: Record<string, any> = {} for (const path in localeFiles) { // 从文件路径提取语言标识(比如 ./locales/en.json → en) const lang = path.match(/\.\/locales\/(.*)\.json/)?.[1] if (lang) { // 加载文件内容 const module = await localeFiles[path]() messages[lang] = module.default } } return messages } // 初始化i18n export async function initI18n() { const messages = await loadMessages() return createI18n({ legacy: false, // Vue3推荐关闭legacy模式 locale: 'zh-CN', // 默认语言 fallbackLocale: 'en', messages }) }
注意事项
- 如果使用Vite的
eager: true模式,可同步加载,但大项目建议用异步模式配合懒加载; - 确保翻译文件命名规范(如
zh-CN.json、en.json),方便提取语言标识。
问题2:脚本中t函数动态更新
模板中的t是响应式绑定,但直接把useI18n返回的t赋值给ref会丢失响应性,且Vue3 setup中不存在this,必须通过useI18n获取实例。
正确实现方式
方式1:使用computed包裹
<script setup> import { useI18n, computed } from 'vue-i18n' const { t, locale } = useI18n() // 响应式获取翻译内容 const helloText = computed(() => t('hello')) // 切换语言示例 const switchLang = (lang: string) => { locale.value = lang } </script> <template> <div>{{ helloText }}</div> <button @click="switchLang('en')">English</button> </template>
方式2:直接在需要时调用t
如果是在方法中使用,直接调用t即可,因为t内部会监听语言变化:
<script setup> import { useI18n } from 'vue-i18n' const { t, locale } = useI18n() const showMessage = () => { alert(t('message.notice')) } </script>
问题3:翻译文件懒加载实现
当翻译文件体积大时,可通过按语言懒加载或按模块懒加载优化。
方案1:切换语言时懒加载对应文件
修改i18n初始化逻辑,默认只加载当前语言,切换时再加载目标语言:
// src/i18n/index.ts import { createI18n } from 'vue-i18n' const i18n = createI18n({ legacy: false, locale: 'zh-CN', fallbackLocale: 'en', messages: { 'zh-CN': await import('./locales/zh-CN.json').then(m => m.default) // 默认加载中文 } }) // 定义懒加载语言方法 export async function loadLocale(lang: string) { if (!i18n.global.availableLocales.includes(lang)) { const messages = await import(`./locales/${lang}.json`).then(m => m.default) i18n.global.setLocaleMessage(lang, messages) } i18n.global.locale.value = lang } export default i18n
方案2:按路由模块懒加载翻译
结合Vue Router的路由守卫,进入对应路由时加载模块专属翻译:
// router/index.ts import { loadLocale } from '@/i18n' import router from './router' router.beforeEach(async (to) => { // 假设路由meta中定义了需要加载的翻译模块 const localeModule = to.meta.localeModule if (localeModule) { const lang = router.app.config.globalProperties.$i18n.locale.value const messages = await import(`@/locales/modules/${localeModule}/${lang}.json`).then(m => m.default) router.app.config.globalProperties.$i18n.global.mergeLocaleMessage(lang, messages) } })
内容的提问来源于stack exchange,提问作者AlienLogic
相关产品推荐
相关产品推荐

