React在线编辑国际化文本
今天给大家介绍一个轻量但神奇的国际化库tiny-i18n
在我们的项目日益庞大的情况下,国际化的字典愈变愈大,国际化文本的维护是一个问题;
有时候修改一个字段,查找就花费了很大的时间功夫。 这个时候 tiny-i18n 中的 @tiny-i18n/react-live 就可以发挥它的力量了,可以帮助我们在线可视化修改、新增国际化字段。
效果
视频效果:http://obu9je6ng.bkt.clouddn.com/Jietu20180622-102135-HD.mp4
DEMO - 更新后,字典存储至 localStorage 中
体验在线编辑
实现原理
对 i18n 转换方法进行包装,转换成包含特殊字符(包裹)的字符串;同时对 React.createElement
方法进行包装,检测出包含特殊字符(包裹)的字符串,这时候就会被认为是国际化的文本,这个时候再去注入一些而外的交互逻辑。
以 codesandbox DEMO 为例,在下面这段 React 视图代码中:
class App extends React.Component {
changeLang = lang => {
this.context.i18n.setLanguage(lang);
};
render() {
return (
<div className="App">
<h1>{_i("tpl.sayhello", _i("name"))}</h1>
<h2 title={_i("content.text")}>{_i("content.text")}</h2>
<a href="/?react-live">Open react-live mode</a>
<div>
<h3>
{_i("label.current.lang")}: {i.getCurrentLanguage()}
</h3>
{i.getLanguages().map(lang => (
<button key={lang} onClick={this.changeLang.bind(this, lang)}>
{lang}
</button>
))}
</div>
</div>
);
}
}
如下图,为国际化文本正常渲染的 DOM 结构:
并无什么异样,只不过是 _i(...)
方法转换为对应语言的译文字符串。
那么在开启 React-Live 功能之后呢?(点击 Open react-live mode
)
react-live 模式加载了下面的脚本
if (location.search === "?react-live") {
require("@tiny-i18n/react-live/register");
require("@tiny-i18n/react-live/lib/style.css");
}
视图就神奇地变成了下面所示!
观察 DOM 结构可以看出来,在 “你好呀,大家” 这段国际化文本中,对应代码为:
<h1>{_i("tpl.sayhello", _i("name"))}</h1>
字典数据为
i.setDictionary(
{
"label.current.lang": "当前语言",
"name": "大家",
"tpl.sayhello": "你好呀,${1}",
"content.text": "点击下面的链接看看有什么神奇的事情发生吧!"
},
"zh-CN"
);
未开启 react-live 对应的 HTML:
<h1>你好呀,大家</h1>
开启后变成:
不难发现,react-live 注入了一些额外的数据,并且各字段之间也被奇怪的字符: ​
‌
包裹,这两个字符是特殊的不可见字符。通过这两个字符包裹,可以找到对应翻译文本在 DOM 中的位置,进而可以进行替换。
但是这两个不可见字符也会带来隐藏的问题,如复制下面“你好”文本
你好
看来其中的字符串长度为2,但是实际上却是2
这是因为上面的文本,实际上为 你​‌好
,而中间 2 个字符不可见。
其他问题
除了上文介绍的不可见字符带来的问题以外,还有如果开启 react-live 模式后,i18n 转换方法输出的字符串将不会再是正确的转换文本;只有通过 React.createElement 方法才能被正确转换为国际化的文本。
所以 document.title = _i('...')
这样的语句会有问题;
即使是使用 react-document-title 也是会有相同的问题。因为 react-live 只会对 html tag(React.createElement 第一个参数为字符串) 中的国际化文本进行转换。