WPF 全球化和本地化概述

将产品的可用性限制为仅一种语言时,可将潜在客户群限制为全球 75 亿人口的一小部分。 如果希望应用程序面向全球受众,产品的成本高效本地化是接触更多客户的最佳且最经济的方法之一。

本概述介绍 Windows Presentation Foundation(WPF)中的全球化和本地化。 全球化是在多个位置执行的应用程序的设计和发展。 例如,全球化为不同文化的用户提供支持,通过本地化用户界面和区域性数据。 WPF 提供全球化的设计功能,包括自动布局、附属程序集和本地化属性和注释。

本地化是将应用程序资源转换为应用程序支持的特定区域性的本地化版本。 在 WPF 中本地化时,请使用命名空间中的 System.Windows.Markup.Localizer API。 这些 API 为 LocBaml 工具示例 命令行工具提供支持。 有关如何生成和使用 LocBaml 的信息,请参阅 本地化应用程序

警告

LocBaml 工具仅适用于 .NET Framework 项目的 WPF,它不适用于用于 .NET 的 WPF。

WPF 中的全球化和本地化最佳做法

可以遵循本部分提供的 UI 设计和本地化相关提示,充分利用 WPF 中内置的全球化和本地化功能。

WPF UI 设计的最佳做法

设计基于 WPF 的 UI 时,请考虑实现以下最佳做法:

  • 使用 XAML 编写 UI;避免在代码中创建 UI。 使用 XAML 创建 UI 时,可以通过内置本地化 API 公开 UI。

  • 避免使用绝对位置和固定大小来布局内容;请改用相对大小或自动大小调整。

    • 使用 SizeToContent 和保持宽度和高度设置为 Auto

    • 避免使用Canvas来布局UI。

    • 使用 Grid 及其大小共享功能。

  • 在边距中提供额外的空间,因为本地化文本通常需要更多空间。 额外的空间允许可能存在的悬挂字符。

  • 启用TextWrappingTextBlock以避免裁剪。

  • 设置xml:lang属性。 此属性描述特定元素及其子元素的文化。 此属性的值更改 WPF 中多个功能的行为。 例如,它会更改断字、拼写检查、数字替换、复杂脚本整形和字体回退的行为。 有关在 XAML 中设置 xml:lang 处理的详细信息,请参阅 WPF 的全球化

  • 创建自定义复合字体,以便更好地控制用于不同语言的字体。 默认情况下,WPF 在 Windows\Fonts 目录中使用 GlobalUserInterface.composite 字体。

  • 创建可能采用从右向左格式呈现文本文化的导航应用程序时,请显式设置每个页面的FlowDirection,以确保页面不从NavigationWindow继承FlowDirection

  • 创建在浏览器外部托管的独立导航应用程序时,请将StartupUri初始应用程序设置为NavigationWindow而不是页面(例如<Application StartupUri="NavigationWindow.xaml">)。 通过此设计,您可以更改窗口和导航栏的FlowDirection。 有关详细信息和示例,请参阅 全球化主页示例

WPF 本地化的最佳做法

本地化基于 WPF 的应用程序时,请考虑实现以下最佳做法:

  • 使用本地化注释为本地化人员提供额外的上下文。

  • 使用本地化属性控制本地化,而不是选择性地省略 Uid 元素的属性。 有关详细信息 ,请参阅本地化属性和注释

  • 在 XAML 中使用 msbuild -t:updateuid-t:checkuid 来添加和检查 Uid 属性。 使用 Uid 属性跟踪开发和本地化之间的更改。 Uid 属性有助于本地化新的开发更改。 如果手动将属性添加到 Uid UI,则任务通常很繁琐且不太准确。

    • 开始本地化后,请勿编辑或更改 Uid 属性。

    • 请勿使用重复 Uid 属性(使用复制和粘贴命令时请记住此提示)。

    • 设置 AssemblyInfo.* 中的 UltimateResourceFallback 位置,以指定回退的适当语言(例如[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)])。

      如果决定通过省略项目文件中的<UICulture>标记将源语言包含在主程序集中,请将UltimateResourceFallback位置设置为主程序集而不是附属程序集(例如)。 [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]

本地化 WPF 应用程序

