【RFC】一個力求簡單易用的jQuery Client-Side多國語系切換設計
9 | 24,940 |
RFC是Request For Comment的意思,學過網路的人應該多半有聽過,但這篇文章跟開創網路歷史的那堆偉大協定文件一點關係都沒有(謎之聲: 憑你也配!),純粹只是提出一個構想,想多蒐集各方意見。
事情要從工作專案增加了多國語系需求說起,ASP.NET雖早有解決方案,但我一直覺得傳統的多國語系搞法不夠人性化,就興起了為搞套簡便做法救自己的念頭。
傳統的ASP.NET多國語系做法要把所有因語系變換的文字改成變數物件或指定Resource Key,然後為不同語系設定資源檔,再針對每個Resource Key指定對應的字串。說具體一點,就是ASPX裡原本是
<asp:Label ID="lblUserName" runat="server" Text="使用者名稱"></asp:Label>
<asp:Label ID="lblUserNameHint" runat="server"
Text="請填寫中文或英文姓名"></asp:Label>
<script type="text/javascript">
...
if (...) alert("使用者名稱中不可包含特殊符號! - " + $("#txtUserName").val());
...
</script>
為了多國語系,要改成:
<asp:Label ID="lblUserName" runat="server"
Text="<%$ Resources:UserNameLabel %>"></asp:Label>
<asp:Label ID="lblUserNameHint" runat="server"
meta:resourcekey="UserNameHint"></asp:Label>
然後Script部分更麻煩,得將原本一氣喝成的Script改成義大利麵寫法:
if (...)
alert("<%=GetLocalResourceObject("DontSymbolMessage").ToString()%> - "
+ $("#txtUserName").val());
再不然就是搬到Server-Side
string s = "alert('" +
GetLocalResourceObject("NoSymbolMessage").ToString() +
" - ' + $('#txtUserName').val());";
依我個人看法,傳統做法最大的缺點是原本Visual Studio WYSWYG的直覺化特色不見了! 在開發階段看不出表單到底長什麼樣子,得按下執行鈕從Browser得到結果;若Layout需要調整,就得重覆"改HTML/CSS->跑Browser看結果->改HTML/CSS->跑Brwoser看結果..."的惱人迴圈。再者,為每段文字編一個Resource Key及維護的浩大工程,更是一箭射中粗心又沒耐性暴躁大叔的罩門,光用想像的就足以讓我瀕臨崩潰。
我不知道別人怎麼看待這樣的設計,但在我心目中,應該要用更直覺的方法解決Client-Side的多國語系問題才對,於是我想出了以下做法,還不怎麼成熟,姑且先稱它jQuery Multi-Language Helper Ver 0.5吧! 如果有機會得到大家的回饋,修校得更具體可行,或許會有推出Ver 1.0的機會。
使用它時,程式長這樣:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Multi-Language UI Test</title>
<script src="jquery-1.4.2.js" type="text/javascript"></script>
<script src="jquery.multilang.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
jQuery.setupMultiLang("UI.lang.htm");
$("#dvLangSwitch span").click(function () {
var t = $(this).text();
var lang = "DEF";
switch (t) {
case "中文":
lang = "DEF";
break;
case "英文":
lang = "ENG";
break;
case "簡中":
lang = "CHS";
break;
}
jQuery.switchLang(lang);
});
$("#btnSubmit").click(function () {
var v = $("#txtEmpName").val();
if (v.length == 0) {
//呼叫ml函數(Multi-Language縮寫),可以自動換訊息
alert(ml("員工姓名不可空白!"));
} else if (v.match("[0-9_!@#$%^&*()<>]"))
//可以利用{0}, {1}加入變動內容
alert(ml("員工姓名有無效字元: {0}", v));
});
});
</script>
<style type="text/css">
#dvLangSwitch span
{
color: Blue; text-decoration: underline;
margin-left: 5px; cursor: pointer
}
body, table { font-size: 9pt; }
#tblFillForm { width: 400px; }
#tblFillForm td { border: 1px solid #dddddd; }
td.hdr { text-align: right; padding-right: 10px; }
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="dvLangSwitch"><span>中文</span><span>英文</span><span>簡中</span></div>
<div>
<table id="tblFillForm">
<tr><td class="dtml hdr" style="width: 100px">員工姓名</td>
<td><input type="text" id="txtEmpName" /></td></tr>
<tr><td class="hdr"><span class="dtml">通訊選項</span></td><td>
<select id="txtContChan" class="dtml">
<option value="MSN">MSN</option>
<option value="Yahoo">即時通</option>
<option value="Plurk">噗浪</option>
</select>
</td></tr>
<tr><td></td>
<td><input type="button" id="btnSubmit" value="送出" class="dtml" /></td></tr>
</table>
</div>
</form>
</body>
</html>
這個網頁跟一般非多語系網頁做法差不多,但我用黃底標出了幾個為了配合多國語系而加的東西。
首先,HTML中還是直接寫死預設語系文字,若針對切換語系時要變化的內容,要多加一個class "dtml"。在本範例中,有td, span, select, input加上了多國語系支援。當jQuery. setupMultiLang時,要指定一個多語系資源檔,雖然XML可能是更好的選擇,但我決定用HTML Table做為儲存對照文字的格式,主要考量在於它可直接用現成網頁編輯工具維護,不需要再生工具。而setupMultiLang時背後有個小機關,它會找出所有標示dtml Class的元素,取出其內容,在UI.lang.htm中比對出它是哪一筆資料,自動定義Resource Key,這種看似沒效率且不怎麼可靠(因為HTML中的文字要跟UI.lang.htm欄位的內容一字不差)的做法,卻可以省下為每個資料定義唯一Resource Key的可觀工程(暴躁大叔表示欣慰)。
在本例中,UI.lang.htm長像如下。第一欄的標記可以用來放#btnSubmit之類的jQuery Selector用以準確鎖定特定元素,會比用文字內容比對決定Resource Key來得可靠,效率也更好;第二欄位則用來標註該內容用於更換SELECT選項清單、INPUT的value或是一般元素的innerHTML;第三欄為預設語系的文字內容,就是HTML使用的語系;第四欄以後則是其他語系資料。
最後,在範例中,順便展示了怎麼讓Javascript也支援多語系文字內容的做法,其中有個ml(...)函數可以查表將預設語系文字轉換成目前語系的內容(一樣用的是比對法,故記得要使其與DEF內容一字不差),而ml("... {0} {1}", v1, v2)的寫法可應用在需穿插動態內容的場合。
經過上述一番惡搞,用了不算太複雜的寫法跟規則,就弄出了一個支援中文、英文跟簡體中文三種語系的介面:
這就是目前我的構想,有興趣的朋友可以下載回去玩(下載解壓如有問題,請用IE以外的瀏覽器試試[原委]),並歡迎將應用時發現的問題反映給我,做為改良參考,感謝!
Comments
# by Wolke
黑大你好: 我有用JQuery做一個語言包的程式, 完全在Client端解決多語系的問題了, 我自已是用的還不錯啦! 歡迎參觀看看! http://wolke-codes.blogspot.com/2010/07/wolke-jquery-language-tools-wolke.html 我的網站,作品集裡也有Demo http://wolke-web-app.appspot.com/
# by Will 保哥
切換語系的地方感覺用 span 怪怪的,用 a 標籤比較符合語意,然後套用 class="DEF" 之類的,少用 switch case 程式碼比較短些。另外,用標準的 zh-TW 似乎比較具有語系的概念。
# by Jeffrey
to 保哥,哈! 切換語系的地方是亂亂寫的(因為實務上大家多半會視Browser語系或使用者Profile決定語系,不會直接用這種方式),不過用class="DEF"是好主意,取zh-TW的建議也很值得考量,十分感謝!
# by 疑惑者
請問您有放在主機上run過嗎? 下載您的範例後,在本機電腦都沒問題 但若是放在主機上,再去開啟UI.htm 都會出現 : multiLangToolbox 未被定義的錯誤
# by Jeffrey
to 疑惑者, 這個做法使用的都是純js加html,理論上對部署主機沒什麼條件限制,只要擺進htm及js後都能正常下載即可。我唯一想到的是編碼問題,若js檔案被當成ANSI編碼,有可能出現一些奇怪狀況: http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/05/04/747.aspx 若是你主機有對Internet開放,提供連結大家可幫忙看。
# by 真相
員工改為教師 其對應employee -> teacher 如何增列呢??? 謝謝您 by 一位菜鳥
# by Jeffrey
to 真相,不是很明白你的問題。員工改為教師是指 員工姓名->教師姓名, Employee Name->Teacher Name 這樣嗎?
# by 宥
請問範例檔的ui.html頁面打開 出現 ---------- Java script通知 ui .lang.htm is missing BEGIN/END mark ---------- 是甚麼狀況 然後暗了確認知後 語言是無法照著按鈕切換
# by Jeffrey
to 宥,請問直接下載範例放在網站執行就出錯嗎?使用的瀏覽器版本為何? 我放了一個Live Demo http://www.darkthread.net/miniajaxlab/multilang/ui.htm 可以比對看看有何差異?