本土化

介绍

开发一个支持全球的应用程序,包括可以本地化为一种或多种语言的应用程序,需要本地化功能。ASP.NET Boilerplate为开发世界级和本地化应用程序提供了广泛的支持。

应用语言

首先要做的是声明支持哪些语言。这是在模块的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(和tr)只是一个CSS类,您可以根据自己的需要进行更改。然后,您可以在UI中使用它来显示相关标志。

ASP.NET Boilerplate  模板  使用此系统向用户显示语言切换组合框。创建模板并查看源代码以获取更多信息。

本地化来源

本地化文本可以存储在不同的源中。您甚至可以在同一个应用程序中使用多个源(如果您有多个  模块,则每个模块可以定义一个独立的本地化源,或者一个模块可以定义多个源)。ILocalizationSource接口应由本地化源实现。然后将其注册到ASP.NET Boilerplate的本地化配置。

每个本地化源都必须具有唯一的源名称。有预定义的本地化源类型,如下所述。

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属性用于标识文本。您可以使用值属性或内部文本(如最后一个)来设置本地化文本的值。我们为每种语言创建一个单独的XML文件,如下所示:

本地化文件

SimpleTaskSystem是源名称,SimpleTaskSystem.xml定义默认语言。当请求文本时,ASP.NET Boilerplate从当前语言的XML文件中获取文本(它使用Thread.CurrentThread.CurrentUICulture查找当前语言)。如果它在当前语言中不存在,则从默认语言的XML文件中获取文本。

注册XML本地化源

XML文件可以存储在文件系统中,也可以嵌入到程序集中。

对于文件系统存储的XML,我们可以注册XML本地化源,如下所示:

Configuration.Localization.Sources.Add(
    new DictionaryBasedLocalizationSource(
        "SimpleTaskSystem",
        new XmlFileLocalizationDictionaryProvider(
            HttpContext.Current.Server.MapPath("~/Localization/SimpleTaskSystem")
            )
        )
    );

这是在模块的PreInitialize事件中完成的(有关 详细信息,请参阅  模块系统)。ASP.NET Boilerplate查找给定目录中的所有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文件应该是unicode(utf-8)。culture:“en”声明此JSON文件包含英文文本。我们为每种语言创建一个单独的JSON文件,如下所示:

JSON本地化文件

MySourceName是源名称,MySourceName.json定义默认语言。它类似于XML文件。

注册JSON本地化源

JSON文件可以存储在文件系统中,也可以嵌入到程序集中。

对于文件系统存储的JSON,我们可以注册一个JSON本地化源,如下所示:

Configuration.Localization.Sources.Add(
    new DictionaryBasedLocalizationSource(
        "MySourceName",
        new JsonFileLocalizationDictionaryProvider(
            HttpContext.Current.Server.MapPath("~/Localization/MySourceName")
            )
        )
    );

这是在模块的PreInitialize事件中完成的(有关 详细信息,请参阅  模块系统)。ASP.NET Boilerplate查找给定目录中的所有JSON文件并注册本地化源。

对于嵌入式JSON文件,我们必须将所有本地化JSON文件标记为嵌入式资源(选择JSON文件,打开属性窗口(F4)并将构建操作更改为嵌入式资源)。然后我们可以注册本地化源,如下所示:

 Configuration.Localization.Sources.Add(
    new DictionaryBasedLocalizationSource(
        "MySourceName",
        new JsonEmbeddedFileLocalizationDictionaryProvider(
            Assembly.GetExecutingAssembly(),
            "MyCompany.MyProject.Localization.Sources"
            )
        )
    );

JsonEmbeddedFileLocalizationDictionaryProvider获取包含JSON文件的程序集(GetExecutingAssembly仅引用当前程序集)和JSON文件的命名空间(namespace是计算的程序集名称+ JSON文件的文件夹层次结构)。

注意:在嵌入式JSON文件中添加语言后缀时,请勿使用“MySource.tr.json”之类的点符号!相反,使用像'MySource-tr.json'这样的破折号,因为点符号在查找资源时会导致命名空间问题。 

资源文件

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

本地化资源文件

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

资源文件的内容

在这种情况下,ASP.NET Boilerplate使用.NET的内置资源管理器进行本地化。您应该为资源配置本地化源:

Configuration.Localization.Sources.Add(
    new ResourceFileLocalizationSource(
        "MySource",
        MyTexts.ResourceManager
        ));

