前言:
好多年没写文章了,工作很忙,天天加班, 每天都相信不用多久,就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰,想想还有点小激动~~~~
直到后来发生了邮箱事件,我竟然忘了给邮箱密码赋值,导致遇到“邮箱不可用。 服务器响应为: 5.7.1 Unable to relay for”的问题,网上一查后,让Boss去设置IIS里的SMTP。
结果Boss力证不用设置也可以发,还给我发了N多Demo代码,让我蛋碎一地, 最后那点小激动,就在这小事件上栽没了~~~
好了,不多扯了,回正文吧~~~
引子:
关于系统的多语言,我在之前的文章都写过不少,包括秋色园QBlog的开源博客里,也有相应的实现方案,不过随着项目环境的不同,往往实现的方案也不尽相同。
今天就来扯扯,ASP.NET MVC下的方案。
1:数据的多语言:
在QBlog里,数据的多语言,我是分成两种方案一起处理:
A:多条数据,文章数据,用一个语言字段来标识该条数据为何种语言。
B:对于其它数据,标题,公告等,用一个[#LangSplit]标识来分隔前后两种语言。
不过现在的方案有点不同,看如下图:
看到大量的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多语言的语法方案
配套的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, @"[#([Ss]*?)#]", 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 多语言定义
<script> var lang={loginID:”[#LoginID#]”,userName:”[#UserName#]”}; <script>
该View会在Controller端提前会替换成相应语言的文字。
总结:
以上的多语言方案,有特定的项目环境背景,仅供参考,讨论,借鉴,反省,请勿轻易模仿。
谢谢观赏。