🚀 微信小程序国际化完整方案
在实际业务开发中,小程序国际化往往会遇到这些"老大难"问题:
- ❌ WXML 里不能优雅写多语言(每次都要 setData)
- ❌ JS 逻辑里调用翻译不统一(到处 require)
- ❌ 切换语言后页面不同步(部分更新、部分没更新)
- ❌ TabBar / 导航栏等原生组件无法自动更新
- ❌ 引入第三方库过重、复杂、增加包体积
- ❌ 老项目改造成本高
🎯 本方案目标
这套方案解决的是企业级真实场景问题:
✅ WXML中能直接写
✅ JS逻辑中随时调用
✅ 切换语言全局生效
✅ 原生组件同步更新
✅ 无任何第三方依赖
✅ 对老项目极低侵入
🧩 一、整体架构设计(核心思想)
架构分层
text
语言资源层(i18n/*.js)
↓
核心引擎(i18n/index.js)
↓
全局注入(重写 Page)
↓
页面使用(WXML + JS)
↓
运行时动态切换
核心机制解释(非常重要)
| 层级 | 作用 |
|---|---|
| 语言包 | 存储所有翻译内容 |
| i18n核心 | 提供 t()、setLocale() |
| Page重写 | 自动注入,无需手动初始化 |
| 页面层 | 直接使用 $t |
| 切换机制 | reLaunch 强制刷新 |
📁 二、目录结构设计(标准企业写法)
bash
├── i18n/
│ ├── index.js # 核心逻辑
│ ├── zh.js # 中文
│ ├── en.js # 英文
├── pages/
├── app.js
🌍 三、语言包设计(支持嵌套 + 变量)
📌 设计原则
- 按模块分组(home、common、tabbar)
- 使用对象嵌套(避免 key 冲突)
- 支持变量占位符
{}
中文语言包(zh.js)
javascript
module.exports = {
home: {
title: '首页',
welcome: '欢迎来到我的小程序,{name}!'
},
common: {
confirm: '确定',
cancel: '取消'
},
tabbar: {
home: '首页',
mine: '我的'
}
}
英文语言包(en.js)
javascript
module.exports = {
home: {
title: 'Home',
welcome: 'Welcome to my app, {name}!'
},
common: {
confirm: 'Confirm',
cancel: 'Cancel'
},
tabbar: {
home: 'Home',
mine: 'Mine'
}
}
⚙️ 四、核心引擎实现(重点讲解)
i18n/index.js
javascript
const zh = require('./zh.js');
const en = require('./en.js');
// 所有语言集合
const locales = { zh, en };
class I18n {
constructor() {
// 1. 优先读取缓存
// 2. 没有则默认中文
this.locale = wx.getStorageSync('lang') || 'zh';
}
/**
* 核心翻译方法
* @param {string} key - 如 'home.title'
* @param {object} params - 变量替换
*/
t(key, params = {}) {
const keys = key.split('.');
let result = locales[this.locale];
// 逐层查找
for (let k of keys) {
if (result) {
result = result[k];
} else {
break;
}
}
// key 不存在
if (!result) {
console.warn(`i18n missing key: ${key}`);
return key;
}
// 变量替换
Object.keys(params).forEach(param => {
result = result.replace(
new RegExp(`{${param}}`, 'g'),
params[param]
);
});
return result;
}
/**
* 设置语言
*/
setLocale(lang) {
this.locale = lang;
wx.setStorageSync('lang', lang);
}
/**
* 获取当前语言
*/
getLocale() {
return this.locale;
}
}
export default new I18n();
🔥 五、核心黑科技:重写 Page(最关键)
为什么要重写 Page?
因为我们要实现:
html
{{ $t.home.title }}
👉 而不是:
html
{{ title }}
实现方式(app.js)
⚠️ 必须写在最顶部!
javascript
import i18n from './i18n/index.js';
// 保存原始 Page
const originalPage = Page;
// 重写 Page
Page = function (pageConfig) {
const { onLoad } = pageConfig;
pageConfig.onLoad = function (options) {
/**
* 1️⃣ 注入语言包(给 WXML 用)
*/
this.setData({
$t: require(`./i18n/${i18n.getLocale()}.js`)
});
/**
* 2️⃣ 注入翻译函数(给 JS 用)
*/
this.$t = i18n.t.bind(i18n);
/**
* 3️⃣ 执行原有生命周期
*/
if (onLoad) {
onLoad.call(this, options);
}
};
return originalPage(pageConfig);
};
App({
onLaunch() {},
//切换语言
changeLanguage() {
const newLang = i18n.getLocale() === 'zh' ? 'en' : 'zh';
// 1. 更新内部状态与缓存
i18n.setLocale(newLang);
// 2. 最稳妥的页面刷新方案:清空路由栈,重启到首页
wx.reLaunch({
url: '/pages/index/index'
});
},
});
🧑💻 六、使用方式(极简)
✅ WXML 使用
html
<view>
<text>{{ $t.home.title }}</text>
<text>{{ $t.home.welcome }}</text>
<button>{{ $t.common.confirm }}</button>
</view>
✅ JS 使用
javascript
Page({
showToast() {
wx.showToast({
title: this.$t('home.welcome', { name: '开发者' }),
icon: 'none'
});
}
});
🔄 七、语言切换(全局刷新机制)
实现代码
javascript
import i18n from '../../i18n/index.js';
Page({
changeLanguage() {
const newLang = i18n.getLocale() === 'zh' ? 'en' : 'zh';
// 更新语言
i18n.setLocale(newLang);
/**
* 关键点:强制刷新
* 原因:
* - Page 不会自动重新执行 onLoad
* - data 不会自动更新
*/
wx.reLaunch({
url: '/pages/index/index'
});
}
});
为什么不用 setData?
| 方法 | 是否可行 |
|---|---|
| setData | ❌ 无法全局更新 |
| eventBus | ❌ 复杂且易出bug |
| reLaunch | ✅ 官方推荐 |
📱 八、原生组件国际化(重点)
❗ 问题说明
这些组件不受 data 控制:
- NavigationBar
- TabBar
✅ 解决方案:手动更新
1️⃣ 导航栏标题
javascript
onShow() {
wx.setNavigationBarTitle({
title: this.$t('home.title')
});
}
2️⃣ TabBar
javascript
onShow() {
if (typeof this.getTabBar === 'function') {
wx.setTabBarItem({
index: 0,
text: this.$t('tabbar.home')
});
wx.setTabBarItem({
index: 1,
text: this.$t('tabbar.mine')
});
}
}
🧠 九、企业级优化(强烈建议加)
✅ 1. 自动识别系统语言
javascript
const systemLang = wx.getSystemInfoSync().language;
this.locale = systemLang.includes('zh') ? 'zh' : 'en';
✅ 2. 防止 key 丢失
javascript
if (!result) {
console.warn(`i18n missing key: ${key}`);
return key;
}
✅ 3. 支持更多语言
javascript
const locales = {
zh,
en,
ja,
ko
};
✅ 4. 模块化语言包(大型项目)
bash
i18n/
├── modules/
│ ├── home/
│ ├── user/
│ ├── order/
✅ 5. 性能优化(避免重复 require)
javascript
const cache = {};
function getLocaleData(lang) {
if (!cache[lang]) {
cache[lang] = require(`./${lang}.js`);
}
return cache[lang];
}
🏆 十、方案优势总结
| 维度 | 表现 |
|---|---|
| 开发体验 | ⭐⭐⭐⭐⭐ |
| 可维护性 | ⭐⭐⭐⭐⭐ |
| 性能 | ⭐⭐⭐⭐ |
| 扩展性 | ⭐⭐⭐⭐⭐ |
| 侵入性 | ⭐ |