本地化

介绍

  任何应用程序都会包含至少一种语言。许多的应用程序都包含多种语言。ABP提供了灵活的本地化系统。

应用程序语言

  首要的事情是声明支持哪种语言。在模块的PreInitialize方法中设置,如下所示:

  1. Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
  2. 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文件的内如大致如下所示:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <localizationDictionary culture="en">
  3. <texts>
  4. <text name="TaskSystem" value="Task System" />
  5. <text name="TaskList" value="Task List" />
  6. <text name="NewTask" value="New Task" />
  7. <text name="Xtasks" value="{0} tasks" />
  8. <text name="CompletedTasks" value="Completed tasks" />
  9. <text name="EmailWelcomeMessage">Hi,
  10. Welcome to Simple Task System! This is a sample
  11. email content.</text>
  12. </texts>
  13. </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本地化源:

  1. Configuration.Localization.Sources.Add(
  2. new DictionaryBasedLocalizationSource(
  3. "SimpleTaskSystem",
  4. new XmlFileLocalizationDictionaryProvider(
  5. HttpContext.Current.Server.MapPath("~/Localization/SimpleTaskSystem")
  6. )
  7. )
  8. );

  这在模块的PreInitialize事件中完成(参见模块系统了解更多)。ABP在指定目录查找所有的XML文件并注册为本地化源。

  对于嵌入XML文件,我们需要标记本地的所有的XML文件为嵌入的资源(选择XML文件,打开属性窗口(F4),改变生成操作为内嵌资源)。然后我们可以按如下所示注册本地化源:

  1. Configuration.Localization.Sources.Add(
  2. new DictionaryBasedLocalizationSource(
  3. "SimpleTaskSystem",
  4. new XmlEmbeddedFileLocalizationDictionaryProvider(
  5. Assembly.GetExecutingAssembly(),
  6. "MyCompany.MyProject.Localization.Sources"
  7. )
  8. )
  9. );

  XmlEmbedddFileLocalizationDictionaryProvider获取包含XML文件(GetExecutingAssembly获取当前程序集)和XML文件命名空间(命名空间由程序集名称+XML文件的目录层级组成)的程序集。

  注意:当给嵌入的XML文件添加语言前缀时,不要使用点符号如'MySource.tr.mxl',应该使用破折号如'MySource-tr.xml',因为点符号会在查找资源时造成命名空间问题。

JSON文件

  本地化源可以使用JSON文件来存储文本。一个JSON本地化文件的实例如下:

  1. {
  2. "culture": "en",
  3. "texts": {
  4. "TaskSystem": "Task system",
  5. "Xtasks": "{0} tasks"
  6. }
  7. }

  JSON文件编码应为unicode(utf-8)。culture:"en"声明标示这个JSON文件包含英文文本。我们我每种语言创建一个单独的JSON文件,如下所示:

  这里,MySourceName资源名称,MySourceName.json文件定义了默认的语言。它和XML文件相似。

注册JSON本地化源

  JOSN文件可以存储在文件系统或嵌入到程序集中。

  如果文件系统存储JSONs,我么可以按如下方式注册JOSN本地化源:

  1. Configuration.Localization.Sources.Add(
  2. new DictionaryBasedLocalizationSource(
  3. "MySourceName",
  4. new JsonFileLocalizationDictionaryProvider(
  5. HttpContext.Current.Server.MapPath("~/Localization/MySourceName")
  6. )
  7. )
  8. );

  这些都是在模块的PreInitialize事件中完成(参见模块系统了解更多信息)。ABP在指定目录查找JSON文件并注册为本地化源。

  对于嵌入JSON文件,我们需要标记本地的所有的XML文件为嵌入的资源(选择JSON文件,打开属性窗口(F4),改变生成操作为内嵌资源)。然后我们可以按如下所示注册本地化资源:

  1. Configuration.Localization.Sources.Add(
  2. new DictionaryBasedLocalizationSource(
  3. "MySourceName",
  4. new JsonEmbeddedFileLocalizationDictionaryProvider(
  5. Assembly.GetExecutingAssembly(),
  6. "MyCompany.MyProject.Localization.Sources"
  7. )
  8. )
  9. );

  JsonEmbedddFileLocalizationDictionaryProvider获取包含XML文件(GetExecutingAssembly获取当前程序集)和XML文件命名空间(命名空间由程序集名称+XML文件的目录层级组成)的程序集。

  注意:当给嵌入的JOSN文件添加语言前缀时,不要使用点符号如'MySource.tr.mxl',应该使用破折号如'MySource-tr.xml',因为点符号会在查找资源时造成命名空间问题。

