ASP.NET MVC 3 Razor 多國語言參考解決方案

 

3月22日整理:實用示例請參考:這裏

支持多國語言基本上是一個成熟產品必須支持的功能,但是直到想用這個功能時,發現居然找不到解決方案(很喫驚,真的沒有提供麼?),於是在網上搜索了好久,發現兩種心儀的方案:

1: ASP.NET MVC 多語言解決方案

2: ASP.NET MVC - Localization Helpers

這兩種方案都是針對WebFormViewEngine的,對於想使用Razor的我來說,修改是必然的了

先說說第二種,這個方法貌似核心是使用了HttpContext.GetLocalResourceObject()方法。但是問題在於在使用GetLocalResourceObject()方法時,需要提供一個參數virtualPath,這個參數花了好久心思沒有成功,關鍵是上面有句代碼老是會拋異常:

ResourceExpressionFields fields = (ResourceExpressionFields)builder.ParseExpression(expression, typeof(string), context);

總是說expression不對之類的,我猜應該是在WebFormViewEngine裏面綁定表達式不能在Razor裏使用的原因吧,但是我偷偷的模擬了一個WebForm式的綁定表達式,依然不能執行通過。而且官方也沒有提供一個完整的示例,時間關係我也不想研究了,如果有人在Razor上試驗成功了,麻煩留個言。

再來說第一種,個人感覺習慣上這個除了一樣,其它的啥都好,哪一樣呢,就是必須使用RexGen來編譯.resx文件,使其成爲.resources文件,然後再去使用。在以前使用WebPage時是沒有這一步的,多一步總沒有少一步來的方便,因此又打開MSDN來看看,一看發現一個類型:ResXResourceReader,從這個類型的名稱上看就是一個好東西,但是在寫代碼時居然發現找不到該類型?再仔細一看,原來這個類型居然是定義在System.Windows.Forms命名空間中的,在Web程序中加入System.Windows.Forms.dll引用總感覺是怪怪的,但是想想都是.NET的標準類庫,加起來應該也沒有太大的影響,再說還不知道加進來能不能用。

於是參照第一種解決方案做出一個助手類:

    public static class LocalizationHelpers
    {
        public static string Lang(this HtmlHelper htmlhelper, string key)
        {
            var viewPath = (htmlhelper.ViewContext.View as BuildManagerCompiledView).ViewPath;
            var viewName = viewPath.Substring(viewPath.LastIndexOf('/'), viewPath.Length - viewPath.LastIndexOf('/')).TrimStart('/');
            var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.LastIndexOf('/') + 1)) + "App_LocalResources";
            var langs = htmlhelper.ViewContext.HttpContext.Request.UserLanguages;
  
            string resxPath = string.Format(@"{0}\{1}.resx", filePath, viewName);
  
            foreach (var lang in langs)
            {
                if (File.Exists(string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang)))
                {
                    resxPath = string.Format(@"{0}\{1}.{2}.resx", filePath, viewName, lang);
                    break;
                }
            }
  
            string result = "";
  
            ResXResourceReader reader = new ResXResourceReader(resxPath);
            var entry = reader.Cast<DictionaryEntry>().FirstOrDefault<DictionaryEntry>(x => x.Key.ToString() == key);
  
            if (entry.Value != null)
            {
                result = (string)entry.Value;
            }
  
            return result;
        }
    }

 

這個方案應該只能算是一個參考原型,還有很多可以改進的地方,比如方法裏沒有使用CultureInfo之類的東西,因爲我們公司通常的方案是語言隨着瀏覽器的語言設定來的,爲了測試簡單點,我只是根據Request裏面的UserLanguages來確定顯示何種語言,另外,每次都new一個Reader是否會對性能帶來較大的影響也未經測試,不過最基本的功能有了,使用該方案,可以像在WebPage裏面一樣方便的使用資源文件了。

對了,差點忘了很重要的內容,如何使用該方法:

@Html.Lang("Test")

即可,"Test"爲資源的Key

值的一提的是,這個LocalizationHelpers類型命名空間需爲System.Web.Mvc

如果大家有更好的方案,請通知我,謝謝

修改:在示例源碼中LocalizatioinHelpers第16行錯誤,

var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.Length - viewPath.LastIndexOf('/'))) + "App_LocalResources";

修正如下:

var filePath = htmlhelper.ViewContext.HttpContext.Server.MapPath(viewPath.Substring(0, viewPath.LastIndexOf('/') + 1)) + "App_LocalResources";

示例代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章