ABP官方文檔翻譯 6.3 本地化
本地化
- 介紹
- 應用程序語言
- 本地化源
- XML文件
- 註冊XML本地化源
- JSON文件
- 註冊JSON本地化源
- 資源文件
- 自定義源
- XML文件
- 當前語言是如何決定的
- ASP.NET Core
- ASP.NET MVC 5.x
- 獲取一個本地化文本
- 在服務端
- 在MVC控制器
- 在MVC視圖
- 在Javascript
- 格式化參數
- 默認本地化源
- 在服務端
- 擴展本地化源
- 獲取語言
- 最佳實踐
介紹
任何應用程序都會包含至少一種語言。許多的應用程序都包含多種語言。ABP提供了靈活的本地化系統。
應用程序語言
首要的事情是聲明支持哪種語言。在模塊的PreInitialize方法中設置,如下所示:
Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true)); Configuration.Localization.Languages.Add(new LanguageInfo("tr", "Türkçe", "famfamfam-flag-tr"));
在服務端,你可以註入並使用ILocalizationManager
ABP模板使用這個系統給用戶展示一個可以語言切換的組合框。可以嘗試創建一個模板並參考源碼了解更多。
本地化源
本地化文本可以存儲在不同的源中。甚至,你可以一個應用中使用多種源(如果你有多個模塊,每個模塊可以定義分離的本地化源,或者一個模塊定義多種源)。ILocalizationSource接口需要使用一個本地化源實現。然後,它就會自動註冊到ABP的本地化配置中。
每一個本地化源必須有一個唯一的源名稱。有如下預先定義的本地源類型。
XML文件
本地化文本可以存儲在XML文件裏。XML文件的內如大致如下所示:
<?xml version="1.0" encoding="utf-8" ?> <localizationDictionary culture="en"> <texts> <text name="TaskSystem" value="Task System" /> <text name="TaskList" value="Task List" /> <text name="NewTask" value="New Task" /> <text name="Xtasks" value="{0} tasks" /> <text name="CompletedTasks" value="Completed tasks" /> <text name="EmailWelcomeMessage">Hi, Welcome to Simple Task System! This is a sample email content.</text> </texts> </localizationDictionary>
XML文件必須是unicode(utf-8)編碼。culture="en"聲明標示這個XML文件包含英文文本。對於文本節點,name屬性用來定義文本。你可以使用value屬性或inner text(如最後一個)來設置本地化文本的值。我們為每一個種語言創建一個單獨的XML文件,如下所示:
SimpleTaskSystem為源名稱,SimpleTaskSystem.xml定義了默認的語言。當文本請求的時候,ABP從當前語言的XML文件中(使用Thread.CurrentThread.CurrentUICulture)獲取文本。如果它在當前語言中不存在,則從默認語言的XML文件中獲取。
註冊XML本地化源
XML文件可以存儲在文件系統或嵌入到程序集中。
對於文件系統存儲的XMLs,我們可以按如下所示註冊一個XML本地化源:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "SimpleTaskSystem", new XmlFileLocalizationDictionaryProvider( HttpContext.Current.Server.MapPath("~/Localization/SimpleTaskSystem") ) ) );
這在模塊的PreInitialize事件中完成(參見模塊系統了解更多)。ABP在指定目錄查找所有的XML文件並註冊為本地化源。
對於嵌入XML文件,我們需要標記本地的所有的XML文件為嵌入的資源(選擇XML文件,打開屬性窗口(F4),改變生成操作為內嵌資源)。然後我們可以按如下所示註冊本地化源:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "SimpleTaskSystem", new XmlEmbeddedFileLocalizationDictionaryProvider( Assembly.GetExecutingAssembly(), "MyCompany.MyProject.Localization.Sources" ) ) );
XmlEmbedddFileLocalizationDictionaryProvider獲取包含XML文件(GetExecutingAssembly獲取當前程序集)和XML文件命名空間(命名空間由程序集名稱+XML文件的目錄層級組成)的程序集。
註意:當給嵌入的XML文件添加語言前綴時,不要使用點符號如‘MySource.tr.mxl‘,應該使用破折號如‘MySource-tr.xml‘,因為點符號會在查找資源時造成命名空間問題。
JSON文件
本地化源可以使用JSON文件來存儲文本。一個JSON本地化文件的實例如下:
{ "culture": "en", "texts": { "TaskSystem": "Task system", "Xtasks": "{0} tasks" } }
JSON文件編碼應為unicode(utf-8)。culture:"en"聲明標示這個JSON文件包含英文文本。我們我每種語言創建一個單獨的JSON文件,如下所示:
這裏,MySourceName為資源名稱,MySourceName.json文件定義了默認的語言。它和XML文件相似。
註冊JSON本地化源
JOSN文件可以存儲在文件系統或嵌入到程序集中。
如果文件系統存儲JSONs,我麽可以按如下方式註冊JOSN本地化源:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "MySourceName", new JsonFileLocalizationDictionaryProvider( HttpContext.Current.Server.MapPath("~/Localization/MySourceName") ) ) );
這些都是在模塊的PreInitialize事件中完成(參見模塊系統了解更多信息)。ABP在指定目錄查找JSON文件並註冊為本地化源。
對於嵌入JSON文件,我們需要標記本地的所有的XML文件為嵌入的資源(選擇JSON文件,打開屬性窗口(F4),改變生成操作為內嵌資源)。然後我們可以按如下所示註冊本地化資源:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "MySourceName", new JsonEmbeddedFileLocalizationDictionaryProvider( Assembly.GetExecutingAssembly(), "MyCompany.MyProject.Localization.Sources" ) ) );
JsonEmbedddFileLocalizationDictionaryProvider獲取包含XML文件(GetExecutingAssembly獲取當前程序集)和XML文件命名空間(命名空間由程序集名稱+XML文件的目錄層級組成)的程序集。
註意:當給嵌入的JOSN文件添加語言前綴時,不要使用點符號如‘MySource.tr.mxl‘,應該使用破折號如‘MySource-tr.xml‘,因為點符號會在查找資源時造成命名空間問題。
資源文件
本地化文本也可以存儲在.NET的資源文件中。我們可以為每種語言創建一個資源文件,如下所示(右鍵單擊工程,選擇添加新項然後找到資源文件):
MyTexts.resx包含默認語言文本,MyTexts.tr.resx包含Turkish語言的文本。當我們打開MyTexts.resx時,我們可以看到所有的文本:
在這種情況下,ABP使用.NET內建的資源管理器。你應該為資源配置一個本地化源:
Configuration.Localization.Sources.Add( new ResourceFileLocalizationSource( "MySource", MyTexts.ResourceManager ));
這裏源的唯一名稱為MySource。MyTexts.ResourceManager為資源管理器的一個引用用來獲取本地化文本。這在模塊的PreInitialize事件中完成(參見模塊系統了解更多信息)。
自定義源
可以實現自定義源來實現在不同的源中存儲文本,如在數據庫中。你可以直接實現ILocalizationSource接口或者你可以使用DictionaryBasedLocalizationSource類來簡化實現(json和xml本地化源也使用它)。例如,Module zero在數據庫中實現資源。
當前語言是如何決定的
ASP.NET Core
ASP.NET Core有自己的機制來決定當前語言。Abp.AspNetCore包自動添加ASP.NET Core的UseRequestLocalization中間件來請求管道。它也添加一些特殊的提供者。這裏是所有提供者的默認順序列表,他們決定HTTP請求的當前語言:
- QueryStringRequestCultureProvider(ASP.NET Core`s默認提供者):使用culture&ui-culture URL查詢字符串值。示例值:“culturee=es-MX&ui-culture=es-MX”。
- AbpUserRequestCultureProvider(ABP的提供者):如果用戶可以通過IAbpSession得知並且之前顯示的選擇了一個語言(且保存到ISettingManager),那麽就使用用戶喜歡的語言。如果用戶可以得知但是沒有選擇任何語言,且.AspNetCore.Culture cookie或header有值,使用這個信息設置用戶的語言設置並使用這個值作為當前語言。如果用戶不可得知,這個提供者什麽都不做。
- AbpLocalizationHeaderRequestCultureProvider(ABP的提供者):使用.AspNetCore.Culture header值。示例值:"c=en|uic=en-US"。
- CookieRequestCultureProvider(ASP.NET Core的默認提供者):使用.AspNetCore.Culture cookie值。示例值:“c=en|uic=en-US”。
- AbpDefaultRequestCultureProvider(ABP的提供者):如果語言(名為"Abp.Localization.DefaultLanguageNmae")有一個默認/應用程序/租戶設置值,那麽使用這個設置值。
- AcceptLanguageHeaderRequestCultureProvider(ASP.NET Core的默認提供者):使用Accept-Language header值。示例值:“tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4”。
當使用app.UseAbp()方法時,會自動添加UseRequestLocalization中間件。但是建議在認證中間件之後手動添加它(在Startup類的配置方法中),如果你的應用程序使用認證校驗的話。否則,本地化中間件可以知道當前用戶來決定最佳的語言。示例用法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseAbp(options => { options.UseAbpRequestLocalization = false; //disable automatic adding of request localization }); //...authentication middleware(s) app.UseAbpRequestLocalization(); //manually add request localization //...other middlewares app.UseMvc(routes => { //... }); }
大多數時候,如果你恰當的使用了ABP的本地化系統,那麽你不必關心它。參見ASP.NET Core本地戶文檔來更好的了解它。
ASP.NET MVC 5.x
在每一次網絡請求時ABP自動決定當前語言,並設置當前線程的culture(和UI culture)。以下是ABP默認如何決定語言的方式:
- 嘗試一個特定header值,默認名為"Abp.Localization.CultureName"。
- 如果沒找打,嘗試獲取一個特定的cookie值,默認名為"Abp.Localization.CultureName"。
- 如果沒找到,嘗試獲取默認的culture設置(設置名為"Abp.Localization.DefaultLanguageName",是定義在Abp.Localization.LocalizationSettingNames.DefaultLanguage裏的一個常量,可以使用設置管理器改變這個值)。
- 如果沒找到,嘗試獲取瀏覽器默認的語言(HttpContext.Request.UserLanguages)。
如果需要,你可以在模塊的PreInitialize方法中改變特定的cookie名稱(也是header名稱)。示例:
Configuration.Modules.AbpWeb().Localization.CookieName = "YourCustomName";
獲取一個本地化文本
創建一個 資源並註冊到ABP本地化系統之後,文本就可以很容易的本地化。
在服務端
在服務端,我們註入ILocalizationManager並使用GetString方法。
var s1 = _localizationManager.GetString("SimpleTaskSystem", "NewTask");
GetString方法基於當前線程UI culture從本地化源中獲取字符串。如果沒找到,它便使用默認語言。
如果指定的字符串沒有定義,那麽它人性化的返回指定的字符串並默認使用‘[‘和‘]‘包裝(取代拋出異常)。示例:如果給定的文本為"ThisIsMyText",那麽結果將為“[This is my text]”。這個功能是可以配置的(你可以在模塊的PreInitialize方法中使用Configuration.Localization改變它)。
為了不要重復使用資源名稱,你可以先獲得資源,然後從資源中獲取字符串:
var source = _localizationManager.GetSource("SimpleTaskSystem"); var s1 = source.GetString("NewTask");
這個返回當前語言的文本。GetString有重寫版本用來在不用的語言中獲取文本或通過參數格式化文本。
如果我們不能註入ILocalizationManager(例如在靜態context中,不能使用依賴註入系統),我們可以簡單的使用LocalizationHelper靜態類。但是盡可能的情況下註入並使用ILocalizationManager,因為LocalizationHelper是靜態的,靜態類是測試不友好的(誰編寫單元測試)。
如果你需要在應用服務、MVC控制器、Razor視圖或其他從AbpServiceBase繼承的類中本地化,可以簡單的使用L方法。
在MVC控制器
本地化文本通常在MVC控制器和視圖中都是需要的。這有一個簡便方法。參見下面控制器示例:
public class HomeController : SimpleTaskSystemControllerBase { public ActionResult Index() { var helloWorldText = L("HelloWorld"); return View(); } }
L方法用來本地化字符串。當然,你必須提供一個資源名稱。這個操作在SimpleTaskSystemControllerBase中完成,如下所示:
public abstract class SimpleTaskSystemControllerBase : AbpController { protected SimpleTaskSystemControllerBase() { LocalizationSourceName = "SimpleTaskSystem"; } }
註意,它繼承自AbpController。因此,你可以輕松的使用L方法本地化文本。
在MVC視圖
在視圖中也存在同樣的L方法:
<div> <form id="NewTaskForm" role="form"> <div class="form-group"> <label for="TaskDescription">@L("TaskDescription")</label> <textarea id="TaskDescription" data-bind="value: task.description" class="form-control" rows="3" placeholder="@L("EnterDescriptionHere")" required></textarea> </div> <div class="form-group"> <label for="TaskAssignedPerson">@L("AssignTo")</label> <select id="TaskAssignedPerson" data-bind="options: people, optionsText: ‘name‘, optionsValue: ‘id‘, value: task.assignedPersonId, optionsCaption: [email protected]("SelectPerson")‘" class="form-control"></select> </div> <button data-bind="click: saveTask" type="submit" class="btn btn-primary">@L("CreateTheTask")</button> </form> </div>
為了使用這個方法,需要視圖繼承自一個基類,這個基類設置了源名稱:
public abstract class SimpleTaskSystemWebViewPageBase : SimpleTaskSystemWebViewPageBase<dynamic> { } public abstract class SimpleTaskSystemWebViewPageBase<TModel> : AbpWebViewPage<TModel> { protected SimpleTaskSystemWebViewPageBase() { LocalizationSourceName = "SimpleTaskSystem"; } }
在web.config文件中設置這個基類:
<pages pageBaseType="SimpleTaskSystem.Web.Views.SimpleTaskSystemWebViewPageBase">
當你從ABP模板中創建解決方案時,控制器和視圖的所有設置都已經準備就緒了。
在Javascript
在javascript代碼中,ABP也可以使用同樣的本地化文本。首先,你要在page中添加動態的ABP腳本:
<script src="/AbpScripts/GetScripts" type="text/javascript"></script>
ABP自動生成需要的javascript代碼來在客戶端獲取本地化文本。然後你可以在javascript中獲得一個本地化文本,如下所示:
var s1 = abp.localization.localize(‘NewTask‘, ‘SimpleTaskSystem‘);
NewTask為文本名稱,SimpleTaskSystem為資源名稱。為了不重復使用資源名稱,你可以首先獲得資源再獲取文本:
var source = abp.localization.getSource(‘SimpleTaskSystem‘); var s1 = source(‘NewTask‘);
格式化參數
本地化方法可以接收其他的格式化參數。示例:
abp.localization.localize(‘RoleDeleteWarningMessage‘, ‘MySource‘, ‘Admin‘); //shortcut if source is got using getSource as shown above source(‘RoleDeleteWarningMessage‘, ‘Admin‘);
如果RoleDeleteWarningMessage=‘Role {0} will be deleted‘,那麽本地化文本將為‘Role Admin will be deleted‘。
默認本地化源
你可以設置一個默認的本地化源,然後使用abp.localization.localize方法時就可以不帶資源名稱:
abp.localization.defaultSourceName = ‘SimpleTaskSystem‘; var s1 = abp.localization.localize(‘NewTask‘);
defaultSourceName是全局的,一次只能有一個資源。
擴展本地化源
假定我們使用一個定義了自己本地化源的模塊。我們要改變他的本地化文本,添加新文本或轉換為其他語言。ABP允許擴展一個本地化源。現在支持XML和JSON文件(實際上為任何實現了IDictionaryBasedLocalizationSource接口的本地化源)。
ABP也定義類一些本地化源。例如,Abp.Web nuget包定義了一個名為"AbpWeb"本地化源,為嵌入的XML文件:
默認(英文)XML文件如下所示(僅第一次時顯示兩個文本):
<?xml version="1.0" encoding="utf-8" ?> <localizationDictionary culture="en"> <texts> <text name="InternalServerError" value="An internal error occurred during your request!" /> <text name="ValidationError" value="Your request is not valid!" /> ... </texts> </localizationDictionary>
然後我們可以在模塊的PreInitialize方法中註冊它:
Configuration.Localization.Sources.Extensions.Add( new LocalizationSourceExtensionInfo("AbpWeb", new XmlFileLocalizationDictionaryProvider( HttpContext.Current.Server.MapPath("~/Localization/AbpWebExtensions") ) ) );
如果想創建嵌入的資源XML文件(參見本地化源部分),我們可以使用XmlEmbeddedFileLocalizationDictionaryProvider。ABP使用我們的XML文件重寫(合並)基本的本地化源。我們也可以添加新的語言文件。
註意:我們可以使用JSON文件擴展XML文件,反之亦然。
獲取語言
ILanguageManager可以用來可用語言的列表和當前語言。
最佳實踐
XML文件、JSON文件和資源文件有自己的長處和弱點。我們建議使用XML或JOSN文件而不是資源文件,因為:
- XML/JSON文件易於編輯、擴展或port。
- 當獲取本地化文本時, XML/JSON文件需要字符串key而不是編譯時的屬性如資源文件。這可以認為是一個弱點。但是,以後容易改變源。甚至我們可以將本地化遷移到數據庫而不用改變代碼(Module-zero實現它創建一個基於數據庫和每個租戶的本地化源。參見文檔)。
如果你使用XML或JSON,建議不要按名稱排序文本。按創建時間排序。這樣,當其他人把它翻譯為其他語言時,他可以輕松的看到哪些文本是新增加的。
返回主目錄
ABP官方文檔翻譯 6.3 本地化