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

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

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

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

🏆 十、方案优势总结

维度 表现
开发体验 ⭐⭐⭐⭐⭐
可维护性 ⭐⭐⭐⭐⭐
性能 ⭐⭐⭐⭐
扩展性 ⭐⭐⭐⭐⭐
侵入性 ⭐
相关推荐
m0_5873830013 小时前
深圳 24 小时自助健身房系统软件开发实战指南与案例解析
java·spring boot·小程序·架构·需求分析
2501_9159090616 小时前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
扶风ff16 小时前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
镭封17 小时前
做电视剧解说视频用什么软件?配音、文案处理一次解决
人工智能·小程序·音视频·语音识别·媒体
闹小艾17 小时前
制作题库练题小程序如何选择搭建平台?3大主流平台优缺点,新手选型不踩坑
小程序
小码哥06818 小时前
陪诊小程序系统开发:开启医疗陪护新时代
小程序·陪诊·陪护·陪诊陪护·医院陪诊系统·陪诊系统·陪诊管理
扶风ff18 小时前
练题簿在线免费刷题:创建个人任务,把刷题、听题和模考目标放到每天的学习中
开发语言·javascript·学习·小程序
xunyan623418 小时前
51 单片机LED闪烁(SDCC + Notepad++ + STC-ISP/普中ISP)
单片机·notepad++·接口隔离原则
andrsted21 小时前
练题簿在线免费刷题:听读练题支持暂停续播、循环播放,让自己的题库听得更方便
学习·微信小程序·小程序·刷题·在线刷题