CODE-jQuery Client-Side多國語系切換設計之Server端補充包
| | | 0 | |
前陣子,我提出一個以jQuery實作網頁多語系切換的點子,主張透過UI.htm維護文字對照表,提供js以Class註記加查表的方式,讓網頁可直接呈現預設語系文字(傳統上要將可切換文字全都換成代碼,可讀性大減),再用對照方式查出並置換為其他語系內容。
同事迫於我的淫威在了解該架構的便利性後,開始逐步在專案中試用。今天同事MSN給我,許了一個願:
呼叫ml("預設語系文字內容")傳回其他語系對照的做法在寫Javascript時很好用,但很希望在aspx.cs端也提供相同功能!!
身為始作俑者元件供應者,幫開發人員實現心願是責無旁貸的使命,所以花了點時間寫了jQueryMultiLangAgent類別來滿足需求。
將jQueryMultiLangAgent.cs(程式碼如下)放在App_Code或編譯入專案中,就可在C#裡指定UI.htm(Yes! 與前端共用)建構jQueryMultiLangAgent物件,接著可由Languages取得所有支援語系的清單,指定好CurrentLanguage,就能呼叫MapText()將預設語系文字轉成指定語系的內容囉!
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.IO;using System.Text.RegularExpressions;using System.Web.Caching;public class jQueryMultiLangAgent
{ //文字對照表資料物件public class MultiLangData
{public List<string> Languages;
public Dictionary<string, int> IndexBook;
public Dictionary<string, List<string>> TextDictionary;
}
//UI.htm的實體路徑public string LangFilePath;
//對照表存於Cache中,發現不存在時就重新產生 public MultiLangData Data {get
{if (HttpContext.Current.Cache[LangFilePath] == null)
{ string html = File.ReadAllText(LangFilePath); //取出標記資料區塊 #region Extract the part between <!-- BEGIN --> and <!-- END -->int x = html.IndexOf("<!-- BEGIN -->");
int y = html.IndexOf("<!-- END -->");
if (x == -1 || y == -1)throw new ApplicationException(
string.Format("{0} is missing BEGIN/END mark!",
LangFilePath));
html = html.Substring(x + 14, y - x - 14);
#endregionDictionary<string, List<string>> dictionary =
new Dictionary<string, List<string>>();
Dictionary<string, int> index = new Dictionary<string, int>();
//SelectChildElements, GetInnerHTML用Regex解析tr, th, td等元素內容取值List<string> trs = SelectChildElements(html, "tr");
//取得全部的語系代碼,最前面的當成預設語系List<string> langs = SelectChildElements(trs.First(), "th").Skip(2)
.Select(o => GetInnerHTML(o)).ToList();
foreach (string lang in langs)
dictionary.Add(lang, new List<string>());
int count = 0;foreach (string tr in trs.Skip(1))
{List<string> tdHtmls = SelectChildElements(tr, "td").Skip(2)
.Select(o => GetInnerHTML(o)).ToList();
//最前面的文字欄位為預設語系 if (index.ContainsKey(tdHtmls[0]))throw new ApplicationException("Duplicated Text - " + tdHtmls[0]);
//記錄索引位置,未來用Dictionary以文字查出位置index.Add(tdHtmls[0], count++);
//逐一放入各語系文字for (int i = 0; i < langs.Count; i++)
dictionary[langs[i]].Add(tdHtmls[i]);
}
//將資料物件存入Cache,並與檔案設定相依性 HttpContext.Current.Cache.Add(LangFilePath, new MultiLangData() {Languages = langs,
IndexBook = index,
TextDictionary = dictionary
}, new System.Web.Caching.CacheDependency(LangFilePath),Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.High, null);
}
return HttpContext.Current.Cache[LangFilePath] as MultiLangData;
}
}
#region Language Options //所有可用語系清單public List<string> Languages
{ get { return Data.Languages; }}
private string currLang = "NA";
//目前指定語系public string CurrentLanguage
{ get { return currLang; } set {if (!Languages.Contains(value))
throw new ApplicationException(
"Language " + value + " not defined!");
currLang = value;}
}
#endregion //將預設語系文字轉為目前指定語系文字,支援string.Formatpublic string MapText(string text, params object[] args)
{ if (!Data.IndexBook.ContainsKey(text))throw new ApplicationException(
"'" + text + "' not found in default language.");
return string.Format(
Data.TextDictionary[CurrentLanguage][Data.IndexBook[text]], args);
}
//建構式,指定UI.htm,取得預設語系時會觸發UI.htm解讀程序public jQueryMultiLangAgent(string langHtmlPath)
{LangFilePath = HttpContext.Current.Server.MapPath(langHtmlPath);
CurrentLanguage = Languages[0];
}
#region Parser Utilityprivate static List<string> SelectChildElements(string html, string tag)
{List<string> lst = new List<string>();
foreach (Match m in Regex.Matches(html, string.Format("<{0}>.*?</{0}>", tag),
RegexOptions.Singleline | RegexOptions.IgnoreCase))
lst.Add(m.Value);
return lst;}
private static string GetInnerHTML(string html)
{int st = html.IndexOf(">") +1, ed = html.LastIndexOf("<");
return html.Substring(st, ed - st).Trim(' ', '\r', '\n');
}
#endregion}
應用範例如下:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;public partial class MultiLang_UI : System.Web.UI.Page
{ jQueryMultiLangAgent mlAgent = new jQueryMultiLangAgent( "UI.lang.htm");string demoString = "員工姓名有無效字元: {0}";
private void showText()
{mlAgent.CurrentLanguage = ddlLangs.SelectedItem.ToString();
lblText.Text = mlAgent.MapText(demoString, "SUCC");}
protected void Page_Load(object sender, EventArgs e)
{ if (!Page.IsPostBack) {ddlLangs.DataSource = mlAgent.Languages;
ddlLangs.DataBind();
showText();
}
}
protected void btnSwitch_Click(object sender, EventArgs e)
{showText();
}
}
歡迎指教!
Comments
Be the first to post a comment