资源文件

  本地化文本也可以存储在.NET的资源文件中。我们可以为每种语言创建一个资源文件,如下所示(右键单击工程,选择添加新项然后找到资源文件):

  MyTexts.resx包含默认语言文本,MyTexts.tr.resx包含Turkish语言的文本。当我们打开MyTexts.resx时,我们可以看到所有的文本:

  在这种情况下,ABP使用.NET內建的资源管理器。你应该为资源配置一个本地化源:

  1. Configuration.Localization.Sources.Add(
  2. new ResourceFileLocalizationSource(
  3. "MySource",
  4. MyTexts.ResourceManager
  5. ));

  这里的唯一名称为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类的配置方法中),如果你的应用程序使用认证校验的话。否则,本地化中间件可以知道当前用户来决定最佳的语言。示例用法:

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  2. {
  3. app.UseAbp(options =>
  4. {
  5. options.UseAbpRequestLocalization = false; //disable automatic adding of request localization
  6. });
  7.  
  8. //...authentication middleware(s)
  9.  
  10. app.UseAbpRequestLocalization(); //manually add request localization
  11.  
  12. //...other middlewares
  13.  
  14. app.UseMvc(routes =>
  15. {
  16. //...
  17. });
  18. }

  大多数时候,如果你恰当的使用了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名称)。示例:

  1. Configuration.Modules.AbpWeb().Localization.CookieName = "YourCustomName";

获取一个本地化文本

  创建一个 资源并注册到ABP本地化系统之后,文本就可以很容易的本地化。

在服务端

  在服务端,我们注入ILocalizationManager并使用GetString方法。

  1. var s1 = _localizationManager.GetString("SimpleTaskSystem", "NewTask");

  GetString方法基于当前线程UI culture从本地化源中获取字符串。如果没找到,它便使用默认语言

  如果指定的字符串没有定义,那么它人性化的返回指定的字符串并默认使用'['和']'包装(取代抛出异常)。示例:如果给定的文本为"ThisIsMyText",那么结果将为“[This is my text]”。这个功能是可以配置的(你可以在模块的PreInitialize方法中使用Configuration.Localization改变它)。

  为了不要重复使用资源名称,你可以先获得资源,然后从资源中获取字符串:

  1. var source = _localizationManager.GetSource("SimpleTaskSystem");
  2. var s1 = source.GetString("NewTask");

  这个返回当前语言的文本。GetString有重写版本用来在不用的语言中获取文本或通过参数格式化文本。

  如果我们不能注入ILocalizationManager(例如在静态context中,不能使用依赖注入系统),我们可以简单的使用LocalizationHelper静态类。但是尽可能的情况下注入并使用ILocalizationManager,因为LocalizationHelper是静态的,静态类是测试不友好的(谁编写单元测试)。

  如果你需要在应用服务MVC控制器Razor视图或其他从AbpServiceBase继承的类中本地化,可以简单的使用L方法。

在MVC控制器

   本地化文本通常在MVC控制器和视图中都是需要的。这有一个简便方法。参见下面控制器示例:

  1. public class HomeController : SimpleTaskSystemControllerBase
  2. {
  3. public ActionResult Index()
  4. {
  5. var helloWorldText = L("HelloWorld");
  6. return View();
  7. }
  8. }

  L方法用来本地化字符串。当然,你必须提供一个资源名称。这个操作在SimpleTaskSystemControllerBase中完成,如下所示:

  1. public abstract class SimpleTaskSystemControllerBase : AbpController
  2. {
  3. protected SimpleTaskSystemControllerBase()
  4. {
  5. LocalizationSourceName = "SimpleTaskSystem";
  6. }
  7. }

  注意,它继承自AbpController。因此,你可以轻松的使用L方法本地化文本。

