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); |
ResXResourceReader reader = new ResXResourceReader(resxPath); |
var entry = reader.Cast<DictionaryEntry>().FirstOrDefault<DictionaryEntry>(x => x.Key.ToString() == key); |
result = ( string )entry.Value; |
這個方案應該只能算是一個參考原型,還有很多可以改進的地方,比如方法裏沒有使用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" ; |
示例代碼