使用 jQuery 进行前端多语言化的方法
使用 jQuery 进行前端多语言化的方法
在处理 URLRedirector (firefox 插件地址) 时,发现通过 jQuery 加上个自定义的 i18n class 能很好地处理多语言的问题。
在 text 中写 __MSG_<消息id>__
在处理这个问题时,由于原来的 html 页面都已经是有中文内容的,一开始时,想模范 firefox 的处理方式,即通过 __MSG_<消息id>__
的方式对 html 元素的 text 进行过滤,但这个方式存在一些问题:
- 需要遍历整个 dom
- 需要对整个 text 进行解释,找到所有
__MSG_<消息id>__
格式的文本 - 破坏原来的 html 的显示,如果有消息没有正确定义,显示错误
对 __MSG_<消息id>__
的字符串处理是比较复杂的,需要多次的 slice 操作,直到整个处理结束。
自定义 i18n 类和 data 属性
后来想了一下,其实可通过自定义一个 i18n 的 css 类,然后加上 data-i18n 的数据属性来完成类似的工作,实现起来已更加简单:
- 加载时,通过
$(.i18n)
选择所有的待进行多语言化的标签 - 分析标签的 data ,对于名字为
i18n_attr_
的数据,当作是标签的 attribute 需要多语言化 - 对于名字为
i18n_text
的数据,作为当前标签的 text 进行多语言化
这是目前的实现方式,代码也非常简单,整个代码见 https://github.com/fengyc/URLRedirector/blob/master/src/i18n.js :
/* Firefox webextension 读取多语言消息 */
function getI18nMessage(msgId) {
if (browser.i18n && browser.i18n.getMessage) {
return browser.i18n.getMessage(msgId);
}
return undefined;
}
$(document).ready(function () {
/* Elements with class "i18n" need to be handled. */
$(".i18n").each(function () {
/* text */
if ($(this).data("i18n_text")) {
var msgId = $(this).data("i18n_text");
var msg = getI18nMessage(msgId);
// If a message can't be found, firefox return "\"??" ad logs an error, chrome return ""
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/i18n/getMessage
if (msg && msg != "\"??") {
$(this).text(msg);
}
}
/* attributes */
for (var p in $(this).data()){
if (p.startsWith("i18n_attr_")) {
var attr = p.slice("i18n_attr_".length);
if (attr) {
var msgId = $(this).data(p);
var msg = getI18nMessage(msgId);
if (msg && msg != "\"??") {
$(this).attr(attr, msg);
}
}
}
}
})
});
这种方式还有进一步扩展的空间,如果在消息中需要到参数,可通过 data 再加入参数,就能应对更加复杂的多语言需求。
想比前一个方法,这个方法的带来一些好处:
- 不破坏原来 html 的显示
- 不修改原来的 text ,减少出错
- 不需要插件和复杂的配置,能与其它方案很好地配合
这种方法多语言方法不只适用于 firefox/chrome 的 webextension 插件,如果有必要也可以和后台解决方案进行整合。