轉自 http://www.cnblogs.com/think8848/archive/2011/03/15/1984793.html
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" ; |
範例程式碼
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" ; |
範例程式碼