asp.net mvc下的多语言方案 包含Html,Javascript和图片

在网上查阅了众多方案,觉得路过秋天的方案 解耦性比较好,可以不使用微软的Resource文件,而是将所有的词汇放入在一个txt的词典之中,便于维护。

步骤如下:

1)在整个程序的入口处global.asax.cs加入函数

 private void ReadDic(string dicFileName)
        {
            var dicPath = Path.Combine(Server.MapPath("/File"), dicFileName);
            string dicStr;
            using (var fs = new StreamReader(dicPath, Encoding.UTF8))
            {
                dicStr = fs.ReadToEnd();
            }
            var englishDict = new Dictionary<string, string>();
            var chineseDict = new Dictionary<string, string>();
            var strs = dicStr.Split(new[] { "
" }, StringSplitOptions.RemoveEmptyEntries);
            string[] temp;
            foreach (var str in strs)
            {
                temp = str.Split('|');
                englishDict.Add(temp[0], temp[1]);
                chineseDict.Add(temp[0], temp[2]);
            }
            MyConst.chineseDictionary = chineseDict;
            MyConst.englishDictionary = englishDict;
        }

该函数的目的是将位于网站目录“File”下的词典文件,如dict.txt以键值对的形式读取到程序的内存之中,以便随时使用。

Dict.txt的内容形如:

Add|Add|增加
LearningInfo|Learning Info|学习资讯
NewColumn|New Column|新建栏目
......

第一列为key,第二列为要显示的英文,第三列为要显示的中文。

2)通过cookie切换语言

在点击切换后,调用

switchLang(),相应的cultrueInfo分别为zh-CN和en-US.

相应的js代码为

function switchLang(cultureInfo) {
    deleteCookie("culture");
    addCookie("culture", cultureInfo, 720);//cookie持续一个月
    location.reload();
}
function addCookie(name, value, expiresHours) {
    var cookieString = name + "=" + escape(value);
    //判断是否设置过期时间 
    if (expiresHours > 0) {
        var date = new Date();
        date.setTime(date.getTime() + expiresHours * 3600 * 1000);
        cookieString = cookieString + "; expires=" + date.toGMTString() + ";  path=/";
    }
    document.cookie = cookieString;
}
function getCookie(name) {
    var strCookie = document.cookie;
    var arrCookie = strCookie.split("; ");
    for (var i = 0; i < arrCookie.length; i++) {
        var arr = arrCookie[i].split("=");
        if (arr[0] == name) return arr[1];
    }
    return "";
}

function deleteCookie(name) {
    var date = new Date();
    date.setTime(date.getTime() - 10000);
    document.cookie = name + "=v; expires=" + date.toGMTString();
}

3)本方案的核心逻辑在于:首先获取到输出到浏览器渲染的html代码,用词典中对应的键使用正则表达式匹配html中相应的词,然后再将全部匹配到的词替换,最后再重新输出到浏览器。

于是改写Html代码

例如:本来纯中文的视图中会这么写:

<span>新建栏目</span>

现在改为:

<span>[#NewColumn#]</span>
AddColumn即为词典中对应的键。

4)设置了cookie,然后就可以在后台的Request中使用。然后,为了做到这一点,需要在输出时给控制器加一个切面——一个自定义的HtmlReplaceFilter特性。代码如下:

  public class ReplaceHtmlFilter : ActionFilterAttribute
    {
       
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (filterContext.Result is ViewResult)
            {
                string html = RenderViewToString(filterContext.Controller, ((ViewResult)filterContext.Result).View);
                var httpCookie = filterContext.HttpContext.Request.Cookies["culture"];
                if (httpCookie != null)
                {
                    var cookie = httpCookie.Value;
                    html = Replace(html, cookie);
                }
                else
                {
                    html = Replace(html, "zh-CN");
                }
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.Write(html);
            }
          
        }

        private static string RenderViewToString(ControllerBase controller, IView view)
        {
            using (var writer = new System.IO.StringWriter())
            {
                var viewContext = new ViewContext(controller.ControllerContext, view, controller.ViewData, controller.TempData, writer);
                viewContext.View.Render(viewContext, writer);
                return writer.ToString();
            }
        }
        /// <summary>
        /// 替换多语言。
        /// </summary>
        /// <param name="html"></param>
        /// <param name="lang"></param>
        /// <returns></returns>
        private string Replace(string html, string lang)
        {
            MatchCollection matchs = Regex.Matches(html, @"[#([Ss]*?)#]",
                RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (matchs != null && matchs.Count > 0)
            {
                var 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;
        }

        private Dictionary<string, string> GetLanguageDic(string lang)
        {
            if (lang == "zh-CN")
            {
                return MyConst.chineseDictionary;
            }
            else
            {
                return MyConst.englishDictionary;
            }
        }

将该Filter加在Controller上,至此,html的中英文切换即可实现。

5)Javascript中的多语言则需多做一步。

在视图文件中,加入类似如下的词典对象。

<script>
        var lang = {
            AllCourses:"[#AllCourses#]",
            AddCourseColumn:"[#AddCourseColumn#]",
            AtLeastOneRow: "[#AtLeastOneRow#]",
            DeleteSelected: "[#DeleteSelected#]",
        };
 </script>

注意,该词典的内容实现也需要添加在dict.txt文件中。

然后,在js代码中

原本为

alert("全部课程");

改为

alert(lang.AllCourses);

由于在输出视图时,所有形如[##]的文本都会被替换为字典里相应的语言,这样js就可以输出多语言了。

6)最后图片也是类似。

注意,图片要制作多语言版本的,即如果之前都是中文,那么要制作一套英文的图片。

然后在视图中,原本为

<img  src='btn1.png ' />

改为

<img  src='[#btn1#] ' />

字典中加入类似

btn1|cntn1.png|entn1.png    

即可起到图片的多语言切换作用。

原文地址:https://www.cnblogs.com/Benjamin/p/3544886.html