前言
VoerkaI18n
是一个非常优秀的前端多语言解决方案库,提供初始化、提取文本、自动翻译、编译、自动补丁等工具链支持。
在开发@voerkai18n/vue2
和@voerkai18n/vue
两个针对Vue2/3
的适配场景时,需要在切换语言时强制重新刷新整个页面,但是无论是Vue2
还是Vue3
均没有提供官方API
。
你可以想到的可能是重新刷新整个页面,但是我们要的重新渲染
而不是重新reload
,两者区别挺大的,此时需要用点小技巧,以下是经验总结。
Vue2
- 第1版的
@voerkai18n/vue2
首先在Vue2
组件实例上发现一个未公开的forceUpdate
的API
,从字面意思上看,就是强制更新的意思,实际测试也的确可以调用forceUpdate
实现强制重新渲染组件。
这下好了,只需要遍历一个组件树,分别调用每个组件实例的forceUpdate
就可以实现整个页面的强制重新渲染了。 但是官方也没有一个API
可以遍历组件树的方法,所以只能是自己通过分析组件树结构来进行遍历,实际也是可行的。
至第一版的@voerkai18n/vue2
就出炉了。
但是由于用的是未公开的API
,心里总不点忐忑不安。果然,没多久就有用户反馈forceUpdate
在开发模式下有效,但是在构建后就无效了。
- 第2版的
@voerkai18n/vue2
接下来就开始探索新的强制重新渲染方案,再镒重新拜官网文档,发现一个底层API observable
,该API
是用来创建一个响应式可观察对象的,结合Vue
的工作机制,这有了一个方案。
- 创建一个
observable
用来保存当前活动语言 - 让翻译函数
t
依赖该observable
如此,当切换语言时,就可以让所有使用t
函数的组件自动重新渲染。
代码如下:
ts
export const i18nPlugin = {
install:function (Vue:any, options:VoerkaI18nVue2Options) {
const { i18nScope } = Object.assign({},options)
if(!i18nScope){
throw new Error('Parameter<i18nScope> is required for VoerkaI18n Vue2 Plugin')
}
const state = Vue.observable({ langauge : i18nScope.activeLanguage })
Vue.prototype.t = (message:string,...args:any[])=>{
state.langauge
return i18nScope.t(message,...args)
}
Vue.prototype.getActiveLanguage =()=> {
return state.langauge
}
i18nScope.on("change",(language:string)=>{
state.langauge = language
})
}
}
以上开发了一个Vue2
组件,为每一个组件提供一个t
函数,重点在于state.langauge
这句代表了其依赖了state.langauge
这个可观察对象。
实测,第2版本的@voerkai18n/vue2
可以实现当切换语言时,所有使用到t
函数的组件均会重新渲染。
Vue3
在Vue3
中同样也是没有官方的强制重新渲染整个页面的API,但是在Vue3
的响应式API
更新完善,实现的思路大体相同。
- 第1步:创建一个ref对象用来保存当前语言
ts
let activeLanguage = ref(i18nScope.global.activeLanguage)
- **第3步:创建全局计算属性
$activeLanguage
php
app.mixin({
computed:{
$activeLanguage:{
get: ():string =>activeLanguage.value,
set: (value:string) =>{ i18nScope.change(value).then((newLanguage:string)=>activeLanguage.value=newLanguage)
}
}
}
})
- **第3步:创建全局可用的
t
函数,在组件模块中可以直接使用
ts
app.config.globalProperties.t = function(message:string,...args:any[]){
// 通过访问计算属性activeLanguage来实现当activeLanguage变更时的重新渲染
this.$activeLanguage
return i18nScope.t(message,...args)
}
重点在于t
函数里面用到了this.$activeLanguage
。这样,当计算属性$activeLanguage
变化时,就触发组件的重新渲染。
小结
- 利用
Vue2/3
响应式系统API来保存当前语言 - 让翻译函数
t
依赖响应式变量
完整代码可以参见:
@voerkai18n/vue @voerkai18n/vue2
开源推荐
以下是我的一大波开源项目推荐:
- 全流程一健化React/Vue/Nodejs国际化方案 - VoerkaI18n
- 无以伦比的React表单开发库 - speedform
- 终端界面开发增强库 - Logsets
- 简单的日志输出库 - VoerkaLogger
- 装饰器开发 - FlexDecorators
- 有限状态机库 - FlexState
- 通用函数工具库 - FlexTools
- 小巧优雅的CSS-IN-JS库 - Styledfc
- 为JSON文件添加注释的VSCODE插件 - json_comments_extension
- 开发交互式命令行程序库 - mixed-cli
- 强大的字符串插值变量处理工具库 - flexvars
- 前端link调试辅助工具 - yald