本地化 WPF 应用程序时,有多个选项。 例如,可以将应用程序中的可本地化资源绑定到 XML 文件、将可本地化文本存储在 resx 表中,或者让本地化程序使用 XAML 文件。 本部分介绍一个本地化工作流,该工作流使用 XAML 的 BAML 形式,它提供了以下几个优势:

  • 可以在生成后进行本地化。

  • 可以将较旧版本的 BAML 形式的 XAML 中的本地化信息更新到较新版本的 BAML 形式的 XAML,以便你可以在开发的同时进行本地化。

  • 你可以在编译时验证原始源元素和语义,因为 XAML 的 BAML 形式是 XAML 的编译形式。

本地化构建过程

开发 WPF 应用程序时,本地化的生成过程如下所示:

  • 开发人员创建并全球化 WPF 应用程序。 在项目文件中,开发人员设置 <UICulture>en-US</UICulture> ,以便在编译应用程序时生成非特定语言的主程序集。 此程序集具有包含所有可本地化资源的附属 .resources.dll 文件。 (可选)可以将源语言保留在主程序集中,因为我们的本地化 API 支持从主程序集提取。

  • 在生成过程中,将文件编译时,XAML 被转换为 BAML 格式的 XAML。 文化中立 MyDialog.exe 和文化依赖(英语) MyDialog.resources.dll 文件将发布给讲英语的客户。

本地化工作流

本地化过程在生成未本地化 MyDialog.resources.dll 的文件后开始。 通过在System.Windows.Markup.Localizer下使用 API,将原始 XAML 中的 UI 元素和属性从 XAML 的 BAML 形式提取为键值对。 本地化人员使用键值对本地化应用程序。 本地化完成后,可以从新值生成新的 .resource.dll。

键值对的键是 x:Uid 开发人员在原始 XAML 中放置的值。 通过这些 x:Uid 值,API 可以跟踪和合并在本地化期间开发人员和本地化程序之间发生的更改。 例如,如果开发人员在本地化程序开始本地化后更改 UI,则可以将开发更改与已完成的本地化工作合并,以便丢失最少的翻译工作。

下图显示了基于 XAML BAML 形式的典型本地化工作流。 此图假定开发人员用英语编写应用程序。 开发人员创建并全球化 WPF 应用程序。 在项目文件中,开发人员集 <UICulture>en-US</UICulture> 以便生成时,使用包含所有可本地化资源的附属 .resources.dll 生成非特定语言主程序集。 或者,可以保留主程序集中的源语言,因为 WPF 本地化 API 支持从主程序集提取。 生成过程后,XAML 将编译为 BAML。 文化中立的 MyDialog.exe.resources.dll 被运送到讲英语的客户。

本地化工作流图示。

显示未本地化工作流的关系图。

WPF 本地化示例

本部分包含本地化应用程序的示例,可帮助你了解如何生成和本地化 WPF 应用程序。

“运行”对话框示例

下图显示了 “运行 ”对话框示例的输出。

英语:

显示“英语运行”对话框的屏幕截图。

德语:

显示“德文运行对话框”的屏幕截图。

设计全局运行对话框

此示例使用 WPF 和 XAML 生成 “运行 ”对话框。 此对话框等效于Microsoft Windows 开始菜单中提供的 “运行 ”对话框。

用于创建全局对话框的一些亮点包括:

自动布局

在 Window1.xaml 中:

<Window SizeToContent="WidthAndHeight">

上一个 Window 属性根据内容的大小自动调整窗口大小。 此属性可防止窗口切断本地化后增大的内容,当内容在本地化后减小时,它还会删除多余的空间。

<Grid x:Uid="Grid_1">

Uid 需要属性才能使 WPF 本地化 API 正常工作。

WPF 本地化 API 使用这些 API 来跟踪用户界面(UI)开发和本地化之间的更改。 Uid 属性使你可以将较新版本的 UI 与 UI 的较旧本地化合并。 在命令行界面中运行msbuild -t:updateuid RunDialog.csproj来添加Uid属性。 这是添加 Uid 属性的建议方法,因为手动添加属性通常是耗时且不太准确的。 可以通过运行msbuild -t:checkuid RunDialog.csproj来检查Uid属性是否正确设置。

