在 ASP.NET Core 中配置可移植对象本地化Configure portable object localization in ASP.NET Core

本文内容

作者:Sébastien RosScott Addie

本文演示通过 Orchard Core 框架在 ASP.NET Core 应用程序中使用可移植对象 (PO) 文件的步骤。

注意: Orchard Core 不是 Microsoft 产品。因此,Microsoft 不提供针对此功能的支持。

查看或下载示例代码如何下载

什么是 PO 文件?What is a PO file?

PO 文件作为包含给定语言的已转换字符串的文本文件分发。使用 PO 文件替代 .resx 文件的一些优势包括:

  • PO 文件支持复数形式;而 .resx 文件不支持复数形式。
  • PO 文件的编译方法与 .resx 文件不同。同样,无需专用工具和生成步骤。
  • PO 文件可很好地与协作联机编辑工具结合使用。

示例Example

下面是一个包含两个法语字符串(其中一个具有复数形式)转换的示例 PO 文件:

fr.po

  1. #: Services/EmailService.cs:29
  2. msgid "Enter a comma separated list of email addresses."
  3. msgstr "Entrez une liste d'emails séparés par une virgule."
  4. #: Views/Email.cshtml:112
  5. msgid "The email address is \"{0}\"."
  6. msgid_plural "The email addresses are \"{0}\"."
  7. msgstr[0] "L'adresse email est \"{0}\"."
  8. msgstr[1] "Les adresses email sont \"{0}\""

此示例使用下列语法:

  • #::用于指示要转换的字符串的上下文的注释。根据使用的位置,可对相同字符串进行不同转换。
  • msgid:未转换的字符串。
  • msgstr:已转换的字符串。

在支持复数形式的情况下,可定义多个条目。

  • msgid_plural:未转换的复数形式字符串。
  • msgstr[0]:针对事例 0 的已转换的字符串。
  • msgstr[N]:针对事例 N 的已转换的字符串。

可在此处找到 PO 文件规范。

在 ASP.NET Core 中配置 PO 文件支持Configuring PO file support in ASP.NET Core

此示例基于从 Visual Studio 2017 项目模板中生成的 ASP.NET Core MVC 应用程序。

引用包Referencing the package

添加对 OrchardCore.Localization.Core NuGet 包的引用。它可在 MyGet 上的以下包源中获得: https://www.myget.org/F/orchardcore-preview/api/v3/index.json

.csproj 文件现在包含类似于以下内容的行(版本号可能不同):

  1. <PackageReference Include="OrchardCore.Localization.Core" Version="1.0.0-beta1-3187" />

注册服务Registering the service

将所需服务添加到 Startup.cs 的 ConfigureServices 方法:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc()
  4. .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);
  5. services.AddPortableObjectLocalization();
  6. services.Configure<RequestLocalizationOptions>(options =>
  7. {
  8. var supportedCultures = new List<CultureInfo>
  9. {
  10. new CultureInfo("en-US"),
  11. new CultureInfo("en"),
  12. new CultureInfo("fr-FR"),
  13. new CultureInfo("fr")
  14. };
  15. options.DefaultRequestCulture = new RequestCulture("en-US");
  16. options.SupportedCultures = supportedCultures;
  17. options.SupportedUICultures = supportedCultures;
  18. });
  19. }

将所需中间件添加到 Startup.cs 的 Configure 方法:

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. app.UseBrowserLink();
  7. }
  8. else
  9. {
  10. app.UseExceptionHandler("/Home/Error");
  11. }
  12. app.UseStaticFiles();
  13. app.UseRequestLocalization();
  14. app.UseMvcWithDefaultRoute();
  15. }

将以下代码添加到所选的 Razor 视图中。在此示例中,使用了 About.cshtml 。

  1. @using Microsoft.AspNetCore.Mvc.Localization
  2. @inject IViewLocalizer Localizer
  3. <p>@Localizer["Hello world!"]</p>

注入了 IViewLocalizer 实例并将其用于转换文本“Hello world!”。

创建 PO 文件Creating a PO file

在应用程序根文件夹中创建名为 <culture code>.po 的文件。在此示例中,文件名为 fr.po ,因为使用了法语:

  1. msgid "Hello world!"
  2. msgstr "Bonjour le monde!"

此文件存储了要转换的字符串和已转换为法语的字符串。如有必要,转换将还原为其父级区域性。在此示例中,如果请求的区域性为 fr-FRfr-CA,则使用 fr.po 文件。

测试应用程序Testing the application

运行应用程序并导航到 URL /Home/About此时将显示文本 Hello world!

导航到 URL /Home/About?culture=fr-FR此时将显示文本 Bonjour le monde!

复数形式Pluralization

PO 文件支持复数形式,在相同字符串需要基于基数以不同方式进行转换时,这非常有用。此任务较为复杂,因为每种语言均定义了自定义规则,以基于基数选择要使用的字符串。

Orchard 本地化包提供了一个 API 以自动调用这些不同的复数形式。

创建复数形式 PO 文件Creating pluralization PO files

