vue全局国际化通过provide注入symbol键的响应式i18n实例,inject安全获取并封装usei18n组合函数,locale与messages须响应式包装,t函数依赖unref读取,动态加载语言包并兜底缺失键。

Vue 依赖注入实现全局国际化语言切换并保证子孙组件实时响应,核心在于 provide 注入响应式 i18n 实例 + inject 安全获取 + 翻译逻辑绑定响应式状态。它不靠 props 透传,也不用事件总线或全局变量,而是让整个组件树共享同一份可追踪、可更新的语言上下文。
用 provide 注入 reactive 的 i18n 对象
在应用初始化时(如 main.js 或 app.ts),创建一个包含 locale、messages 和 t 函数的响应式对象,并通过 app.provide 注入:
- 推荐用
reactive({ locale: ref('zh'), messages: ref({}) })或直接reactive({ locale: 'zh', messages: {} })—— 关键是整个对象或其属性必须被响应式包装 - 提供 key 建议用
Symbol('i18n')避免命名冲突,例如:const I18N_KEY = Symbol('i18n') - 调用
app.provide(I18N_KEY, i18n),其中i18n是封装好的响应式对象
在子孙组件中用 inject 获取并使用
任意后代组件(包括 setup、script setup、甚至函数式组件)都能安全拿到该实例:
- 写法示例:
const i18n = inject(I18N_KEY, null),后续加非空判断再使用 - 更推荐封装成组合式函数:
useI18n()内部统一 inject 并返回{ t, locale, setLocale } - 模板中可直接用
{{ i18n.t('login') }},或配合 computed 包一层:const msg = computed(() => i18n.t('welcome'))
确保语言切换真正触发视图更新
切换语言不是简单赋值,必须维持响应链完整:
- 错误做法:
i18n.locale = 'en'(若 locale 是普通字符串属性,无响应) - 正确做法:locale 是
ref('zh'),则调用i18n.locale.value = 'en';或 locale 在 reactive 对象里,如i18n.state.locale = 'en' - t 函数内部需用
unref或.value读取响应式数据,确保 key 变化或 locale 变化时重新执行
语言包本身也要响应式加载
静态对象无法触发更新,动态语言包需通过 ref/reactive 管理:
- 异步加载示例:
messages.value = await import(`./locales/${locale.value}.json`) - 缺失键兜底处理:
messages.value?.[locale.value]?.[key] || key,避免页面空白 - 不建议在 computed 中硬编码语言对象(如
{ zh: { a: 'x' } }[locale]),那会切断响应追踪
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











