App端多语言初始化必须在plusready事件后读取plus.os.language并持久化,避免uni.getLocale()不准;切换语言需storage存储+uni.reLaunch重启生效,且pages.json中tabBar等需按lang字段静态配置多套。

uni-app 的 App 端(5+ Runtime)多语言配置,不能只靠 uni.getLocale() 初始化就完事——它在首次冷启动时可能不准,且后续切换语言会强制重启,必须提前设计持久化和平台适配逻辑。
App 启动时怎么拿到真实系统语言
在 App(Android/iOS)中,uni.getLocale() 早期可能返回空或错误值,因为 5+ Runtime 的 plus.os.language 需等 plusready 事件触发后才可用;而 uni.getSystemInfo().language 又常 fallback 到宿主环境(如微信客户端语言),不反映手机设置。
- 必须监听
plusready事件后再读取:用document.addEventListener('plusready', () => { const lang = plus.os.language; }) - 推荐封装一个同步获取函数,在
main.js顶部调用:function getRealAppLocale() { if (typeof plus !== 'undefined' && plus.os) { return plus.os.language.replace('_', '-'); // 如 'zh_CN' → 'zh-CN' } return uni.getLocale() || 'zh-CN'; } - 不要在
onLaunch里直接require语言包——异步时机不可控,容易导致页面首次渲染用默认 locale 渲染后无法刷新
语言切换为什么 App 会重启,怎么避免闪退感
调用 uni.setLocale('en-US') 在 Android 上会触发整个应用重启,这是 5+ Runtime 的底层限制,iOS 和小程序则不会。这意味着你不能指望“点一下按钮立刻翻译生效”。
- 用户切换语言后,应主动提示“设置已保存,稍后重启生效”,或跳转到一个空白 loading 页,再
uni.reLaunch到首页 - 别在
onShow或onLoad中反复调用this.$i18n.locale = xxx——App 重启后 Vue 实例重建,该赋值无效 - 真正生效的时机只有两个:首次初始化 i18n 实例前、或重启后重新挂载时。所以语言变更必须写入本地存储,并在
main.js最早阶段读取
语言包命名和 messages 键名必须严格匹配
uni-app 对语言标识符大小写和连字符敏感,uni.getLocale() 返回的是 zh-Hans,但如果你的 messages 里写的是 'zh-HANS' 或 'zh_Hans',就会 fallback 到默认语言,甚至报错找不到 key。
- 语言 JSON 文件名必须与
messages中的键名完全一致,包括大小写:zh-Hans.json对应messages['zh-Hans'] - 繁体常见有
zh-Hant和zh-HK两种,需按实际返回值区分;iOS 可能返回zh-Hant-HK,此时要手动截断或映射:const locale = uni.getLocale(); const normalized = locale.split('-')[0] === 'zh' ? locale.replace(/-Hant.*/, '-Hant') : locale; - App 打包后首次运行语言正确、杀进程重进变英文?大概率是没持久化——每次重启都走
uni.getLocale(),而该 API 在未触发 plusready 前返回空字符串,fallback 成了默认zh-CN或en-US
tabBar、navigationBarTitleText 这些框架层文本怎么国际化
这些不是组件内 $t() 能覆盖的,必须在 pages.json 中通过 "lang" 字段声明支持的语言,并配合对应语言的 tabBar 和 navigationBarTitleText 配置。
-
pages.json里不能写动态表达式,只能写静态对象,所以需为每种语言单独定义一套结构:"tabBar": { "color": "#7A7E83", "selectedColor": "#007AFF", "borderStyle": "black", "list": [{ "pagePath": "pages/index/index", "text": "首页", "lang": "zh-Hans" }, { "pagePath": "pages/index/index", "text": "Home", "lang": "en-US" }] } - 注意:这个
lang字段只在 App 和 H5 生效,小程序不识别;且必须与uni.getLocale()返回值完全一致 - 如果项目只支持简繁英三语,
pages.json就得写三组 tabbar 配置,否则切换语言后 tabBar 文字不会变
最易被忽略的一点:App 端语言初始化必须在 plusready 后完成,且所有语言相关逻辑(读取、存储、切换)都要绕过“立即生效”思维——它本质是重启驱动的,不是响应式更新。把语言当成一次性的启动参数来处理,反而更稳。