将以下内容添加到前面所述的 fr.po 文件:

  1. msgid "There is one item."
  2. msgid_plural "There are {0} items."
  3. msgstr[0] "Il y a un élément."
  4. msgstr[1] "Il y a {0} éléments."

有关此示例中每个条目所表示的内容的说明,请参阅什么是 PO 文件?

使用不同的复数形式添加语言Adding a language using different pluralization forms

前面的示例中使用了英语和法语字符串。英语和法语只有两种复数形式且拥有相同形式规则,即一的基数映射到第一种复数形式。任何其他基数映射到第二种复数形式。

并非所有语言都拥有相同的规则。捷克语就是一个例子,它具有三种复数形式。

如下所示,创建 cs.po 文件,并记下复数形式如何需要三种不同转换:

  1. msgid "Hello world!"
  2. msgstr "Ahoj světe!!"
  3. msgid "There is one item."
  4. msgid_plural "There are {0} items."
  5. msgstr[0] "Existuje jedna položka."
  6. msgstr[1] "Existují {0} položky."
  7. msgstr[2] "Existuje {0} položek."

若要接受捷克语本地化,请将 "cs" 添加到 ConfigureServices 方法中受支持的区域性列表:

  1. var supportedCultures = new List<CultureInfo>
  2. {
  3. new CultureInfo("en-US"),
  4. new CultureInfo("en"),
  5. new CultureInfo("fr-FR"),
  6. new CultureInfo("fr"),
  7. new CultureInfo("cs")
  8. };

编辑 Views/Home/About.cshtml 文件以呈现一些基数的已本地化复数形式字符串:

  1. <p>@Localizer.Plural(1, "There is one item.", "There are {0} items.")</p>
  2. <p>@Localizer.Plural(2, "There is one item.", "There are {0} items.")</p>
  3. <p>@Localizer.Plural(5, "There is one item.", "There are {0} items.")</p>

注意: 在实际方案中,将使用变量表示计数。此处,我们通过三个不同的值重复相同代码,以公开非常特定的事例。

切换区域性时,将显示如下内容:

对于 /Home/About

  1. There is one item.
  2. There are 2 items.
  3. There are 5 items.

对于 /Home/About?culture=fr

  1. Il y a un élément.
  2. Il y a 2 éléments.
  3. Il y a 5 éléments.

对于 /Home/About?culture=cs

  1. Existuje jedna položka.
  2. Existují 2 položky.
  3. Existuje 5 položek.

请注意,对于捷克语区域性,这三种转换各不相同。对于最后两个已转换字符串,法语和英语区域性具有相同构造。

高级任务Advanced tasks

将字符串置于上下文中理解Contextualizing strings

应用程序通常包含要在多个位置中进行转换的字符串。在应用中的特定位置(Razor 视图或类文件),相同字符串可能具有不同转换。PO 文件支持文件上下文概念,此概念可用于对所表示的字符串进行分类。使用文件上下文,可将字符串进行不同转换,具体取决于文件上下文(或缺乏文件上下文)。

PO 本地化服务使用完整类的名称或转换字符串时使用的视图。这通过在 msgctxt 条目上设置值来完成。

请考虑对以前的 fr.po 示例作一点小小的补充。可通过设置保留的 msgctxt 条目的值将位于 Views/Home/About.cshtml 的 Razor 视图定义为文件上下文:

  1. msgctxt "Views.Home.About"
  2. msgid "Hello world!"
  3. msgstr "Bonjour le monde!"

这样设置 msgctxt 后,导航到 /Home/About?culture=fr-FR 时将发生文本转换。而导航到 /Home/Contact?culture=fr-FR 时,则不发生转换。

当没有特定条目与给定文件上下文相匹配时,Orchard Core 的回退机制将在没有上下文的情况下查找适当的 PO 文件。假设不存在针对 Views/Home/Contact.cshtml 定义的特定文件上下文,导航到 /Home/Contact?culture=fr-FR,加载 PO 文件,如:

  1. msgid "Hello world!"
  2. msgstr "Bonjour le monde!"

更改 PO 文件的位置Changing the location of PO files

可以在 ConfigureServices 中更改 PO 文件的默认位置:

  1. services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");

在此示例中,从本地化 文件夹加载 PO 文件。

实现用于查找本地化文件的自定义逻辑Implementing a custom logic for finding localization files

当需要更复杂的逻辑以查找 PO 文件时,可实现 OrchardCore.Localization.PortableObject.ILocalizationFileLocationProvider 接口并将其注册为服务。在可将 PO 文件存储于不同位置或在文件夹层次结构中找到文件时,这非常有用。

使用不同默认复数形式语言Using a different default pluralized language

此包包含特定于两种复数形式的 Plural 扩展方法。对于需要更多复数形式的语言,请创建扩展方法。通过扩展方法,无需提供默认语言的任何本地化文件 — 可在代码中直接使用原始字符串。

可使用更加广泛的、接受转换的字符串数组的 Plural(int count, string[] pluralForms, params object[] arguments) 重载。