ABP官方文档翻译 6.3 本地化
本地化
介绍
任何应用程序都会包含至少一种语言。许多的应用程序都包含多种语言。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
- ));
这里源的唯一名称为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="" 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,建议不要按名称排序文本。按创建时间排序。这样,当其他人把它翻译为其他语言时,他可以轻松的看到哪些文本是新增加的。
ABP官方文档翻译 6.3 本地化的更多相关文章
- ABP官方文档翻译 2.5 设置管理
设置管理 介绍 关于 ISettingStore 定义设置 设置范围 重写设置定义 获取设置值 服务端 客户端 更改设置 关于缓存 介绍 每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置. ...
- 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 ...
- ABP官方文档翻译 8.1 通知系统
通知系统 介绍 发送模型 通知类型 通知数据 通知严重性 关于通知持久化 订阅通知 发布通知 用户通知管理 实时通知 客户端 通知存储 通知定义 介绍 在系统中通知用来基于特定的事件告知用户.ABP提 ...
- ABP官方文档翻译 7.3 Quartz集成
Quartz集成 介绍 安装 创建Jobs 计划安排Jobs 更多 介绍 Quartz是一个全功能的.开源的job计划安排系统,可以用在小的apps也可以用于大型的企业系统.Abp.Quartz包简化 ...
- ABP官方文档翻译 6.4 导航
导航 创建菜单 注册导航提供者 显示菜单 每一个网络应用都会有一些菜单用来在pages/screens之间导航.ABP提供了通用的基础设施来创建并显示菜单. 创建菜单 应用可以由不同的模块组成,每一个 ...
- ABP官方文档翻译 6.2.1 ASP.NET Core集成
ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...
- ABP官方文档翻译 6.1.3 异常处理
处理异常 介绍 启用错误处理 Non-Ajax请求 显示异常 UserFriendlyException Error模型 AJAX请求 异常事件 介绍 此文档是与ASP.NET MVC和Web API ...
- ABP官方文档翻译 6.1.2 MVC视图
ASP.NET MVC 视图 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc nuget包集成到MVC视图.你可以如往常一样创建正常的MVC视图. AbpWebView ...
- ABP官方文档翻译 6.1.1 MVC控制器
ASP.NET MVC控制器 介绍 AbpController基类 本地化 其他 过滤器 异常处理和结果包装 审计日志 验证 授权 工作单元 介绍 ABP通过Abp.Web.Mvc nuget包集成到 ...
随机推荐
- [51nod Round15 E ]Danganronpa
AC自动机,树上莫队,树状数组.. 比赛的时候完全看不出来...赛后去膜了一波网上题解才明白= = 离线,先把AC自动机建出来,把fail边反向建出fail树. 发射言弹,就是将言弹结束节点的fail ...
- H5基础浏览器兼容性
<!DOCTYPE HTML><html><body> <video width="320" height="240" ...
- Spring的IOC分析(二)源码
承接上节继续,分析Ioc的工作原理,在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起(同时一个叫DI"依赖注入"或DL"依赖查找" ...
- 基于ARM的车牌识别技术研究与实现
在云盘里包含了我本科毕业设计的全部资料和代码.主要涉及下面摘要中的几个部分.虽然系统无法实用,但是适合机器视觉和嵌入式方向的入门.希望能对有志从事相关方向的朋友有所帮助.本人现在在深圳从事机器视觉算法 ...
- 修改nopCommerce中的实体
对已有实体增加一个属性(对Category增加一个SomeNewProperty) 最近在研究nopcommerce,这里是对官网上文档的学习 ...
- How to bypass Win10 logon password?
Usually we will use LiveView or VFC to "boot up" the evidence files acquired from suspect' ...
- 本地如何使用phpstudy环境搭建多站点
http://jingyan.baidu.com/article/e52e36154227ef40c70c5147.html 平时在开发项目的时候, 多个项目同时开发的时候会遇到都得放到根目录才能正常 ...
- Linux的运行级别详细说明
Linux 7个运行级别 # 0 - 停机(千万不要把initdefault设置为0 ) # 1 - 单用户模式 # 2 - 多用户,但是没有NFS # 3 - 完全多用 ...
- ADO.NET复习总结(4)--访问SqlServer的类
1.连接SqlConnection 2. 3.执行命令SqlCommand 4.数据读取SqlDataReader 注意: ExecuteNonQuery() :执行非查询(增删改) Execute ...
- HTML <a href >标签的target属性
规定在何处打开链接文档. _blank 在新窗口中打开被链接文档 _parent 在父框架集中打开被链接文档 _self 默认.在相同的框架中打开被链接文档 _top 在整 ...