在MVC视图

  在视图中也存在同样的L方法:

  1. <div>
  2. <form id="NewTaskForm" role="form">
  3. <div class="form-group">
  4. <label for="TaskDescription">@L("TaskDescription")</label>
  5. <textarea id="TaskDescription" data-bind="value: task.description" class="form-control" rows="" placeholder="@L("EnterDescriptionHere")" required></textarea>
  6. </div>
  7. <div class="form-group">
  8. <label for="TaskAssignedPerson">@L("AssignTo")</label>
  9. <select id="TaskAssignedPerson" data-bind="options: people, optionsText: 'name', optionsValue: 'id', value: task.assignedPersonId, optionsCaption: '@L("SelectPerson")'" class="form-control"></select>
  10. </div>
  11. <button data-bind="click: saveTask" type="submit" class="btn btn-primary">@L("CreateTheTask")</button>
  12. </form>
  13. </div>

  为了使用这个方法,需要视图继承自一个基类,这个基类设置了源名称:

  1. public abstract class SimpleTaskSystemWebViewPageBase : SimpleTaskSystemWebViewPageBase<dynamic>
  2. {
  3.  
  4. }
  5.  
  6. public abstract class SimpleTaskSystemWebViewPageBase<TModel> : AbpWebViewPage<TModel>
  7. {
  8. protected SimpleTaskSystemWebViewPageBase()
  9. {
  10. LocalizationSourceName = "SimpleTaskSystem";
  11. }
  12. }

  在web.config文件中设置这个基类:

  1. <pages pageBaseType="SimpleTaskSystem.Web.Views.SimpleTaskSystemWebViewPageBase">

  当你从ABP模板中创建解决方案时,控制器和视图的所有设置都已经准备就绪了。

在Javascript

  在javascript代码中,ABP也可以使用同样的本地化文本。首先,你要在page中添加动态的ABP脚本:

  1. <script src="/AbpScripts/GetScripts" type="text/javascript"></script>

  ABP自动生成需要的javascript代码来在客户端获取本地化文本。然后你可以在javascript中获得一个本地化文本,如下所示:

  1. var s1 = abp.localization.localize('NewTask', 'SimpleTaskSystem');

  NewTask为文本名称,SimpleTaskSystem为资源名称。为了不重复使用资源名称,你可以首先获得资源再获取文本:

  1. var source = abp.localization.getSource('SimpleTaskSystem');
  2. var s1 = source('NewTask');

格式化参数

  本地化方法可以接收其他的格式化参数。示例:

  1. abp.localization.localize('RoleDeleteWarningMessage', 'MySource', 'Admin');
  2.  
  3. //shortcut if source is got using getSource as shown above
  4. source('RoleDeleteWarningMessage', 'Admin');

  如果RoleDeleteWarningMessage='Role {0} will be deleted',那么本地化文本将为'Role Admin will be deleted'。

默认本地化源

  你可以设置一个默认的本地化源,然后使用abp.localization.localize方法时就可以不带资源名称:

  1. abp.localization.defaultSourceName = 'SimpleTaskSystem';
  2. var s1 = abp.localization.localize('NewTask');

  defaultSourceName是全局的,一次只能有一个资源。

扩展本地化源

  假定我们使用一个定义了自己本地化源的模块。我们要改变他的本地化文本,添加新文本或转换为其他语言。ABP允许扩展一个本地化源。现在支持XML和JSON文件(实际上为任何实现了IDictionaryBasedLocalizationSource接口的本地化源)。

  ABP也定义类一些本地化源。例如,Abp.Web nuget包定义了一个名为"AbpWeb"本地化源,为嵌入的XML文件:

  默认(英文)XML文件如下所示(仅第一次时显示两个文本):

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <localizationDictionary culture="en">
  3. <texts>
  4. <text name="InternalServerError" value="An internal error occurred during your request!" />
  5. <text name="ValidationError" value="Your request is not valid!" />
  6. ...
  7. </texts>
  8. </localizationDictionary>

  然后我们可以在模块的PreInitialize方法中注册它:

  1. Configuration.Localization.Sources.Extensions.Add(
  2. new LocalizationSourceExtensionInfo("AbpWeb",
  3. new XmlFileLocalizationDictionaryProvider(
  4. HttpContext.Current.Server.MapPath("~/Localization/AbpWebExtensions")
  5. )
  6. )
  7. );

  如果想创建嵌入的资源XML文件(参见本地化源部分),我们可以使用XmlEmbeddedFileLocalizationDictionaryProvider。ABP使用我们的XML文件重写(合并)基本的本地化源。我们也可以添加新的语言文件。

  注意:我们可以使用JSON文件扩展XML文件,反之亦然。

获取语言

  ILanguageManager可以用来可用语言的列表和当前语言。

最佳实践

  XML文件、JSON文件和资源文件有自己的长处和弱点。我们建议使用XML或JOSN文件而不是资源文件,因为:

  • XML/JSON文件易于编辑、扩展或port。
  • 当获取本地化文本时, XML/JSON文件需要字符串key而不是编译时的属性如资源文件。这可以认为是一个弱点。但是,以后容易改变源。甚至我们可以将本地化迁移到数据库而不用改变代码(Module-zero实现它创建一个基于数据库和每个租户的本地化源。参见文档)。

  如果你使用XML或JSON,建议不要按名称排序文本。按创建时间排序。这样,当其他人把它翻译为其他语言时,他可以轻松的看到哪些文本是新增加的。

