前端如何从0到1实现一个多语言方案

244 阅读3分钟

一.不谈谈历史,字数是凑不够的

以前原始时代,没有三大框架的时候。做多语言设计,你能想到怎么做?无非是对页面的dom结构进行标记,然后在遍历替换。这说实话效果就很扯,体验效果很差。简直就是一闪一闪亮晶晶。当然神器jquery,有提供一些插件方案,效果也好不到哪里去。

后来前端出了几大框架,各社区也有对应的开源方案,一般是定义json,然后在应用最外层包裹一个数据层。传递key,通过改key和页面刷新实现切换。

二.首先说一下结论,我们决定自己造轮子

为什么要造轮子?

1、首先我们需要切换无刷

2、可以实时注册增减多语言

3、不想应用顶层包裹一个多语言的容器

4、可以在任意地方注册多语言并全局生效。

因为我们公司采用react框架为主。我们历史有项目用过react-intl,其实这个框架整体还是挺强大的,但是使用起来不够简单,创建,消费都需要特定方法和组件。而且包有200多kb,是我们不能接受的。同时在使用的过程,还有浏览器兼容性问题。无法支持某组件差异更新。其次还不支持hooks用法。

后来项目中我们后来改进了,定义一个全局json,采用rxjs全局监听一个多语言对象。再使用时用observer收集组件依赖,从而更轻量简化了多语言方案。并支持某一个组件多语言单独刷新。提供多语言组件TextMessage,只需要包裹一个key就能实现转化。同时提供getMessage,useMessage等多样化的消费方式,满足不同的使用场景。

总之这版多语言我们团队上下都还比较满意。

直到有一天,有人说起,每个组件都包裹着一个observer不觉得比较繁琐,且不好理解吗?,同时对forwardRef也不友好。为什么不能自动收集一下依赖?

首先我们去调研了一下开源的能实现自动收集依赖的库很多,如 recoil,valtio,zustand,jotai等。发现他们实现的原理都不复杂。

所以感觉我上我也行。

所以我们自己就编写属于我们团队自己的自动收集依赖库@focbiz/loong,同时我们也使用此库做我们的全局数据流方案。

三.基于自动收集依赖的框实现多语方案

有了loong一切都简单了。

1.首先定义多语言格式:

export const companent = { 
 
'zh-CN': {companent: { base: '基础组件', baseform: '基础表单', }}, 

'en-US': {companent: { base: 'Base component', baseform: 'Base form'}},

'ja': {companent: { base: 'ベースコンポーネント', baseform: 'ベースフォーム', }}};

key可以尽量参照于国际化标准。

2.提供全局多语言对象locales生成一个可以被监听loong对象,这里loong可以用其他库替换

import { loong} from '@focbiz/loong';

const locales= {};

export const localesHander = loong(locales);

3.提供消费的hooks,根据对象路径进行查找,期间要对传入的 tokenstring做必须得校验,和查找。校验是必要的tokenstring格式验证已经存在验证等。查找是根据 tokenstring 作为对象路径查找

const useMessage=(key:tokenstring)=>{

    const [data] = useLoong<typeof locales>(localesHander)

    return data[nowLangKey][tokenstring]
}

4.组件不做演示,组件就是使用hooks,封装一个基础的react组件即可。

5.提供全局注册多语言的方法 mergeLocales方法就是对象的合并

export const registerLocales=(...packages: Locales[]) => {   
     packages.forEach((locales) => {   
        mergeLocales(locales, locales)}
)}

6.最后可以把这些方法挂着window上,可以实时查看以及注册调试等。

这个方案带来的使用体验以及性能体验都是相当的哇塞的。

整体思路仅作参考,如有雷同,纯属巧合。