国际化方案
前端 i18n 库的选择
市面上比较流行的只有两种,两者功能差不太多。
- 可支持插件拓展
- 不支持编译自动生成 key (但是可以直接用文案当作 key)
- 不支持插件拓展,但支持高阶 hoc 的拓展
- 支持编译时自动生成 key
i18n 的本质
key - value 映射
不管哪种方案都是 key - value 的映射,抓住本质他的概念就很好理解。
如下
// 只是切换时候加载不同对象内容。
let languages = {
en: {
"common.hello": "hello",
},
zh: {
"common.hello": "你好",
},
};
i18n 需要解决的问题
key 的选取
如上所述 react-intl 支持自动生成 key,也支持手写 key。
i18n-next 貌似只支持手写 key。
key 的常见规则如下
// 规则一:手写,短语拼接
let languages = {
en: {
// 短语方式写key
"common.hello": "hello",
},
};
// 规则二: 手写,直接用文案当key
let languages = {
en: {
// 这种可能文案生成的json会很大
"hello ,i am fine and you?": "hello ,i am fine and you?",
},
};
// 规则三: 自动生成
//react intl 支持自动生成
// 举例
function Demo() {
const intl = useIntl();
return intl.formatMessage({ defaultMessage: "hello" });
// ^^^^^^^
// 在编译时候会给你生成
// intl.formatMessage({id:'generateKeyRule("hello")',defaultMessage:"hello"});
// generateKeyRul 可以自己指定,还有一些额外上下文变量可以使用,比如文件路径。
// 可以生成这种内容sha1
// intl.formatMessage({id:'asdjfkasjdfxxx',defaultMessage:"hello"});
}
对比下三种规则优缺点
手写短语 | 文案就是 key | 自动生成 | |
---|---|---|---|
优点 | 无文案依赖,也就是说它只作为页面的一个占位符,你想换文案就可以换文案 | 无文案依赖,相比手写更加易于理解 | 无文案 key 维护成本,翻译易于复用 |
缺点 | 累,维护 key 贼累,翻译可能不易复用 | 代码显示文案可能与线上显示文案不符 | 依赖文案生成 key,依赖文案的变更需要重新生成 key,重新上线,文案冲突频率变高,需要选择一种基准文案(建议项目母语,变更频率最低) |
适用场景 | 文案少,变更频繁,可自定义覆盖,c 端,组件库 | 没想好 | 文案多,变更不频繁,b 端 |
ps: 文案冲突
// 自动生成key的文案冲突问题
function Demo() {
const intl = useIntl();
return intl.formatMessage({ defaultMessage: "select" });
// ^^^^^^^
// 对应中文可能是 选择图片,选择视频
// 解决办法,添加描述性语句辅助生成key
// return intl.formatMessage({ defaultMessage: "select", description: 'image', });
// zh: 选择图像 key-> select#video (react-intl 拼接规则)
// return intl.formatMessage({ defaultMessage: "select", description: 'video', });
// zh: 选择视频 key-> select#video (react-intl 拼接规则)
// return intl.formatMessage({ defaultMessage: "select" });
// zh: 选择 key-> select
}
可能遇见的状况(低频)
货币,数字国际化,i18n 是提供这个 api 的,可放心食用。
基础库解决的问题
- 文案提取的能力。
function Demo() {
const intl = useIntl();
return intl.formatMessage({ defaultMessage: "hello" });
// return intl.formatMessage({ id:"id", defaultMessage: "hello" });
}
// ===> 提取json
// 类似这种
// {
// "id || generateKeyRule(text)" : "hello"
// }
- key-value 映射
基础库未解决的问题
- 文案管理
随着业务迭代,文案越来越多,会有废弃文案,新增文案的概念。
需要一个平台存储文案,然后前端项目获取文案,可根据从项目中提取的文案与存储文案的地方做对比,然后获取文案。
- 文案完整度
如何确保多国翻译,或者部分国翻译 100%已有翻译,还是需要从项目中获取项目中使用的文案,然后对比语言包。
- 翻译流程
一条文案的产生的源头通常 prd,然后设计复制一份并拓展,然后研发根据设计稿开发,当提测是应提交项目中的文案到,待翻译状态,然后翻译组/产品/机翻,进行翻译,然后前端项目获取这些文案,进行文案完整度上线前检测即可。
这个是最难的,要拉起设计、产品、研发的认知才能搞。
翻译文案
如何保证一条文案在语境下的正确性?
- 方案一:
文案+设计图
实现难度低 - 方案二:
文案+页面
实现难度复杂
- 方案一:
文案关联页面
可通过webpack 插件开发处理chunk信息获取
所以需要一个平台/平台周边生态去做这些事
参考
i18n-next 文案平台
https://locize.com/
vscode i18n all in one 插件
https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally
阿里的轮子
https://github.com/alibaba/react-intl-universal
https://github.com/alibaba/kiwi