现有三方框架较多,如(Taro、UniApp)且支持框架不同(例:Vue + Taro、React + Taro)。每种跟随框架的多语言包都依赖于该框架的特性,无法通用但性能较好。
该库适合寻求框架通用、无三方依赖、且无频繁语言切换的场景使用。切换语言时会重新加载页面,造成一定的消耗。当然也可以将该库结合三方框架的特性使用,如在 Vue 的插件中使用,将语言切换做为数据响应的出发条件使用。
- 页面重载,重载到 tabbar 时会清空 tabbar 的页面缓存。支付宝小程序除外(支付宝使用 redirectTo)。
- 整个页面会重新加载,频繁切换时页面消耗较大。如较少存在小程序中语言切换,影响较小。
Tabbar(自定义除外)、NavigationBarTitle 的设置需要通过 Api 单独设置,即使采用跟随框架的方式更新多语言,也需要额外提供函数,触发已加载页面的 Tabbar、NavigationBarTitle 的设置函数更新页面数据。
语言切换后,需要刷新所有接口并附带当前语言标记,让后端感知并返回相应多语言的数据或错误提示。
-
公众号跳转至小程序页面(或小程序中的插件页面)
-
小程序跳转至小程序
-
H5 跳转至小程序
-
微信链接跳转至小程序
// 上述的跳转方式都可以通过以下 API 拿到当前打开页面的信息来源
onAppShow: referrerInfo // 来源信息
getLaunchOptionsSync: referrerInfo scene // 1.来源信息 2.场景值
本地缓存、运行时缓存和宿主小程序共享内存但各自环境独立,并且没有全局的生命周期,可以看做小程序中的一个组件。所以实现时主要需要考虑插件中的以下几点
- 多语言工具不重复初始化
// 可以通过 API (当前所有语言的集合)字段,判断长度是否大于 0
i18n.getLanguagePackList
- 宿主语言的语言环境参数传递
- 本地缓存:环境相互隔离。 此路不通
- 路径传参:可以实现。 plugin://hello-plugin/demo?lang=en_US
- 插件主文件:可以实现。 需要在跳转插件之前调用主文件中方法如下代码所示
2.1. 插件使用示例
// 插件主文件 index.js
import { i18n } from '@wooc/mini-i18n'
import locales from '../../locales/index' // 引入脚本自动执行初始化操作
module.exports = {
init(lang) {
i18n.setLocales(lang || 'zh_CN') // 默认语言
}
}
// 宿主环境使用
const plugin = requirePlugin('hello-plugin')
Page({
data: {},
onLoad() {
plugin.init('zh_CN') // 当前语言环境标记,可通过小程序 Api 获取
},
})
3. 页面渲染后的数据更新
在初始化、更改语言后的页面已经渲染。
// 通过 setData 实现页面的及时渲染
this.setData({title1: t('home.device_list.room_manage')})
4. 多语言接口动态更新语言
接口返回多语言数据,调用 API 完成,即可通过页面重载,更新多语言数据
i18n.updateLocale(obj)
非自定义多语言:官方支持四种语言设置:中文、英文、zh-HK、zh-TW。
自定义多语言:可使用i18n。
非自定义多语言: 无法使用多语言。可通过 API 设置 tabbar 多语言
自定义多语言: 可使用i18n。
npm install @wooc/mini-i18n
// index.ts
// locales 结构如下,将语言包的key值替换为 ua.ts 中对应的value的标记。具体内容请查看
// https://github.com/zhangchao-wooc/mini-i18n/blob/main/until/ua.ts
// 与react-i18n 要求基本相同
// {
// "zh-Hans": zh
// "en": "en"
// }
// 语言文件为对象嵌套格式
import zh from './zh';
import en from './en';
export default {
'zh-Hans': zh,
en
}
import { i18n, t } from '@wooc/mini-i18n'
import locales from './locales' // 语言文件
onLaunch (options) {
i18n.init({
locales,
lang: 'zh_CN',
defualtLang: 'en_US'
isHint: true,
themeColor: '#ff6600',
homePath: '/pages/my/index'
})
},
{
home: {
list: {
title: '家庭列表',
go_to: '前往%'
}
}
}
/** 1. 获取词条 */
t('home.list.title')
/**
* 2. 动态拼接
* 第二个参数为动态参数
* 第三个参数为占位符,默认为'%', 也可自定义。为了满足不同语言翻译时顺序不一致时词条的位置动态拼接
* 替换词条中的'%'为动态参数。输出: 前往涂鸦智能
*/
t('home.list.go_to', '涂鸦智能', '%')
/** JS */
import { t } from '@wooc/mini-i18n'
Page({
data: {},
onLoad() {
this.setData({
title: t('home.device_list.room_manage')
})
},
})
<!-- wxs 中无法引入外部 js 使用 -->
<!-- WXML -->
<button id="add" bindtap="addItem">{{ title }}</button>
import { i18n, t } from '@wooc/mini-i18n';
onShow () {
wx.setNavigationBarTitle({title: t('login') })
}
<View className={style.tip}>{t('loginHint')}</View>
<Button
className={style.apBtn}
style={{ backgroundColor: OEMConfig.extConfig.colorStyle.themaStyle, position:'fixed',right: 0, top: '30%' }}
hoverClass={style.hoverclass}
onClick={() => {
i18n.setLocales(i18n.getLocales() === 'zh_CN' ? 'en_US' : 'zh_CN')
}}
>
切换语言
</Button>
编写 vue 插件 plugins/t.ts
export default {
install: (app, options) => {
/** 混入全局 methods 中, 否则在模版中无法使用。或是挂载到全局均可 */
app.mixin({
methods: {
t (id: string) {
return options(id)
},
}
})
}
}
在 app.ts 中挂载插件
import i18 from './plugins/t'
const App = createApp({})
App.use(i18, t)
vue 文件中使用
import {i18n, t } from '@wooc/mini-i18n'
/** 全局混入 methods 或 在 methods 中创建一个 t 函数,方可在模版引擎中使用 */
<view class="commodity-info_name">{{t(item.name)}}</view>
/** setup创建时,组件实例并未创建,无法使用 methods 中的 t 函数,通过import引用方式,在 setup 中使用 */
setup(){
const state = reactive({
msg: t('home'),
menuItems: [
{
name: t('chinese'),
value: 'zh_CN'
},
{
name: t('english'),
value: 'en_US'
},
],
})
onMounted(() => {
Taro.setNavigationBarTitle({title: t('home')})
})
return {onMounted, ...toRefs(state)}
}
小程序插件中没有全局生命周期,可以看做为小程序的组件。
/** locales.ts 初始化 */
import { i18n, t } from '@wooc/mini-i18n'
import zh from './zh-Hans';
import en from './en';
const locales = {
'zh-Hans': zh,
en
}
const isInit = Object.keys(i18n.allLangData)
/** 防止多次 init */
isInit && i18n.init({
locales,
lang: 'zh_CN',
defualtLang: 'en_US',
isHint: false,
})
wxs 中使用
import { i18n, t } from '@wooc/mini-i18n'
Page({
data: {},
onLoad(options) {
const { lang } = options
if(lang !== i18n.getLocales()) {
i18n.setLocales({
lang: 'zh_CN',
isReload: true,
path 'plugin://hello-plugin/hello-page?lang=zh'
})
}
// setLocales(lang) 时页面已经渲染。使用setData 触发页面的数据更新
this.setData({title: t('home.device_list.room_manage')})
},
})
wxml 中使用
<text>{{title}}</text>
/**
* locales
* { 'en': {home: '首页'}, 'zh': {home: 'Home'}}
* 结构中的key值,应与 dist/until/ua.js 中对应多语言的 value 值一致
* https://github.com/zhangchao-wooc/mini-i18n/blob/main/until/ua.ts
*
*
* defualtLang
* 获取当前容器中的多语言直接传入即可,i18n中已做转换并映射到 locales 对于语言数据
*
*
* lang: 同上
*
*
* themeColor
* 十六进制颜色。如 isHint 为 true,提示框中的按钮颜色。默认为 '#000'
* 支付宝不支持
* 字节小程序不支持,自动跟随主题色。但字节小程序中有微信小程序的实例.所以复用微信小程序api,目前可以使用
*
*
* homePath
* '/pages/home/index' 重新加载指向的页面。插件中使用时通常带有动态参数,建议插件中使用
* setLocales,updateLocale 中的自定义路径,方便携带动态参数
*
*
* isHint
* 是否弹出提示框,判断系统语言是否与当前小程序语言一致,如不一致弹出提示框是否切换?如下图
* 插件中不可使用:isHint,因为插件中没有 onAppShow API
*
*
* isVerifiyApi
* 校验当前环境中api是否可用。插件中不可使用,因为插件中没有 canIUse 及其它众多 API
* 工具中使用的 Api 在各容器中的版本建议不同,某些版本下不可使用
* 由于 canIUse 在不同环境下表现不稳定,所以暴露是否开启配置项
* 建议将开发工具、基础库升级到主流配置。同时查看小程序后台,查看当前用户使用的基础库版本,对于指定版本的用户推送
* 升级消息
*
*/
i18n.init({
locales: object; // 兜底语言数据必须存在
defualtLang?: string; // 兜底语言 默认:'en_US'
lang?: string; // 当前显示语言 默认:'en_US'
themeColor?: string; // 主题颜色,用于全局提示时,颜色一致 默认:'#000'
homePath: string; // reload 默认跳转到的页面, 建议为首页,不建议插件中使用。
isHint?: boolean; // 是否显示语言切换提示
isVerifiyApi?: boolean; // 是否校验当前环境mini- i18n Api 是否可用 默认:false
})
/**
* lang:'zh_CN'
*
* isReload?: 是否定向到指定页面,完成页面更新。默认为 false
*
* path?: string,
* 自定义的跳转路径。 为空时,以 homePath(不建议于插件) 路径为准。
* 插件通常携带动态参数,建议如下方式使用
* 插件使用自定义路径:'plugin://hello-plugin/hello-page?lang=zh' 模式
*
* query?: string,
* 参数。也可以将参数直接拼接到 path 后,如上所示
*/
i18n.setLocales({
lang: string,
isReload: boolean = false,
path?: string,
query?: {
[propName: string]: string
}
})
// 语言获取顺序 params lang > localStorage > userAgent > defualt Lang
i18n.getLocales()
i18n.getLanguagePackList()
// 每次设置多语言时,在主文件中调用多语言接口,使用该 Api 更新多语言数据
/**
* 例:locales
* { 'en': {home: '首页'}, 'zh': {home: 'Home'}}
*
* isReload?:
* 是否定向到指定页面,完成页面更新。默认 false
*
* isAnalyticalData?: boolean,
* 是否解析数据,默认为 true,如过结构为对象、json嵌套形式,可设置为 false
*
* mark?: string,
* 分割语言 code 的占位符,默认为 '.'
*
* path?: string,
* 自定义的跳转路径。 为空时,以 homePath(不建议于插件) 路径为准。
* 插件通常携带动态参数,建议如下方式使用
* 插件使用自定义路径:'plugin://hello-plugin/hello-page?lang=zh' 模式
*
* query?: string,
* 参数。也可以将参数直接拼接到 path 后,如上所示
*/
i18n.updateLocale({
locales,
isReload = false,
isAnalyticalData = true,
mark = '.',
path: string,
query: {
[propName: string]: string
}
})
校验当前传入语言包中,是否存在传入的兜底语言的语言包,如无,控制台提示
是:当前 id 是否存在 > 显示兜底语言中对应 id 的value
否:显示兜底语言中对应 id 的value > key。
提示:控制台提示相应语言包不存在,对应的词条不存在
https://github.com/zhangchao-wooc/mini-i18n/blob/main/until/ua.ts
-
不支持showModal中按钮颜色自定义,且字段key值不同
-
tt.getSystemInfoSync 获取的系统信息中不含有 language 字段,tt.getUserInfo 中可以获取到,但需要授权弹框,故不使用
Tip: 在字节小程序中可以获取到微信小程序 wx 实例,所有字节小程序上均走 wx 实例上的api,且均可以成功调用,故功能上完全兼容字节小程。注意字节小程序将wx实例从中完全剥离时,该库则不支持字节小程序,请注意后续更新。
全局也存在 wx 实例,且两个实例的变化是同步的
2.1.2 及以上
1.4.0 及以上
1.10.8 及以上
1.46.0 及以上
3.140.1 及以上