Vue 2 项目必须用 @dcloudio/uni-i18n,Vue 3 项目推荐用 vue-i18n@9.1.9;需同步调用 uni.setLocale 和 i18n.locale 并持久化 locale 值,语言包应按模块拆分、统一键名,tabbar 和原生组件需手动更新文案。

uni-app 里该用 @dcloudio/uni-i18n 还是 vue-i18n?
直接结论:Vue 2 项目必须用 @dcloudio/uni-i18n;Vue 3 项目推荐用 vue-i18n@9.1.9(官方指定兼容版本),别装最新版——否则 onLocaleChange 不触发、uni.setLocale 失效、热更新后语言回退,全是版本错配惹的祸。
原因很简单:@dcloudio/uni-i18n 是 DCloud 官方 fork 并深度适配 uni-app 生命周期(比如小程序 onShow、App.vue 的 locale 变更监听)的分支;而原生 vue-i18n 默认不感知 uni.onLocaleChange,也不自动同步 uni.getLocale() 的变化。
- Vue 2 项目装
vue-i18n→this.$t能用,但切换语言后 tabbar、下拉刷新文案、甚至部分组件内部文本不更新 - Vue 3 项目装
vue-i18n@10+→ 控制台报TypeError: i18n.__VUE_I18N_BRIDGE__ is not defined,App 启动白屏 - 正确姿势:
npm install @dcloudio/uni-i18n(Vue 2)或npm install vue-i18n@9.1.9(Vue 3)
uni.setLocale 和 i18n.locale 到底谁管用?
两者都得用,但职责不同:前者改「应用级语言状态」并触发 uni.onLocaleChange 回调,后者只改 i18n 实例的当前 locale —— 如果只改 i18n.locale,uni.getLocale() 仍返回旧值,下次冷启动、分享卡片、甚至某些平台(如支付宝小程序)会直接 fallback 到系统语言。
实操时必须同步更新:
- 调用
uni.setLocale('en-US')→ 确保全局 API(如uni.showModal的 confirmText)也走新语言 - 再设
i18n.locale = 'en-US'→ 让$t、$tc等方法立刻生效 - 务必搭配
uni.setStorageSync('locale', 'en-US')→ 否则用户重启 App 又变回中文
漏掉任意一环,就会出现「界面上文字切了,但 uni.showToast 的按钮还是中文」这类诡异问题。
语言包结构怎么组织才不踩坑?
别把所有翻译塞进一个 zh-Hans.json。uni-app 在分包加载、热重载时对大 JSON 文件敏感,超过 200KB 容易卡顿或白屏;而且中英文键名不一致时,$t('user.name') 在 en 包里写成 "userName" 就直接 fallback 到 key 本身,界面显示 user.name。
推荐按模块拆分 + 统一键名规范:
- 路径统一放
locales/zh-Hans/user.js、locales/en-US/user.js,用require动态合并(Vue 2)或defineI18nLocale(Vue 3) - 所有语言包用完全相同的 key 结构,比如都叫
user.fullName,而不是中文用用户全名、英文用full_name - 避免在语言包里写逻辑,比如
"price": "{value} 元 (¥{value})"→ 应拆成"price": "{value} {unit}"+ 单独传参,否则无法做货币本地化
tabbar、原生组件、第三方 UI 库怎么一起切语言?
tabbar 文字不是 Vue 模板,$t 失效;uni.showToast、uni.chooseImage 等原生弹窗文案由客户端控制;Wot Design、uView 等 UI 库也有自己的 locale 配置 —— 光改 i18n.locale 是远远不够的。
必须手动联动:
- 切换语言后立刻调用
uni.setTabBarItem({ text: this.$t('tabbar.home') }),且需遍历所有 tab 项 - 封装一个
showToast方法,内部根据当前i18n.locale映射按钮文案:confirmText: this.$t('common.confirm') - UI 库如 wot-design-uni,要显式调用
Locale.use(i18n.global.locale.value),否则其内部DatePicker的月份名仍是中文
最容易被忽略的是:iOS 微信小程序里,uni.chooseImage 的「取消」「确定」按钮永远是系统语言,根本切不了——这不是 bug,是微信限制,文档里白纸黑字写着「原生选择器文案不可自定义」。

