通过使用 Grid 控件可以构建 UI,它是一个在 WPF 中利用自动布局的有用控件。 请注意,对话框拆分为三行和五列。 行定义和列定义中没有固定大小;因此,在每个单元格中定位的 UI 元素可以适应本地化期间增加和减小大小。

<Grid.ColumnDefinitions>
  <ColumnDefinition x:Uid="ColumnDefinition_1" />
  <ColumnDefinition x:Uid="ColumnDefinition_2" />

Open: 标签和 ComboBox 前两列占据 UI 总宽度的 10%。

  <ColumnDefinition x:Uid="ColumnDefinition_3" SharedSizeGroup="Buttons" />
  <ColumnDefinition x:Uid="ColumnDefinition_4" SharedSizeGroup="Buttons" />
  <ColumnDefinition x:Uid="ColumnDefinition_5" SharedSizeGroup="Buttons" />
</Grid.ColumnDefinitions>

请注意示例中,使用了 Grid 的共享大小调整功能。 最后三列通过将自身置于同一 SharedSizeGroup位置来利用这一点。 正如属性名称所期望的那样,这允许列共享相同的大小。 因此,当“浏览...”被本地化为较长的字符串“Durchsuchen...”时,所有按钮的宽度会一起增大,以避免出现一个小的“确定”按钮和一个不成比例的大“Durchsuchen...”按钮。

xml:lang

xml:lang="en-US"

请注意位于 UI 根元素的 XAML 中的 xml:lang 处理。 此属性描述给定元素及其子元素的文化。 此值由 WPF 中的多个功能使用,应在本地化期间适当更改。 此值更改用于连字符和拼写检查单词的语言字典。 它还会影响数字的显示以及字体回退系统选择要使用的字体的方式。 最后,该属性会影响数字的显示方式,以及用复杂脚本编写的文本的排版方式。 默认值为“en-US”。

构建卫星资源程序集

在 .csproj 中:

编辑.csproj文件,并将以下标签添加到<PropertyGroup>无条件:

<UICulture>en-US</UICulture>

请注意已经添加的UICulture 值。 如果将此值设置为有效 CultureInfo 值(如 en-US),编译项目时将生成一个附属程序集,其中包含所有可本地化的资源。

<Resource Include="RunIcon.JPG">

<Localizable>False</Localizable>

</Resource>

RunIcon.JPG 无需本地化,因为它在所有文化中都应显示相同。 Localizable 设置为 false 使其保留在语言无关的主程序集中,而不是附属程序集。 所有不可编译资源的 Localizable 默认值设置为 true

本地化运行对话框

解析

生成应用程序后,本地化应用程序的第一步是解析附属程序集中的可本地化资源。 出于本主题的目的,请使用可在 LocBaml 工具示例中找到的示例 LocBaml 工具。 请注意,LocBaml 只是一个示例工具,旨在帮助你开始构建适合本地化过程的本地化工具。 使用 LocBaml,运行以下命令以分析: LocBaml /parse RunDialog.resources.dll /out: 生成“RunDialog.resources.dll。CSV“文件。

警告

LocBaml 工具仅适用于 .NET Framework 项目的 WPF,它不适用于用于 .NET 的 WPF。

本地化

使用支持 Unicode 的常用 CSV 编辑器编辑此文件。 筛选出本地化类别为“None”的所有条目。 应会看到以下条目:

资源密钥 本地化类别 价值
Button_1:System.Windows.Controls.Button.$Content 按钮 好的
Button_2:System.Windows.Controls.Button.$Content 按钮 取消
Button_3:System.Windows.Controls.Button.$Content 按钮 浏览。。。
ComboBox_1:System.Windows.Controls.ComboBox.$Content ComboBox
TextBlock_1:System.Windows.Controls.TextBlock.$Content 文本 键入程序、文件夹、文档或 Internet 资源的名称,Windows 将为你打开它。
TextBlock_2:System.Windows.Controls.TextBlock.$Content 文本 打开:
Window_1:System.Windows.Window.Title 标题 跑步

将应用程序本地化为德语需要以下翻译:

