从0到1教你写一个JS的多语言库

前言

造这个轮子源于之前做的那个彩虹屁老婆插件,里面需要用到多语言切换。借这个由头,自己来实现一下。做之前其实对JS的多语言库没什么了解,做完之后倒是去比较了下vue-i18n。

选择多语言文本配置

vue-i18n的配置(图片来自百度)图片

vue-i18n的配置(图片来自百度)图片

大部分js的多语言库似乎都采用了json格式,可以很方便的转为对象解析,还可以分多级结构来组织配置内容。但是我个人感觉json格式对非技术人员(比如正经请个翻译的话)并不太友好。加上联想起过去做iOS开发多语言时的体验,我还是倾向于选择普通的文本格式,基本上完全照搬iOS里的.strings文件来做多语言配置。

图片

  • 这样的好处是,我们在代码里使用的时候就用常用语言写字符串即可。无论是代码的可读性,多语言配置文件编辑者的易用性都很高
//vue-i18n示例
$t("login.title")

//NSLocalizedString示例
NSLocalizedString("知道了")

代码时间

按行拆分数据

本例里是一个node环境,所以用fs来读取文件内容,然后赋值给data。如果要支持浏览器环境,可以用其他http框架api来读取文件内容。

const list = data.split("\n");

拆分变量名和值

在这里我使用了两个数组,一个用来存放读取所用的键名,一个用来存放对应的值。是不是可以扔到{}对象里呢?考虑到可能有一些特殊情况需要使用特殊字符来取值,为了保证这种特殊情况下的兼容性,所以尽量不要让key成为key

keys=[];
values=[];
    
for (var i = list.length - 1; i >= 0; i--) {
    var row=list[i];
    var key=row.split("=")[0].trim().match(/(?<=').*?(?=')/)[0];
    var value=row.split("=")[1].trim().match(/(?<=').*?(?=')/)[0];

    keys.push(key);
    values.push(value);
}

首先通过String的split方法,以=为分隔符拆分字符串为数组。然后trim裁剪掉两边的空格,给这样的配置结构增加一定的容错性。

以上步骤完成后,我们就可以通过values[keys.indexOf("键")]的方式来获取对应的多语言文本了。

拆解变量

在使用多语言时,我们可能会遇到这样的情况。“我有1个苹果”,其中数字部分是动态的,前后为固定不变的内容。当然我们可以使用A+变量+B的形式来组合,但这样未免有点麻烦,而且影响代码的可读性。

这个时候我们就需要另一种实现方式

localized("请选择{$1}文件","model.json")

也需要支持携带多个变量

localized("请选择{$1},{$2}文件","png","jpg")

这样用起来就非常简单,代码也十分好读。实现的核心就是先用正则将{$}结构全部提取出来,然后按照args的传递顺序依次替换

let dynamics=value.match(/{\$.*?}/g);

if(!dynamics)return value;

var dynamic_str = value;
for (var i = 0; i < dynamics.length; i++) {
    var d_item=dynamics[i];
    dynamic_str=dynamic_str.replace(d_item,`${args[i]}`);
}

return dynamic_str;

结语

自己手写一个多语言库不难,核心逻辑并不复杂。重点是在造轮子的过程中,去思考使用场景,多语言配置的提供者,有可能遇到哪些问题,什么样的配置能提升他们的工作效率。在代码层,api怎么设计更好用,代码可读性更好等等。

源码及示例

https://github.com/ezshine/ezlocale

猜你喜欢

转载自blog.csdn.net/ezshine/article/details/124311206