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

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

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

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

🏆 十、方案优势总结

维度 表现
开发体验 ⭐⭐⭐⭐⭐
可维护性 ⭐⭐⭐⭐⭐
性能 ⭐⭐⭐⭐
扩展性 ⭐⭐⭐⭐⭐
侵入性
相关推荐
棋宣29 分钟前
uni-app编译到微信小程序中,父传子props首次传递数据不接收的bug
微信小程序·uni-app·bug
程序鉴定师18 小时前
西安App开发推荐与业界认可的优秀实践
大数据·小程序
纤纡.1 天前
HarmonyOS 鸿蒙 ArkTS 实战:从零开发生肖集卡抽奖小程序
华为·小程序·harmonyos·deveco studio
Lsx_1 天前
H5 嵌入微信 / 支付宝 / 抖音小程序 WebView:调用原生能力完整方案
前端·微信小程序·webview
我是伪码农1 天前
小程序26-50
小程序
计算机学姐2 天前
基于微信小程序的图书馆座位预约系统【uniapp+springboot+vue】
vue.js·spring boot·微信小程序·小程序·java-ee·uni-app·intellij-idea
焦糖玛奇朵婷2 天前
健身房预约小程序开发、设计
java·大数据·服务器·前端·小程序
Dragon Wu2 天前
Taro v4.2.0 scss使用“@/xxx“的配置方法
前端·小程序·taro·scss
WKK_2 天前
uniapp 微信小程序使用TextEncoder,arrayBufferToBase64
微信小程序·小程序·uni-app
舟遥遥娓飘飘2 天前
面向零基础初学者,从环境搭建到发布上线,手把手教你开发第一个微信小程序(第3章-认识项目结构)
微信小程序·小程序·notepad++