国际化、多语言
一般公司在创立之初,根本就没有概念(或者没有时间)来做5年后、10年后的技术架构(除非是连续创业、有前瞻性很强的技术团队或者领导),这是很自然的,因为默认最重要的就是处理好眼前的事,如果一开始就花了太多时间做未来规划,结果自己都撑不了3年,这就真的是没有脑子的行为了。
公司一开始的头号目标,一定是活下去。
撑过头几年的夭折高峰期,业务慢慢发展起来,慢慢的,技术需要迭代、需要更新、需要重新设计
。这个时候就需要有一定的前瞻性
。
比如开始拆分单体结构,做成模块化服务
,做成微服务
,慢慢的上云
,拥抱云原生
(Cloud Native
)/服务网格
(Service Mesh
)等等。
再比如,公司业务走向国际化
,需要重新设计,如何更好的为其他语种的客户服务,如何做到国际化
,支持多语言
。
几种多语言设计方案
1、单字段多实例方案
这种方案就是一种设计干到底,一把梭。 每次新增一个语种,就做成一个新的子站。每次新增一个站点就需要新增一个数据库集群。字段永远是那个字段,只不过内容变为对应的语言。
此方案部署实施简单,但是需要更多的成本,适合不差钱的公司采用。
- 优点:简单
- 缺点:成本高
2、列扩展方案
此方案就是每次来一个语言,就新增列,这个思考来也没什么难度,想得到的,但就是每次新增列的时候,会对数据库有影响。当数据量很大的时候,如何保证不影响用户体验的增加字段是个难题,大多需要提前准备做停机升级。如果要保持向后兼容,需要提前预留一些字段
。
- 优点:简单
- 缺点:扩展语言对业务影响大(除非预留字段),不同的表都需要维护一套类似方案
3、行扩展方案
此方案就是提前做好根据语言的区分,增加一个语言的映射表,每次增加一种语言,新增该映射表即可。新增语言对业务影响小。
- 优点:新增语言对业务影响小,扩充平滑
- 缺点:不同的表都需要维护一套类似方案
4、语言表集中维护
此方案就是为了解决前面提到的一个问题:不同的表都需要维护一套类似方案。该方案将全部的语言内容放到一个地方集中统一管理,各个表中要取对应的语言内容,根据映射id去语言表中拿对应的语言即可。
不过因为全部业务的多语言内容都放在一个表里面,很快就会达到瓶颈,需要及早的考虑分库分表的问题。
- 优点:对业务影响小,统一管理语言
- 缺点:语言表是瓶颈,需要注意性能问题
不同的方案有不同的优缺点,技术实现并没有银弹。我们需要根据具体的场景选择不同的方案,或者根据某个方案进行改造。
案例:跨境电商 2种语言 => 7种语言
跨境电商刚开始很多是先做一个只支持简体中文的,毕竟主要是为了远方的华人华侨留学生们服务,然后慢慢普及到汉语系的其他人。然后慢慢发展,需要挖掘英语系的客户,就支持英语。双语支持一大段时间之后,又想要支持更多的语言,比如说日语、韩语、西班牙语和越南语等。
前提:
- 公司现在支持
2种
语言,采用的是上面的列扩展
方式 - 要影响更小的支持更多的
5种
语言 - 业务量已经比较大
思考:要一口气新增5种语言,并且日后不知道要不要新增更多语言,最好是可扩展
。基于现有方案,如果继续采用列扩展方式,会很麻烦,而且多个DB
多个Table
都需要一起扩充,基本上要停机更新。这个对于现有业务的冲击很大,直接放弃。
可以考虑采用语言表集中维护的办法,同时兼容现有结构,采用API Gateway
做统一转换。
语言 | 翻译自 | 回写字段 |
---|---|---|
zh-TW | goods_name | goods_name |
ja | goods_name_en | goods_name_en |
ko | goods_name_en | goods_name_en |
es | goods_name_en | goods_name_en |
vi | goods_name_en | goods_name_en |
该方案有几个核心思路:
- 1、异步
翻译Job
(下方蓝色三条线对应的),将业务表内容取出来异步翻译,然后存入翻译表。将翻译表的ID
组成一个唯一标识(i18n#id#
),回写到业务库(Goods表
) - 2、用户访问,传入对应需要的语言,比如是韩语ko
- 3、业务服务根据下面的映射提取表中数据
- 4、拿到的数据
{goods_name_en:"i18n#123#chocolate"}
经过API Gateway
的时候,调用I18N Service
,I18N Service
根据已有内容前缀i18n#123#
,提取其翻译对应ID
(123),去翻译表中,找到对应语言(ko
)的内容(초콜릿) - 5、返回翻译好的对应语言的内容
{goods_name_en:"초콜릿"}
这个方法有几个好处:
- 1、充分利用现有字段,不再扩充
- 2、业务代码变化极少,只需要在原有的基础上(简体中文 => goods_name, 英文 => goods_name_en) 变为(简体中文/繁体中文 => goods_name, 英文/日语/韩语/西班牙语/越南语 => goods_name_en)
- 3、集中统一在
API Gateway
中做处理,没有更多代码/业务耦合 - 4、上线简单,无需停机更新,滚动升级。可以按照业务情况,逐步上线不同项目,只需要异步进行提前翻译即可,未翻译的自动用原语言兜底。
- 5、回滚方便。只需要将数据库中的i18n##xxx##头部去掉即可。
当然,这个只是一些基础的设计,后续还有更多需要处理,比如翻译表显然是瓶颈
。不能放在单表里面,如果要做持久化,需要分库分表
,添加多级缓存
。因为只是做一个简单存取,没有更多业务逻辑,可以考虑使用Elasticsearch
、K-V数据库
或者列式数据库(HBase等)
存储以及使用等。
评论区