深入研究.NET Core的本地化機制
ASP.NET Core中提供了一些本地化服務和中介軟體,可將網站本地化為不同的語言文化。
ASP.NET Core中我們可以使用 Microsoft.AspNetCore.Localization 庫來實現本地化。
在.NET Core 2.0以上版本, Microsoft.AspNetCore.Localization 已經包含在了 Microsoft.AspNetCore.All 中,所以我們並不需要手動引入其他的類庫。
建立一個MVC網站
為了測試ASP.NET Core的本地化,我們首先在Visual Studio 2017中建立一個MVC專案LocalizationSample。
配置Startup類
ASP.NET Core中,如果希望啟動本地化,首先需要在 Startup
類的 ConfigureServices
方法中使用 services.AddLocalization
新增本地化服務。
public void ConfigureServices(IServiceCollection services) { services.AddLocalization(o => { o.ResourcesPath = "Resources"; }); services.AddMvc(); }
在這個方法中,我們指定了資料夾Resources作為存放翻譯檔案的目錄。
注: 如果不指定存放翻譯檔案的目錄, ASP.NET Core會預設從網站根目錄下讀取。
然後我們需要在 Configure
方法中新增本地化中介軟體。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseStaticFiles(); IList<CultureInfo> supportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("zh-CN"), }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("en-US"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
-
app.UseRequestLocalization
必須放置app.UseMvc
之前 -
DefaultRequestCulture
引數指定了預設的語言文化,即使用者不指定任何文化時的預設語言文化 -
SupportedCultures
和SupportedUICultures
是指定當前應用支援的所有語言文化
注: SupportedCultures
指定的是數字和日期格式, SupportedUICultures
指定的翻譯檔案
新增資原始檔
下面我們嘗試新增一個資原始檔
Startup
在Controller中獲取本地化字串
現在我們開啟預設生成的 HomeController
, 清空裡面所有的action, 並新增一個新的action, 程式碼如下:
public class HomeController : Controller { public HomeController() { } public IActionResult Hello() { return Content("Hello"); } }
啟動專案之後訪問/Home/Hello, 結果如下
下面我們修改HomeController的程式碼, 來引入本地化字串訪問器
public class HomeController : Controller { private readonly IStringLocalizer<HomeController> _localizer; public HomeController(IStringLocalizer<HomeController> localizer) { _localizer = localizer; } public IActionResult Hello() { return Content(_localizer["Hello"]); } }
程式碼解釋
-
IStringLocalizer
是一個本地化字串訪問器的泛型介面,這裡我們通過依賴注入的方式在HomeController
的建構函式中將其注入 - 我們可以通過IStringLocalizer的屬性訪問器獲取到對應欄位在不同語言下的文字。
最終效果
現在我們啟動程式, 重新訪問/Home/Hello, 結果如下
你會發現結果沒有變化,這是因為預設我們設定的語言文化是en-US, 但是我們之前沒有新增en-US的資原始檔,所以程式就直接將訪問的欄位名輸出了。
現在我們修改URL, 訪問/Home/Hello?ui-culture=zh-CN, 結果如下
我們期望的“你好”被正確輸出了,這說明ASP.NET Core預設支援在Url中以culture引數的形式設定當前網站使用的語言文化。
資原始檔命名
為什麼我們之前添加了一個名為Controllers.HomeController.zh-CN.resx的資原始檔,本地化字串訪問器 IStringLocalizer
就能定位到這個檔案並讀取其中的欄位屬性呢?
這是由ASP.NET Core資原始檔的命名約定決定的。
ASP.NET Core資原始檔的名稱由2部分組成:
- 去掉程式集名稱的完整類名
- 語言文化名稱
以前面的例子為例:
我們建立了一個本地化字串訪問器介面,它的泛型型別是 HomeController
, 其完整類名是 LocalizationSample.Controllers.HomeController
, 當前程式集的名稱是 LocalizationSample
, 所以去掉程式集名稱之後,剩餘部分是 Controllers.HomeController
。當我們設定culture引數是zh-CN時, ASP.NET Core查詢的資原始檔名是Controllers.HomeController.zh-CN.resx, 這正是我們前面新增的中文語言文化資原始檔名。
如果你不喜歡這種方式,ASP.NET Core還提供了另外一種資原始檔的組織方式
你可以Resources目錄下建立以下目錄結構
- Resources
- Controllers
- HomeController.zh-CN.resx
- Controllers
本地化字串訪問器也能自動定位到這個檔案。
預設的語言文化提供器
ASP.NET Core的本地化中介軟體預設支援3種語言文化提供器
- URL中的查詢字串
- Cookie
- 請求頭
URL中的查詢字串
ASP.NET Core會從URL中的culture引數中獲取當前應用使用的語言文化,這就是前面例子中,“你好”能正確輸出的原因
除了指定ui-culture引數,你還可以使用culture引數指定當前格式化時間,數字等所使用的語言文化。
?culture=zh-CN&ui-culture=zh-CN ?culture=zh-CN ?ui-culture=zh-CN
Tips: 當只指定culture或ui-culture引數時,ASP.NET Core會自動將culture和ui-culture設定成一樣的。即?culture=zh-CN等同於?culture=zh-CN&ui-culture=zh-CN
Cookie
ASP.NET Core中還支援使用Cookie的方式設定當前應用使用的語言文化。預設使用的Cookie名稱是.AspNetCore.Culture。
.AspNetCore.Culture的值格式如下
c=zh-CN|uic=zh-CN c=zh-CN uic=zh-CN
其中c表示culture, uic表示ui-culture。
下面我們使用Chrome的開發者工具, 為當前網頁新增語言文化Cookie
然後我們訪問/Home/Hello, "你好"也被正確的輸出了

這說明ASP.NET Core從Cookie中讀取到了語言文化配置
請求頭
除了URL查詢字串和Cookie, ASP.NET Core還支援在請求頭中指定語言文化。請求頭中語言文化欄位名稱是 Accept-Language。
Accept-Language的文件,參見 HTTP/Headers/Accept-Language" rel="nofollow,noindex" target="_blank">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Language
這裡我們使用Postman來測試一下,我們設定Accept-Language為zh-CN, zh;q=0.9, 結果如下
如何在View中使用本地化
除了Controller, 我們更多的是在View中使用本地化。
如果希望在View中使用本地化,首先需要在 Startup
類的 ConfigureServices
方法中啟用View本地化。
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix); }
這裡 LanguageViewLocationExpanderFormat
支援2種方式,這個和前面Controller的本地化檔名稱約定類似
- Suffix, 例/Resources/Home/Hello.zh-CN.resx
- Path, 例/Resources/Home/zh-CN/Hello.resx
下面我們修改HomeController的程式碼, Hello
方法將返回一個View
HomeController
public IActionResult Hello() { //return Content(_localizer["Hello"]); return View(); }
Hello.cshtml
@{ ViewData["Title"] = "Hello"; } <h2>Good Bye</h2>
然後我們建立如下圖的目錄結構, 並建立資原始檔Hello.zh-CN.resx, 並新增GoodBye欄位,其值為"再見"

使用ViewLocalizer
ViewLocalizer
類可以幫助我們在Razor檢視中使用本地化文字。現在我們來修改Hello.cshtml, 在檔案新增本地化引用,並注入一個ViewLocalizer物件
@using Microsoft.AspNetCore.Mvc.Localization @inject IViewLocalizer Localizer @{ ViewData["Title"] = "Hello"; } <h2>@Localizer["GoodBye"]</h2>
這裡我們使用ViewLocalizer讀取了本地化文字,它的用法和 IStringLocalier
一樣,都是通過屬性訪問器訪問對應欄位的本地化文字。
最終效果
現在我們執行程式並訪問/Home/Hello, 結果如下

然後我們繼續訪問/Home/Hello?ui-culture=zh-CN, 結果如下

本地化字串讀取成功
本篇原始碼 https://github.com/lamondlu/aspnetcore_localizationsample