ABP官方文档翻译 6.3 本地化

本地化

  • 介绍
  • 应用程序语言
  • 本地化源
    • 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: ‘@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

  在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,建议不要按名称排序文本。按创建时间排序。这样,当其他人把它翻译为其他语言时,他可以轻松的看到哪些文本是新增加的。

返回主目录

时间: 2024-10-18 06:57:05

ABP官方文档翻译 6.3 本地化的相关文章

ABP官方文档翻译 6.4 导航

导航 创建菜单 注册导航提供者 显示菜单 每一个网络应用都会有一些菜单用来在pages/screens之间导航.ABP提供了通用的基础设施来创建并显示菜单. 创建菜单 应用可以由不同的模块组成,每一个模块都有自己的菜单项.为了定义菜单项,我们需要创建一个继承自NavigationProvider的类. 假定,我们有一个如下所示的主菜单: Tasks Reports Administration User management Role management 这里,Administration菜单

ABP官方文档翻译 6.1.2 MVC视图

ASP.NET MVC 视图 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc nuget包集成到MVC视图.你可以如往常一样创建正常的MVC视图. AbpWebViewPage基类 ABP提供了AbpWebViewPage,它定义了一些有用的属性和方法.如果你使用启动模板创建的工程,那么你所有的views都自动从这个基类继承. AbpWebViewPage定义了L方法用于本地化,IsGranted方法用于授权,IsFeatureEnabled和GetFeature

ABP官方文档翻译 10.1 ABP Nuget包

ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OData Abp.Web.Resources Abp.Web.SignalR Abp.Owin Abp.EntityFramework.Common Abp.EntityFramework Abp.EntityFramework.GraphDiff Abp.EntityFrameworkCore Ab

ABP官方文档翻译 7.3 Quartz集成

Quartz集成 介绍 安装 创建Jobs 计划安排Jobs 更多 介绍 Quartz是一个全功能的.开源的job计划安排系统,可以用在小的apps也可以用于大型的企业系统.Abp.Quartz包简化了ABP集成Quartz. ABP有內建的持久化后台job队列和后台worker系统.如果对于后台workers你有更高级的计划安排需求,Quartz会是一个更好的选择.对于持久化后台job队列,Hangfire也是一个好的选择. 安装 在工程中安装Abp.Quartz nuget包并在模块上为Ab

ABP官方文档翻译 6.2.1 ASP.NET Core集成

ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Action过滤器 异常过滤器 结果过滤器 Ajax请求的结果缓存 模型绑定器 视图 客户端代理 集成测试 介绍 本文档描述了ABP如何集成ASP.NET Core.ASP.NET Core通过Abp.AspNetCore nuget包实现集成. 迁移到ASP.NET Core? 如果你已经有一个工程并考虑

ABP官方文档翻译 4.4 授权

授权 介绍 关于IPermissionChecker 定义权限 检查权限 使用AbpAuthorize特性 AbpAuthorize特性注意点 抑制授权 使用IPermissionChecker 在Razor视图 客户端(Javascript) 权限管理 介绍 几乎所有的企业应用都在一定程度上使用授权.在应用中,授权用来检查用户是否允许执行一些特定的操作.ABP定义了一个基础的权限设施来实现授权. 关于IPermissionChecker 授权系统使用IPermissionChecker来检查权

ABP官方文档翻译 4.1 应用服务

应用服务 IApplicationService接口 ApplicationService类 CrudService和AsyncCrudAppService类 简单的CRUD应用服务示例 自定义CRUD应用服务 GettingList Create和Update 其他方法参数 CRUD权限 工作单元 应用服务生命周期 应用服务将领域逻辑暴露给展示层.在展示层使用DTO(数据传输对象)作为参数调用应用服务,应用服务使用领域对象执行一些特定的业务逻辑,并返回DTO到展示层.因此,展示层与领域层是完全

ABP官方文档翻译 1.2 N层架构

N层架构 介绍 ABP架构 其他(通用) 领域层 应用层 基础设施层 网络和展现层 其他 总结 介绍 应用程序代码库的分层架构是被广泛认可的可以减少程序复杂度.提高代码复用率的技术.为了实现分层架构,ABP遵循领域驱动设计的原则.在领域驱动设计中有四个基本层: 表现层:提供用户接口.使用应用层实现用户交互. 应用层:桥接表现层和领域层.协调业务对象来执行特定的应用任务. 领域层:包括业务对象以及业务规则.此层是整个应用的核心. 基础设施层:提供通用的技术能力来支持高层.基础设施层可以是使用ORM

ABP官方文档翻译 3.4 领域服务

领域服务 介绍 IDomainService接口和DomainService类 示例 创建接口 服务实现 使用应用服务 一些探讨 为什么只有应用服务? 如何强制使用领域服务? 介绍 领域服务(或者在DDD中单纯的服务)用来执行领域操作和业务规则.Eric Evans在他的DDD书中描述了一个好的服务有三个特征: 1. 与领域概念关联的操作,但不是实体或值对象的自然组成部分. 2. 接口的定义依照领域模型的其他元素. 3. 操作是无状态的. 不像应用服务那样获取或返回DTO,领域服务获取或返回领域