返回主目录

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

  1. ABP官方文档翻译 2.5 设置管理

    设置管理 介绍 关于 ISettingStore 定义设置 设置范围 重写设置定义 获取设置值 服务端 客户端 更改设置 关于缓存 介绍 每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置. ...

  2. 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.OD ...

  3. ABP官方文档翻译 8.1 通知系统

    通知系统 介绍 发送模型 通知类型 通知数据 通知严重性 关于通知持久化 订阅通知 发布通知 用户通知管理 实时通知 客户端 通知存储 通知定义 介绍 在系统中通知用来基于特定的事件告知用户.ABP提 ...

  4. ABP官方文档翻译 7.3 Quartz集成

    Quartz集成 介绍 安装 创建Jobs 计划安排Jobs 更多 介绍 Quartz是一个全功能的.开源的job计划安排系统,可以用在小的apps也可以用于大型的企业系统.Abp.Quartz包简化 ...

  5. ABP官方文档翻译 6.4 导航

    导航 创建菜单 注册导航提供者 显示菜单 每一个网络应用都会有一些菜单用来在pages/screens之间导航.ABP提供了通用的基础设施来创建并显示菜单. 创建菜单 应用可以由不同的模块组成,每一个 ...

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

    ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...

  7. ABP官方文档翻译 6.1.3 异常处理

    处理异常 介绍 启用错误处理 Non-Ajax请求 显示异常 UserFriendlyException Error模型 AJAX请求 异常事件 介绍 此文档是与ASP.NET MVC和Web API ...

  8. ABP官方文档翻译 6.1.2 MVC视图

    ASP.NET MVC 视图 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc nuget包集成到MVC视图.你可以如往常一样创建正常的MVC视图. AbpWebView ...

  9. ABP官方文档翻译 6.1.1 MVC控制器

    ASP.NET MVC控制器 介绍 AbpController基类 本地化 其他 过滤器 异常处理和结果包装 审计日志 验证 授权 工作单元 介绍 ABP通过Abp.Web.Mvc nuget包集成到 ...

随机推荐

  1. [51nod Round15 E ]Danganronpa

    AC自动机,树上莫队,树状数组.. 比赛的时候完全看不出来...赛后去膜了一波网上题解才明白= = 离线,先把AC自动机建出来,把fail边反向建出fail树. 发射言弹,就是将言弹结束节点的fail ...

  2. H5基础浏览器兼容性

    <!DOCTYPE HTML><html><body> <video width="320" height="240" ...

  3. Spring的IOC分析(二)源码

    承接上节继续,分析Ioc的工作原理,在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起(同时一个叫DI"依赖注入"或DL"依赖查找" ...

  4. 基于ARM的车牌识别技术研究与实现

    在云盘里包含了我本科毕业设计的全部资料和代码.主要涉及下面摘要中的几个部分.虽然系统无法实用,但是适合机器视觉和嵌入式方向的入门.希望能对有志从事相关方向的朋友有所帮助.本人现在在深圳从事机器视觉算法 ...

  5. 修改nopCommerce中的实体

                               对已有实体增加一个属性(对Category增加一个SomeNewProperty)   最近在研究nopcommerce,这里是对官网上文档的学习 ...

  6. How to bypass Win10 logon password?

    Usually we will use LiveView or VFC to "boot up" the evidence files acquired from suspect' ...

  7. 本地如何使用phpstudy环境搭建多站点

    http://jingyan.baidu.com/article/e52e36154227ef40c70c5147.html 平时在开发项目的时候, 多个项目同时开发的时候会遇到都得放到根目录才能正常 ...

  8. Linux的运行级别详细说明

    Linux 7个运行级别    # 0 - 停机(千万不要把initdefault设置为0 )     # 1 - 单用户模式     # 2 - 多用户,但是没有NFS     # 3 - 完全多用 ...

  9. ADO.NET复习总结(4)--访问SqlServer的类

    1.连接SqlConnection 2. 3.执行命令SqlCommand 4.数据读取SqlDataReader  注意: ExecuteNonQuery() :执行非查询(增删改) Execute ...

  10. HTML <a href >标签的target属性

    规定在何处打开链接文档. _blank    在新窗口中打开被链接文档 _parent  在父框架集中打开被链接文档 _self      默认.在相同的框架中打开被链接文档 _top      在整 ...