源的唯一名称是MySource。MyTexts.ResourceManager是对用于获取本地化文本的资源管理器的引用。这是在模块的PreInitialize事件中完成的(有关 详细信息,请参阅  模块系统)。

自定义来源

可以实现定制本地化源以将文本存储在不同的源中,例如在数据库中。您可以直接实现ILocalizationSource接口,也可以使用DictionaryBasedLocalizationSource类来简化实现(json和xml本地化源也可以使用它)。 例如,模块零  实现数据库中的源。

如何确定当前语言

ASP.NET核心

ASP.NET Core有自己的机制来确定当前语言。Abp.AspNetCore包自动添加ASP.NET Core的UseRequestLocalization中间件来请求管道。它还增加了一些特殊的提供者。以下是所有提供程序的默认有序列表,它确定HTTP请求的当前语言:

调用app.UseAbp()方法时会自动添加UseRequestLocalization中间件。但是,如果您的应用程序使用身份验证,建议您在身份验证中间件之后手动添加它(在Startup类的Configure方法中)。否则,本地化中间件不知道当前用户确定最佳语言。用法示例:

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自动确定每个Web请求中的当前语言,并设置当前线程的文化(和UI文化)。这是ABP默认确定的方式。ABP将:

如果需要,可以在模块的PreInitialize方法中更改特殊的cookie / header / querystring名称。例:

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

ABP重写Application_PostAuthenticateRequest(在global.asax中)以实现该逻辑。您可以在global.asax中覆盖SetCurrentCulture或替换ICurrentCultureSetter以覆盖上述逻辑。

获取本地化文本

创建源并将其注册到ASP.NET Boilerplate的本地化系统后,可以轻松地对文本进行本地化。 

服务器端

在服务器端,我们可以  注入  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");

这将返回当前语言的文本。还有GetString的覆盖来获取不同语言的文本并通过参数格式化。

如果我们不能注入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" style="box-sizing: border-box; color: rgb(163, 21, 21);">"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" style="box-sizing: border-box; color: rgb(163, 21, 21);">"options: people, optionsText: 'name', optionsValue: 'id', value: task.assignedPersonId, optionsCaption: '@L("SelectPerson")'" class="form-control"></select>
        </div>
        <button style="box-sizing: border-box; color: rgb(163, 21, 21);">"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">

当您从其中一个ASP.NET Boilerplate 模板创建解决方案时,所有控制器和视图都已准备好使用这些方法  

在JavaScript中

ASP.NET Boilerplate还可以在JavaScript中使用相同的本地化文本。首先,您需要将动态ABP脚本添加到页面:

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

ASP.NET Boilerplate自动生成所需的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 the source is retrieved using getSource as shown above
source('RoleDeleteWarningMessage', 'Admin');

如果RoleDeleteWarningMessage ='Role {0}将被删除',则本地化文本将为'Role Admin将被删除'。

默认本地化源

您可以设置默认本地化源并使用不带源名称的abp.localization.localize方法。

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

defaultSourceName是全局的,一次只能用于一个源。

扩展本地化源

假设我们使用一个定义它自己的本地化源的模块。我们可能需要更改其本地化文本,添加新文本或翻译为其他语言。ASP.NET Boilerplate允许扩展本地化源。它目前适用于XML和JSON文件(实际上任何实现IDictionaryBasedLocalizationSource接口的本地化源)。

ASP.NET Boilerplate还定义了一些本地化源。例如,Abp.Web NuGet包将名为“AbpWeb”的本地化源定义为嵌入式XML文件:

AbpWeb本地化源文件

默认(英语)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 XmlEmbeddedFileLocalizationDictionaryProvider(
			Assembly.GetExecutingAssembly(),
			"MyCompany.MyProject.Localization.Sources"
		)
	)
);

ASP.NET Boilerplate使用我们的XML文件覆盖(合并)基本本地化源。我们还可以添加新的语言文件。

注意:我们可以使用JSON文件来扩展XML文件,反之亦然。为扩展本地化源而创建的文件必须标记为嵌入式资源。

获得语言

ILanguageManager可用于获取所有可用语言和当前语言的列表。

最佳实践

XML文件,JSON文件和资源文件都有自己的优点和缺点。我们建议您使用XML或JSON文件而不是资源文件,因为;

如果您使用XML或JSON,我们建议您不要按名称对文本进行排序。按创建日期排序!这样,当有人将其翻译成另一种语言时,他/她可以很容易地看到最近添加了哪些文本。

nidie.com.cn - 用心与你沟通