微信小程序实现i18n国际化能力的解决方案
发布于 3 年前 作者 xuemin 834 次浏览 来自 分享

需求背景介绍

现在有大量的外国客户会使用到我们的产品,从而产生了需要有通过切换语种达到显示不同语种文案的页面,用来满足外国客户的浏览使用。而如今市面上有很多流行的第三方库,可以实现这种能力,如vue-i18n。而微信原生小程序的运行环境是将WebViewe与AppService分层处理,所以需要自研一套支持在微信原生小程序技术框架上运行的i18n库。

设计概要

主要模块。
  • 实现一个下载进程器。保证多个相同的CDN请求时,只发一条CDN的正常下载。
  • 实现一个观察者,用于在异步数据响应成功后通知相关的页面或组件进行更新。
  • 实现一个缓存器,用于将CDN上获取的语言包内容缓存起来,避免重复请求。
  • 实现一个i18n类,主要用于实例后的对外api整理。
  • 实现一个package类,主要用于集成下载进程器、观察者、缓存器及实例后的api整理。
  • WXS(微信脚本),这个模块主要是实现i18n.t方法及与AppService层的通信。
主要的功能

i18n库提供install方法,用于集成在RPRM或未来的其它平台上。install方法返回一个i18n实例,该实例内置以下属性:

方法 作用描述 参数 备注
data 所有缓存的模块语言包内容,按package名分包。如:wx.rprm.i18n.data.package1 wx.rprm.i18n.data.package2 不涉及 只缓存当前语种的语言包内容。
getCurrentLang() 获取当前语种的函数。
swtich({lang}) 全量切换语种。 {lang:string}
use(options} 预加载模块语种 {package:string,version:string/number}
globalConfig(config) 通过路由划分,实现全量配置模块描述。 object

开发者希望使用的方式

//语法
i18m.t('key','default',options:object|array)

//具名格式
//对应的语言包格式
...
spec:'规格:{num}个'
...

//I18n.t的使用方式
... 
{{i18n.t('spec',{num:'100'})}}
...

//结果
//规格:100个

//列表格式
//对应的语言包格式
...
spec:'规格:第{0}百零{1}个'
...

//I18n.t的使用方式
... 
{{i18n.t('spec', ['一','三'])}}
...

//结果
//规格:第一百零三个

WXS(微信脚本)

由于i18n库涉及的模块比较多,所以这里说明WXS(微信脚本)模块是如何实现t方法及与AppService层实现通信能力。

如何在WXML上使用i18n.t方法

WXML上无法直接使用方法,所以要借助微信脚本(WXS)完成。声明一个WXS文件,在里面实现t方法,然后在WXML中引入这个WXS文件,其module的值设置为i18n。参考代码:

//WXS
function t(参数){
    //实现功能
}
module.exports = {t}

//WXML
<wxs src='路径/名称.wxs' module='i18n'></wxs>
<view>{{i18n.t(参数)}}</view>

如何在微信脚本(WXS)上得到语言包内容

微信脚本(WXS)是WebView里的一个脚本,想得到AppService里的数据,是需要实现数据通信的能力。借助setData触发微信脚本(WXS)的WxspropObserver。

参考代码:

<wxs src='路径/名称.wxs' module='i18n'></wxs>
<view change:prop="{{i18n.change}}" prop="{{langs}}"></view>
//WXS
function t(参数){
    //实现功能
}
function change(langs){
    //langs参数就是AppService层的setData传递的值
}
module.exports = {t}

上述代码的基本思路是,在view元素上的属性值绑定AppService层中data中的langs。用setData触发langs更新到Webview层的view元素上,然后用WxsPropObserver监听prop是否发生变化,变化了就触发i18n脚本模块中的change方法。change方法触发后会得到prop的值,也就是langs的值。

t方法格式化

...

/**
 * 格式化列表
 * 场景二:”Hello,{0}{1} = "Hello,world!"
 *
 */
var formatterByList = function(text, list = []) {
  //遍历数组
  //利用正则将花括号内容捕获匹配的内容替换成对应下标的数组值。
  return text;
};

/**
 * 具名格式化
 * 场景一:"Hello,{msg}" = "Hello,world“
 *
 */
var formatterByName = function(text, names = {}) {
  //利用正则分析出花括号里的值
  //在names对象里找到花括号里值的内容
  return text;
};

...

总结

上述主要是说明如何在WXML使用t方法以及将语言包内容同步到微信脚本上。实际的项目中需要考虑到将i18n功能模块化,异步数据获取监听及通知到微信脚本,性能、缓存等问题。

回到顶部