uni.setlocale在app端不生效是设计使然,仅修改原生层语言标识,不触发vue层翻译更新;需通过页面重载+重建i18n实例实现中英文切换。

uni.setLocale 在 App 端点不生效?不是 bug,是设计如此——它只改 native 层标识,不触发 Vue 层翻译更新。真要切换中英文,得靠页面重载 + i18n 实例重建。
uni.setLocale 为什么点了没反应
调用 uni.setLocale('en-US') 后,$t('hello') 还是中文,是因为:
-
uni.setLocale仅向原生层写入语言标识,App(iOS/Android)冷启动时才读取,热切换完全不联动 Vue 实例 -
uni.getSystemInfoSync().language返回的是系统语言,不是你设的;uni.getLocale()虽能读到设置值,但只是“存档”,不驱动响应式更新 - Vue 组件里用的
$t或useI18n().t(),全依赖初始化时传入的locale值,后续改i18n.locale = 'en'在 App 端无效(尤其 vue-i18n v9legacy: false模式下)
App 端中英文切换必须 reload 页面
核心动作不是“改 locale”,而是“让新 locale 生效”:清状态、重建实例、重绘所有组件。
- 切换前把语言 code 存进持久化存储:
uni.setStorageSync('lang', 'en-US') - 切换后立即执行:
uni.reLaunch({ url: '/pages/index/index' })(推荐)或uni.redirectTo,确保页面完全重建 - 在
main.js(Vue 2)或app.js(Vue 3)里,每次启动都读 storage 并 新建i18n实例,不要复用旧的 - 别把
i18n挂在Vue.prototype上——App 端页面重建后原型链断开,子组件拿不到实例
vue-i18n v9 的 legacy 配置陷阱
uni-app 3.x 默认适配 vue-i18n v9,但 legacy: true 和 false 行为差异极大,App 端尤其敏感:
- 必须显式声明
createI18n({ legacy: false, locale: savedLang }),否则useI18n()在子组件里返回空对象 -
locale.value = 'en-US'只在setup()内有效,模板里仍靠{{ $t('key') }}自动响应,不能手动调用t() - 避免在
onLoad里调用useI18n()——此时 i18n 实例还没初始化完成,拿到的是 undefined - 日期/数字格式不会随语言自动变,
new Date().toLocaleDateString()必须显式传参:toLocaleDateString(useI18n().locale.value)
语言包结构与动态加载建议
别把所有语言塞进一个大 JSON,App 启动慢、首屏卡顿:
- 按模块拆分,比如
home.js、profile.js、common.js,每个导出一个对象 - 首次只加载当前语言的全部模块,切换时用
i18n.mergeLocaleMessage('en-US', { home: {...} })动态合并 - 中文推荐用
zh-Hans(简体),英文用en-US,避免用zh或en这类模糊码,防止 iOS/Android 解析歧义 - tabBar 文字国际化需单独处理:在
pages.json中用"text": "$t:tabBar.home"不生效,得用uni.setTabBarItem手动设
最易被忽略的一点:App 端切换语言后,uni.chooseImage、uni.showModal 等原生弹窗的按钮文字(如“取消”“确定”)仍是系统语言——它们由 OS 控制,uni.setLocale 对其无影响,只能接受这个事实。