资源密钥 本地化类别 价值
Button_1:System.Windows.Controls.Button.$Content 按钮 好的
Button_2:System.Windows.Controls.Button.$Content 按钮 Abbrechen
Button_3:System.Windows.Controls.Button.$Content 按钮 浏览…
ComboBox_1:System.Windows.Controls.ComboBox.$Content ComboBox
TextBlock_1:System.Windows.Controls.TextBlock.$Content 文本 Geben Sie den Namen eines Programms, Ordners, Dokuments oder einer Internetresource an.
TextBlock_2:System.Windows.Controls.TextBlock.$Content 文本 打开
Window_1:System.Windows.Window.Title 标题 跑步

生成

本地化的最后一步是创建新的本地化卫星程序集。 这可以通过以下 LocBaml 命令完成:

LocBaml.exe /generate RunDialog.resources.dll /trans:RunDialog.resources.dll。CSV /out: . /cul:de-DE

在德语 Windows 上,如果此 resources.dll 放置在主程序集旁边的 de-DE 文件夹中,则此资源将自动加载,而不是 en-US 文件夹中的资源。 如果没有德语版本的 Windows 来测试此功能,请将区域性设置为你正在使用的任何 Windows 区域性(例如 en-US),并替换掉原始的资源 DLL。

卫星资源加载

MyDialog.exe en-US\MyDialog.resources.dll de-DE\MyDialog.resources.dll
代码 原版英语 BAML 本地化 BAML
文化中立资源 英语的其他资源 本地化为德语的其他资源

.NET 会自动根据应用程序的 Thread.CurrentUICulture选择加载的卫星资源程序集。 这默认为您 Windows 操作系统的语言环境。 如果使用德语 Windows, de-DE\MyDialog.resources.dll 文件将加载。 如果使用英语 Windows, en-US\MyDialog.resources.dll 文件将加载。 可以通过在项目的 AssemblyInfo 文件中指定NeutralResourcesLanguage属性来设置应用程序的最终回退资源。 例如,如果指定:

[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]

如果以下两个文件都不可用, 则会使用 en-US\MyDialog.resources.dll 文件与德语 Windows 一起: de-DE\MyDialog.resources.dllde\MyDialog.resources.dll

Microsoft沙特阿拉伯主页

下图显示了英语和阿拉伯语主页。 有关生成这些图形的完整示例,请参阅 全球化主页示例

英语:

显示英语主页的屏幕截图。

阿拉伯语:

显示阿拉伯语主页的屏幕截图。

设计全球Microsoft主页

这一Microsoft沙特阿拉伯网站的模拟说明了为 RightToLeft 语言提供的全球化功能。 希伯来语和阿拉伯语等语言具有从右到左的阅读顺序,因此 UI 的布局通常与从左到右的语言(如英语)布局大相径庭。 从左到右语言与从右到左语言之间的本地化过程可能相当具有挑战性。 WPF 旨在使此类本地化更加容易。

流向

Homepage.xaml:

<Page x:Uid="Page_1" x:Class="MicrosoftSaudiArabiaHomepage.Homepage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
    FlowDirection="LeftToRight" 
    Localization.Comments="FlowDirection(This FlowDirection controls the actual content of the homepage)"
    xml:lang="en-US">

请注意 Page 上的 FlowDirection 属性。 将此属性更改为 RightToLeft 将更改 Page 和其子元素的 FlowDirection,从而使此 UI 的布局翻转为从右到左,符合阿拉伯语用户的预期。 可以通过在任何元素上指定显式 FlowDirection 来替代继承行为。 该 FlowDirection 属性可用于任何 FrameworkElement 或文档相关元素,并且具有隐式值 LeftToRight

请注意,更改根 FlowDirection 时,即使是背景渐变画笔也会正确翻转:

FlowDirection=“LeftToRight”

显示从左到右的渐变流的屏幕截图。

FlowDirection=“RightToLeft”

显示从右到左的渐变流的屏幕截图。

避免对面板和控件使用固定维度

