uni-app中$t切换语言后文字未变,需确保i18n.locale响应式更新;动画须作用于view容器而非text节点,用v-if+transition配合opacity/transform实现流畅切换。

uni-app中用$t切换语言后文字没变?先确认i18n实例是否响应式绑定
uni-app本身不内置i18n,多数项目用vue-i18n@8.x(适配Vue 2/3)或@intlify/vue-i18n-bridge。常见问题是语言切换后界面未更新,本质是$t调用未触发视图重渲染——这通常因为i18n.locale被直接赋值而非通过locale.value = 'zh'(Vue 3)或i18n.locale = 'zh'(Vue 2)正确设置。
实操建议:
- Vue 3项目务必用
ref或reactive包裹i18n实例,并在setup中返回locale供模板响应式读取 - 避免在
onLoad里直接改i18n.locale,应调用封装好的setLocale('en')方法,内部统一触发locale.value = lang+uni.setStorageSync('lang', lang) - 检查
pages.json是否启用了usingComponents,若自定义了多语言组件但未声明,$t可能在子组件中失效
按钮点击后文字闪动或错位?动画需作用于文案容器而非整个页面
直接对<view></view>加transition无效,因为uni-app的transition组件仅支持v-if/v-show切换,且不兼容text节点。常见错误是给<text>{{ $t('login') }}</text>加transition,结果动画不触发或报错transition is not supported on text node。
实操建议:
- 把文案包在
<view class="i18n-text"><text>{{ $t('login') }}</text></view>中,用v-if控制该view显隐,配合<transition name="fade"></transition> - CSS动画用
opacity+transform,避免触发布局重排;.fade-enter-active, .fade-leave-active必须设transition,否则无动画 - 慎用
v-show配动画——它只是display: none,transition不会生效
如何让语言切换动画与按钮点击解耦?用watch监听locale比事件总线更可靠
有人用uni.$emit('lang-change')通知全局,但跨页面时容易漏监听,且动画时机难控制。更稳的方式是让文案容器自己监听语言变化,而不是等按钮“通知”。
实操建议:
- 在文案组件的
setup中用watch监听i18n.locale(Vue 2)或localeref(Vue 3),变化时触发isLeaving = true,延时300ms后置isLeaving = false并更新文案 - 按钮只负责调用
changeLang('ja'),不关心动画逻辑,降低耦合 - 如果使用
pinia管理语言状态,watchuseI18nStore().locale,同样适用
真机上动画卡顿或跳帧?避开font-size和color的transition
Android低端机上,font-size过渡会强制重绘整块文本,color过渡在部分Webview中不触发硬件加速。现象是文字突然消失再出现,或动画掉帧明显。
实操建议:
- 动画只用
opacity(淡入淡出)和transform: translateX()(滑动),这两者可走GPU加速 - 避免在
transition中写all,明确指定transition: opacity 0.3s, transform 0.3s - 真机调试时用
uni.getSystemInfoSync().platform区分iOS/Android,对Android加will-change: transform提升性能
语言切换动画的复杂点不在切换逻辑,而在于文案节点的生命周期控制——它既不能阻塞用户操作,又得确保旧文案完全退出后再渲染新文案。很多坑都源于想“一劳永逸”地给所有$t加动画,实际应该按需包裹、逐个控制。











