app端切换语言需手动重载页面,因uni.setlocale不触发渲染;tabbar等原生组件需显式更新;推荐@dcloudio/uni-i18n用于轻量场景,vue-i18n@9用于复杂需求但须手动适配。

App端切换语言后页面不刷新?uni.setLocale没效果
因为 uni.setLocale 只改全局 locale 值,不触发 Vue 组件重新渲染。App 端(iOS/Android)的 uni-app 运行时不会自动监听 locale 变化并响应式更新文本——这和 H5 端靠 vue-i18n 的响应式机制不同。
实操建议:
- 必须手动触发页面重载:调用
uni.reLaunch或uni.redirectTo当前页面(推荐uni.reLaunch避免栈堆积) - 切换前用
uni.setStorageSync存下新语言,如uni.setStorageSync('app_locale', 'zh-Hans') - 在页面
onLoad中读取存储值并调用uni.setLocale,确保每次进入都对齐 - 避免在
onShow里重复 setLocale,可能引发白屏或闪退(尤其 Android)
i18n 插件选 @dcloudio/uni-i18n 还是 vue-i18n@9?
@dcloudio/uni-i18n 是 uni 官方轻量方案,仅支持编译时静态替换,不支持动态 key、复数、插槽翻译;vue-i18n@9 功能全但需手动适配 App 端生命周期,且体积大 200KB+,容易触发 iOS 包体积警告。
实操建议:
- 纯 App 项目且语言少(≤3 种)、文案固定 → 用
@dcloudio/uni-i18n,配置简单,无运行时开销 - 需要动态加载语言包、带命名空间或格式化(日期/数字)→ 选
vue-i18n@9,但必须配合createI18n+useI18n在每个页面手动调用locale.value = xxx - 别混用两个插件,
uni.getLocale()和i18n.locale.value不同步,会互相覆盖
切换语言时 TabBar 文字不更新?uni.setTabBarItem 失效
App 端 TabBar 是原生控件,uni.setTabBarItem 只能改单个 item,且只在当前页面生效;如果 TabBar 文字来自 i18n 配置,切换语言后它不会自动重读。
实操建议:
- 在切换语言后,显式调用
uni.setTabBarItem更新每个 tab,传入对应语言下的文字,例如:uni.setTabBarItem({index: 0, text: $t('tab.home')}) - 不要依赖
tabBar.list.text的初始配置做多语言——它只读一次,编译后就固化了 - iOS 上若发现文字截断,检查是否用了中英文混排导致宽度计算异常,可加空格或固定
width样式兜底
App 启动时语言没按系统设置自动匹配?uni.getSystemInfoSync().language 返回 zh 但期望 zh-Hans
Android 返回的是简写(如 zh, en),iOS 返回带区域(如 zh-Hans, en-US),而 i18n 配置通常按完整 locale 名定义,直接赋值会匹配失败。
实操建议:
- 启动时用
uni.getSystemInfoSync().language获取原始值,再做映射:zh → zh-Hans,en → en-US - 不要直接
uni.setLocale(lang),先判断是否存在对应语言包:if (i18n.availableLocales.includes(mappedLang)) {...} - 用户首次启动没存语言偏好时,以映射后值为准;后续以本地存储为准,避免每次进 App 都切回系统语言
最麻烦的其实是 TabBar 和原生组件(如 uni-date-picker)的语言联动——它们不走 Vue 渲染流程,得各自手动桥接,而且 iOS 和 Android 行为还不一致。留个心眼:切语言前先 console.log(uni.getLocale()),确认值真的变了,再查哪一层没跟上。










