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);
#endregion
Dictionary<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.Format
public 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 Utility
private 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
}