文檔目錄
本節內容:
簡介
任何應用至少有一種用戶界面語言,很多應用有多種,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,在客戶端,你可以使用javascript Api的abp.localization獲取所有可用語言列表和當前語言,famfamfam-flag-england (and tr)是一個CSS類,你可根據需要修改它,然後使用它在UI上顯示相關的標志。
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文件必須包含編碼(utf-8),culture=”en“表明這個XML文件包含英文文本,文本的節點:name屬性用來標識一個文本,你可以使用value屬性或inner text(如最後一個)來設置本地化文本的值,我們為每個語言創建一個獨立的XML文件,如下所示:
SimpleTaskSystem是源名稱,SimpleTaskSystem.xml定義當前語言,當一個文本被請求,ABP從當前語言的XML文件裡獲取文本(使用Thread.CurrentThread查找當前語言),如果文本不存在,它將從默認語言的XML文件裡查找。
注冊XML本地化源
XML文件可存儲於文件系統裡或嵌入到一個程序集裡。
如果XML文件存儲於文件系統,我們可以用如下方式注冊一個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" ) ) );
XmlEmbeddedFileLocalizationDictionaryProvider獲取一個程序集包含的xml文件(GetExecutingAssembly直接指向當前程序集) 和xml文件的命名空間(命名空間通過計算:程序集名稱+XML文件的目錄級次)。
注意:當給嵌入的XML文件添加後綴時,不要使用.號,如“MySource.tr.xml",應當用短橫,如”MySource-tr.xml“,因為當查找資源時.號會引起命名空間的問題。
JSON文件
JSON文件可以用來存儲一個本地化源的文本,下面是一個JSON本地化文件的示例:
{ "culture": "en", "texts": { "TaskSystem": "Task system", "Xtasks": "{0} tasks" } }
JSON文件應當編碼(utf-8),culture:“en“表明這個JSON文件包含英文文本,我們可以為每個語言創建單獨的JSON文件,如下所示:
MySourceName是源名稱,MySourceName.json定義了默認語言,這類似於XML文件。
注冊JSON本地化源
JSON文件可存儲在文件系統裡或是嵌入到一個程序集中。
如果存儲在文件系統裡,我們可以用以下方式注冊它:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "MySourceName", new JsonFileLocalizationDictionaryProvider( HttpContext.Current.Server.MapPath("~/Localization/MySourceName") ) ) );
這在一個模塊的PreInitialize事件裡完成(更多信息查看模塊系統),ABP從指定文件夾裡找到所有JSON文件並把它們注冊為本地化源。
如果JSON嵌入到一個程序集裡,我們應當把所有本地化JSON文件標記為嵌入的資源(選擇JSON文件,打開屬性窗口(F4)並把生成操作改成嵌入的資源),然後我們可以用如下的方式注冊這個本地化源:
Configuration.Localization.Sources.Add( new DictionaryBasedLocalizationSource( "MySourceName", new JsonEmbeddedFileLocalizationDictionaryProvider( Assembly.GetExecutingAssembly(), "MyCompany.MyProject.Localization.Sources" ) ) );
JsonEmbeddedFileLocalizationDictionaryProvider獲取一個程序集包含的JSON文件(GetExecutingAssembly直接指向當前程序集) 和JSON文件的命名空間(命名空間通過計算:程序集名稱+JSON文件的目錄級次)。
注意:當給嵌入的JSON文件添加後綴時,不要使用.號,如“MySource.tr.JSON",應當用短橫,如”MySource-tr.JSON“,因為當查找資源時.號會引起命名空間的問題。
資源文件
本地化文件同樣也能存儲於.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 就是在使用數據庫。
獲取一個本地文本
在創建一個源並把它注冊到ABP本地化系統後,就可以很簡單的本地化文本了。
在服務端
在服務端,我們可以注入ILocalizationManager並使用它的GetString方法:
var s1 = _localizationManager.GetString("SimpleTaskSystem", "NewTask");
GetString方法基於當前線程的UI文化從本地化源裡獲取字符串,如果沒有找到,它退回到默認語言。
如果都沒定義指定字符串,它默認返回人性化指定字符串並用[和]包裹它(而不拋出異常),例如:如果指定文本是“ThisIsMyText”,結果將是“[This is my text]”,這個行為可配置(可在你的模塊的PreInitialize裡使用Configuration.Localization)。
為不一直重復獲取源名稱,你可以先獲取源,然後從源裡獲取一個字符串:
var source = _localizationManager.GetSource("SimpleTaskSystem"); var s1 = source.GetString("NewTask");
這將用返回當前語言的文本,同時有幾個用來獲取不同語言和不同格式化參數的重載。
如果我們不能注入ILocalizationManager(可能在一個不能使用依賴注入的靜態上下文裡),我們可以簡單地使用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: '@L("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裡
ABP使在javascript代碼裡本地化文本成為可能,首先,應該在頁面裡添加動態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');
格式化參數
Localization方法可以接受額外的格式化參數,例如:
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>
這擴展AbpWeb源,我們可以定義XML文件,假設我們只想修改InternalServerError文本,我們可以定義一下如下所示的XML文件:
<?xml version="1.0" encoding="utf-8" ?> <localizationDictionary culture="en"> <texts> <text name="InternalServerError" value="Sorry :( It seems there is a problem. Let us to solve it and please try again later." /> </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或JSON文件,不用資源文件,因為:
如果你使用XML或JSON,建議你不要把文本按名稱排序,要按創建時間排序,因為,當某人把它翻譯成另一種語言時,他可以很容易地看出哪一個是新添加的。
kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/Localization