微信小程序国际化完整方案

🚀 微信小程序国际化完整方案

在实际业务开发中,小程序国际化往往会遇到这些"老大难"问题:

  • ❌ 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];
}

🏆 十、方案优势总结

维度 表现
开发体验 ⭐⭐⭐⭐⭐
可维护性 ⭐⭐⭐⭐⭐
性能 ⭐⭐⭐⭐
扩展性 ⭐⭐⭐⭐⭐
侵入性
相关推荐
2501_916008892 小时前
2026 iOS 证书管理,告别钥匙串依赖,构建可复制的签名环境
android·ios·小程序·https·uni-app·iphone·webview
nhc0882 小时前
贵阳纳海川科技・上门洗车行业解决方案
科技·微信小程序·软件开发·小程序开发
土土哥V_araolin3 小时前
十二星商城小公排系统开发
小程序·个人开发·零售
hashiqimiya3 小时前
微信小程序--动态切换登录注册标签页
微信小程序·小程序
hashiqimiya3 小时前
微信小程序--获取验证码设计倒计时灰白色
微信小程序·小程序
weixin_lynhgworld6 小时前
电商营销新风口,淘宝扭蛋机小程序引爆流量与转化
小程序
2501_933907217 小时前
宁波小程序公司提供专业的小程序开发服务
科技·微信小程序·小程序
杰建云1678 小时前
小程序搭建如何影响企业数字化转型
小程序·小程序制作
2501_915918418 小时前
iOS App 拿不到数据怎么办?数据解密导出到分析结构方法
android·macos·ios·小程序·uni-app·cocoa·iphone