查看 Homepage.xaml,请注意,除了为顶部 DockPanel的整个 UI 指定的固定宽度和高度之外,没有其他固定尺寸。 避免使用固定的尺寸来防止截断可能长于源文本的本地化文本。 WPF 面板和控件将根据它们包含的内容自动调整大小。 大多数控件还具有可为更多控件设置的最小和最大尺寸(例如 MinWidth=“20”)。 在Grid中,您还可以使用“*”(例如Width="0.25*")设置相对宽度和高度,或者使用其单元格大小共享功能。

本地化注释

在许多情况下,内容可能含糊不清,难以翻译。 开发人员或设计器可以通过本地化注释向本地化人员提供额外的上下文和注释。 例如,下面的 Localization.Comments 阐明了字符“|”的用法。

<TextBlock 
  x:Uid="TextBlock_2" 
  DockPanel.Dock="Right" 
  Foreground="White" 
  Margin="5,0,5,0"
  Localization.Comments="$Content(This character is used as a decorative rule.)">
  |
</TextBlock>

此注释与TextBlock_1的内容相关联,在 LocBaml 工具(请参阅 本地化应用程序)的情况下,可以在输出 .csv 文件中TextBlock_1行的第 6 列中看到:

资源密钥 类别 可读的 可修改 注释 价值
TextBlock_1:System.Windows.Controls.TextBlock.$Content 文本 正确 正确 此字符用作装饰性规则。 |

可以使用以下语法将注释放置在任何元素的内容或属性上:

<TextBlock 
  x:Uid="TextBlock_1" 
  DockPanel.Dock="Right" 
  Foreground="White" 
  Margin="5,0,5,0"
  Localization.Comments="$Content(This is a comment on the TextBlock's content.)
     Margin(This is a comment on the TextBlock's Margin property.)">
  |
 </TextBlock>

本地化属性

通常,开发人员或本地化管理器需要控制本地化人员可以读取和修改的内容。 例如,你可能不希望本地化人员翻译公司的名称或法律措辞。 WPF 提供了使你能够设置元素内容或属性的可读性、可修改性和类别的属性,本地化工具可用于锁定、隐藏或排序元素的属性。 有关详细信息,请参阅 Attributes。 对于此示例,LocBaml 工具仅输出这些属性的值。 WPF 控件都具有这些属性的默认值,但你可以覆盖它们。 例如,以下示例替代了 TextBlock_1 的默认本地化属性,并将内容设置为对于本地化人员可读但不可修改。

<TextBlock
x:Uid="TextBlock_1"
Localization.Attributes=
"$Content(Readable Unmodifiable)">
  Microsoft Corporation
</TextBlock>

除了可读性和可修改性属性外,WPF 还提供通用 UI 类别(LocalizationCategory)的枚举,可用于为本地化人员提供更多上下文。 平台控件的 WPF 默认类别也可以在 XAML 中重写:

<TextBlock x:Uid="TextBlock_2">
<TextBlock.ToolTip>
<TextBlock
x:Uid="TextBlock_3"
Localization.Attributes=
"$Content(ToolTip Readable Unmodifiable)">
Microsoft Corporation
</TextBlock>
</TextBlock.ToolTip>
Windows Vista
</TextBlock>

WPF 提供的默认本地化属性也可以通过代码重写,以便正确为自定义控件设置正确的默认值。 例如:

[Localizability(Readability = Readability.Readable, Modifiability=Modifiability.Unmodifiable, LocalizationCategory.None)]
public class CorporateLogo : TextBlock
{
    // ...
}

XAML 中设置的每个实例属性将优先于在自定义控件的代码中设置的值。 有关属性和注释的详细信息,请参阅 本地化属性和注释

字体回退和复合字体

如果指定的字体不支持特定的代码点范围,那么 WPF 将会自动回退到使用位于 Windows\Fonts 目录中的 Global User Interface 复合字体。 复合字体的工作方式与任何其他字体相同,可以通过设置元素显式使用,例如使用 FontFamilyFontFamily="Global User Interface"。 可以通过创建自己的复合字体并指定要用于特定代码点范围和语言的字体来指定自己的字体回退首选项。

有关复合字体的详细信息,请参阅 FontFamily

本地化Microsoft主页

可以遵循与运行对话框示例相同的步骤来本地化此应用程序。 全球化 主页示例中提供了阿拉伯语的本地化 .csv 文件。