• 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    

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

  • 相关阅读:
    JSP使用JDBC ODBC 实例
    Gradle templates 的使用
    Java 中使用Jackson反序列化
    Java getResourceAsStream返回为空的问题
    MVC 学习随笔(一)
    分区信息查看
    关于线程 wait notify sleep
    synchronized与Lock
    java类初始化
    oracle sql 执行原理
  • 原文地址:https://www.cnblogs.com/Benjamin/p/3544886.html
Copyright © 2020-2023  润新知