1. 程式人生 > >ABP官方文檔翻譯 6.3 本地化

ABP官方文檔翻譯 6.3 本地化

round 找到 factory 版本 assign reg 允許 mine man

本地化

  • 介紹
  • 應用程序語言
  • 本地化源
    • XML文件
      • 註冊XML本地化源
    • JSON文件
      • 註冊JSON本地化源
    • 資源文件
    • 自定義源
  • 當前語言是如何決定的
    • 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.Localization javascript API來獲取所有可用語言的列表及當前語言。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文件必須是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
        ));

  這裏的唯一名稱為MySourceMyTexts.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 本地化