前言:
好多年沒寫文章了,工做很忙,每天加班, 天天都相信不用多久,就會升職加薪,當上總經理,出任CEO,迎娶白富美,走上人生巔峯,想一想還有點小激動~~~~html
直到後來發生了郵箱事件,我居然忘了給郵箱密碼賦值,致使遇到「郵箱不可用。 服務器響應爲: 5.7.1 Unable to relay for」的問題,網上一查後,讓Boss去設置IIS裏的SMTP。數據庫
結果Boss力證不用設置也能夠發,還給我發了N多Demo代碼,讓我蛋碎一地, 最後那點小激動,就在這小事件上栽沒了~~~json
好了,很少扯了,回正文吧~~~服務器
引子:
關於系統的多語言,我在以前的文章都寫過很多,包括秋色園QBlog的開源博客裏,也有相應的實現方案,不過隨着項目環境的不一樣,每每實現的方案也不盡相同。ide
今天就來扯扯,ASP.NET MVC下的方案。 this
1:數據的多語言:
在QBlog裏,數據的多語言,我是分紅兩種方案一塊兒處理:spa
A:多條數據,文章數據,用一個語言字段來標識該條數據爲什麼種語言。3d
B:對於其它數據,標題,公告等,用一個[#LangSplit]標識來分隔先後兩種語言。調試
不過如今的方案有點不一樣,看以下圖:code
看到大量的Xml字段了吧,這就是上一個項目繼承而來的精華,在項目裏動不了事實存在。
關於表名和字段命名方式,走的是國際範,大夥不要學。
針對Xml,須要有一小套處理方案:
數據庫以Xml字段存檔多語言,格式爲:
<
ML
V
="1.0"
>
<
M
L
="zh-cn"
>中文
</
M
>
<
M
L
="en"
>English
</
M
>
<
M
L
=".."
>其它語言
</
M
>
</
ML
>
而後針對這種存檔,須要有相應的處理:
SQL:查詢語法爲:
取值:字段名.value('(/ML/M[@L="zh-cn"])[1]','nvarchar(max)')
取節點:字段名.query('/ML/M[@L="en"]')
判斷:字段名.exists('/ML/M[@L="zh-cn"]')
排序:用取值後的字段名進行排序
處理流程大致以下:
2:UI多語言
2.1:MVC View的多語言流程:
通過對MVC的源碼調試,發如今Control基類(本身定義)統一處理便可。
Demo代碼:
protected
override
void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Result
is ViewResult)
{
string html = RenderViewToString(
this, ((ViewResult)filterContext.Result).View);
html = LanguageMgr.Replace(html,
"
zh
");
Response.Clear();
Response.Write(html);
}
}
protected
static
string RenderViewToString(Controller controller, IView view)
{
//
IView view = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, masterName).View;
using (System.IO.StringWriter writer =
new System.IO.StringWriter())
{
ViewContext viewContext =
new ViewContext(controller.ControllerContext, view, controller.ViewData, controller.TempData, writer);
viewContext.View.Render(viewContext, writer);
return writer.ToString();
}
}
一開始的想法是處理完後寫回去,後來調試了半天源碼發現找不到寫回去的,靈光一閃,發現數據在Response.OutPut流裏,直接清空,輸出新的Html便可。
2.2:JS腳本的多語言流程:
具體的實現,看下面的語法定義。
3:UI多語言的語法方案
界面標籤訂義:[#對象名稱-字段名#],標籤內不容許帶有空格。
或者直接:[#字段名#](由Controller自動取得對象名稱處理)
例如:[#UserID#] 或者[#Login-UserID#]
中文時將被替換成:登錄名,英文就是Login了。
配套的Demo實現:
public
class LanguageMgr
{
///
<summary>
///
替換多語言。
///
</summary>
///
<param name="html"></param>
///
<param name="lang"></param>
///
<returns></returns>
public
static
string Replace(
string html,
string lang)
{
MatchCollection matchs = Regex.Matches(html,
@"
\[#([\S\s]*?)#\]
", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (matchs !=
null && matchs.Count >
0)
{
List<
string> keys =
new List<
string>(matchs.Count);
//
記錄已匹配過的
Dictionary<
string,
string> dic = GetLanguageDic(lang);
foreach (Match match
in matchs)
{
string text = match.Groups[
0].Value;
string key = match.Groups[
1].Value.Trim();
if (!keys.Contains(key))
{
keys.Add(key);
if (dic.ContainsKey(key))
{
html = html.Replace(text, dic[key]);
}
}
}
keys =
null;
matchs =
null;
}
return html;
}
internal
static Dictionary<
string,
string> GetLanguageDic(
string lang)
{
Dictionary<
string,
string> dic =
new Dictionary<
string,
string>();
dic.Add(
"
aaa
",
"
中文
");
dic.Add(
"
bbb
",
"
英文
");
return dic;
}
}
4: JavaScript 多語言定義
對於JavaScript須要在客戶端調用的多語言,能夠在View中進行以下定義語言json:
<
script
>
var lang={loginID:」[#LoginID#]」,userName:」[#UserName#]」};
<script>
該View會在Controller端提早會替換成相應語言的文字。
以後的引用調用alert(lang.loginID)便可。
總結:
以上的多語言方案,有特定的項目環境背景,僅供參考,討論,借鑑,檢討,請勿輕易模仿。
謝謝觀賞。