使用 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 插件,如果有必要也可以和后台解決方案進行整合。