本地化
本地化是调整应用来满足目标市场的特定语言或区域性要求的过程。 若要本地化应用,可能需要将其文本和图像翻译成多种语言。 本地化后的应用会根据设备的区域性设置自动显示翻译后的文本:
.NET 包含一个使用资源文件进行应用本地化的机制。 资源文件将文本和其他内容存储为名称/值对,让应用能根据所提供的键值检索内容。 资源文件可使本地化后的内容与应用代码相分离。 除了存储文本之外,资源文件还可以存储图像和二进制数据。 但是,设备的屏幕大小和密度各异,而每个移动平台都有显示受到密度约束的图像的功能。 因此,应使用平台的功能来本地化图像,而不是将图像存储到资源文件。
要本地化 .NET Multi-platform App UI (.NET MAUI) 应用,你应执行以下操作:
- 创建资源文件以存储字符串。 有关详细信息,请参阅创建资源文件以存储字符串。
- 指定应用的非特定语言。 有关详细信息,请参阅指定应用的非特定语言。
- 执行平台设置。 有关详细信息,请参阅执行平台设置。
- 本地化文本。 有关详细信息,请参阅本地化文本。
- 本地化图像。 有关详细信息,请参阅本地化图像。
- 本地化应用名称。 有关详细信息,请参阅本地化应用名称。
- 对本地化进行测试。 有关详细信息,请参阅对本地化进行测试。
此外,还可以指定应用的布局方向。 有关详细信息,请参阅从右向左本地化。
创建资源文件以存储字符串
.NET 资源文件是扩展名为 .resx 的 XML 文件,它们在生成过程中会被编译为二进制资源 (.resources) 文件。 本地化后的应用通常包含一个默认资源文件,其中包含在应用中使用的所有字符串,还包含用于每种受支持语言的资源文件。
资源文件包含每个项的下列信息:
- 名称指定用于在代码中访问文本的键。
- 值指定翻译后的文本。
- 注释是包含其他信息的可选字段。
可通过 Visual Studio 中的“添加新项”对话框添加资源文件:
添加文件后,可为每个文本资源添加行:
“访问修饰符”下拉列表确定 Visual Studio 如何生成用于访问资源的类。 将“访问修饰符”设置为“公共”或“内部”会生成具有指定可访问性级别的类。 如果将“访问修饰符”设置为“无代码生成”,则不会生成类文件。 默认资源文件应配置为生成类文件,这样即可生成一个扩展名为 .Designer.cs 的文件,然后会将该文件添加到项目中。
创建默认资源文件后,可为应用支持的每个区域设置创建其他文件。 每个附加资源文件应具有与默认资源文件相同的根文件名,但还应在文件名中包含语言和可选区域性。 例如,如果添加名为 AppResources.resx 的资源文件,则还可以创建名为 AppResources.en-US.resx 和 AppResources.fr-FR.resx 的资源文件,以分别保存英语(美国)和法语(法国)区域性的本地化资源。 此外,应将每个附加资源文件的“访问修饰符”设置为“无代码生成”。
运行时期间,应用会按指定顺序尝试解析资源请求。 例如,如果设备区域性是 en-US,应用程序将按以下顺序查找资源文件:
- AppResources.en-US.resx
- AppResources.en.resx
- AppResources.resx(默认)
以下屏幕截图显示了名为 AppResources.es.resx 的西班牙语翻译文件:
这个本地化资源文件使用在默认文件中指定的同一个“名称”值,但在“值”列中包含西班牙语字符串。 此外,“访问修饰符”设置为“不生成代码”。
指定应用的非特定语言
为了使 .NET 资源文件正常工作,必须为应用指定非特定语言。 如果找不到某个区域设置的资源,则使用该语言的资源。 若要指定非特定语言,请执行以下操作:
在“解决方案资源管理器”中,右键单击 .NET MAUI 应用项目,然后选择“属性”。
选择“包 > 常规”属性页,然后从“程序集非特定语言”下拉列表中选择相应的语言和区域性:
保存所做更改。
或者,将 <NeutralLanguage>
元素添加到项目文件的第一个 <PropertyGroup>
,并指定所选区域设置作为其值:
<NeutralLanguage>en-US</NeutralLanguage>
警告
如果未指定非特定语言,对于没有资源文件的任何语言,ResourceManager 类将返回 null
值。 指定了非特定语言时,对于不受支持的语言,ResourceManager 类将返回非特定语言资源文件中的结果。 因此,建议始终指定非特定语言,以便显示不受支持语言的文本。
执行平台设置
在 iOS、Mac Catalyst 和 Windows 上,还需要执行额外设置,以便本地化所有 .NET MAUI 控件。
iOS 和 Mac Catalyst
在 iOS 和 Mac Catalyst 上,必须在 .NET MAUI 应用项目的平台 Info.plist 文件中声明所有受支持的语言。 为此,请在 XML 编辑器中打开所选平台的 Info.plist 文件,并为 CFBundleLocalizations
键创建数组。 然后提供与资源文件相对应的数组值。 此外,请确保通过 CFBundleDevelopmentRegion
键设置所需的语言:
<key>CFBundleLocalizations</key>
<array>
<string>de</string>
<string>es</string>
<string>fr</string>
<string>ja</string>
<string>pt</string> <!-- Brazil -->
<string>pt-PT</string> <!-- Portugal -->
<string>ru</string>
<string>zh-Hans</string>
<string>zh-Hant</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
或者,在 Visual Studio 的“解决方案资源管理器”的“泛型 PList 编辑器”中,打开所选平台的 Info.plist 文件。 然后,为 CFBundleLocalizations
键创建一个数组,并提供与资源文件相对应的数组值。 此外,请确保通过 CFBundleDevelopmentRegion
键设置所需的语言:
有关 Info.plist 文件的详细信息,请参阅信息属性列表。
Windows
为了在 Windows 上的 .NET MAUI 应用中支持多种语言,必须在 .NET MAUI 应用项目的 Platforms\Windows\Package.appxmanifest 文件中声明每种受支持的语言:
在文本编辑器中打开 Package.appxmanifest 文件,并找到以下部分:
<Resources> <Resource Language="x-generate"/> </Resources>
将每种受支持语言的
<Resource Language="x-generate">
替换为<Resource />
元素:<Resources> <Resource Language="en-US"/> <Resource Language="de-DE"/> <Resource Language="es-ES"/> <Resource Language="fr-FR"/> <Resource Language="ja-JP"/> <Resource Language="pt-BR"/> <Resource Language="pt-PT"/> <Resource Language="ru-RU"/> <Resource Language="zh-CN"/> <Resource Language="zh-TW"/> </Resources>
保存所做更改。
对文本进行本地化
文本的本地化是使用从默认资源文件生成的类进行的。 会根据默认资源文件名称为该类命名。 假设默认资源文件名为 AppResources.resx,Visual Studio 将生成名为 AppResources
的匹配类,其中包含资源文件中每个条目的静态属性。
在 XAML 中,可以使用 x:Static
标记扩展来检索本地化文本,以访问生成的静态属性:
<ContentPage ...
xmlns:strings="clr-namespace:LocalizationDemo.Resources.Strings">
<VerticalStackLayout>
<Label Text="{x:Static strings:AppResources.NotesLabel}" />
<Entry Placeholder="{x:Static strings:AppResources.NotesPlaceholder}" />
<Button Text="{x:Static strings:AppResources.AddButton}" />
</VerticalStackLayout>
</ContentPage>
有关 x:Static
标记扩展的详细信息,请参阅 x:Static 标记扩展。
还可在代码中检索本地化文本:
Label notesLabel = new Label();
notesLabel.Text = AppResources.NotesLabel,
Entry notesEntry = new Entry();
notesEntry.Placeholder = AppResources.NotesPlaceholder,
Button addButton = new Button();
addButton.Text = AppResources.AddButton,
AppResources
类中的属性使用 CurrentUICulture 属性值来确定要从中检索值的资源文件。
本地化图像
除了存储文本之外,资源文件还可以存储图像和二进制数据。 但是,设备的屏幕大小和密度各异,而每个移动平台都有显示受到密度约束的图像的功能。 因此,应使用平台的功能来本地化图像,而不是将图像存储到资源文件。
Android
在 Android 上,会使用基于文件夹的命名约定将本地化图像(即可绘制资源)存储在 Platforms\Android\Resources 文件夹中。 文件夹应命名为 drawable,并附上表示语言和区域性的后缀。 例如,西班牙语文件夹命名为 drawable-es。 drawable 文件夹应包含与默认语言和区域性对应的图像。 每个图像的生成操作应设置为 AndroidResource。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 AndroidResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<AndroidResource Include="Platforms\Android\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\Android\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 AndroidResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
指定顶级语言时,文件夹名称中只需要两个字符,例如 es。 但是,指定完整区域设置时,文件夹名称格式必须使用短划线和小写 r 将语言与区域性分开。 例如,墨西哥区域设置 (es-MX) 文件夹应命名为 drawable-es-rMX。 每个区域设置文件夹中的图像文件名应相同:
iOS
在 iOS 上,本地化后的图像将使用基于文件夹的命名约定存储在 Platforms\iOS\Resources 文件夹中。 文件夹应以语言和可选区域性命名,后跟 .lproj。 例如,西班牙语文件夹命名为 es.lproj。 每个图像的生成操作应设置为 BundleResource。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 BundleResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-ios'))">
<BundleResource Include="Platforms\iOS\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\iOS\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 BundleResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
指定顶级语言时,文件夹名称中只需要两个字符,例如 es。 但是,指定完整区域设置时,文件夹名称格式必须使用短划线来分隔语言与区域性。 例如,墨西哥区域设置 (es-MX) 文件夹应命名为 es-MX.lproj。 每个区域设置文件夹中的图像文件名应相同:
如果某个图像在某个语言中不存在,则 iOS 会返回到默认本机语言文件夹,并从那里加载图像。
Mac Catalyst
在 Mac Catalyst 上,会使用基于文件夹的命名约定将本地化图像存储在 Platforms\MacCatalyst\Resources 文件夹中。 文件夹应以语言和可选区域性命名,后跟 .lproj。 例如,西班牙语文件夹命名为 es.lproj。 每个图像的生成操作应设置为 BundleResource。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 BundleResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-maccatalyst'))">
<BundleResource Include="Platforms\MacCatalyst\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\MacCatalyst\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 BundleResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
指定顶级语言时,文件夹名称中只需要两个字符,例如 es。 但是,指定完整区域设置时,文件夹名称格式必须使用短划线来分隔语言与区域性。 例如,墨西哥区域设置 (es-MX) 文件夹应命名为 es-MX.lproj。 每个区域设置文件夹中的图像文件名应相同:
如果某个图像在某个语言中不存在,则 Mac Catalyst 会返回默认的本机语言文件夹,并从那里加载图像。
Windows
在 Windows 上,本地化图像将使用基于文件夹的命名约定存储在 Platforms\Windows\Assets\Images 文件夹中。 文件夹应以语言和可选区域性命名。 例如,西班牙语文件夹以 es 命名,墨西哥区域设置文件夹应以 es-MX 命名。 每个图像的生成操作应设置为“内容”。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为“内容”生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
<Content Include="Platforms\Windows\Assets\Images\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\Windows\Assets\Images 文件夹中的所有内容(包括子文件夹中的内容)设置为“内容”生成操作。 还会使用此生成操作设置每个文件的输出路径。
指定顶级语言时,文件夹名称中只需要两个字符,例如 es。 但是,指定完整区域设置时,文件夹名称格式必须使用短划线来分隔语言与区域性。 例如,应将墨西哥区域设置 (es-MX) 文件夹命名为 es-MX。 每个区域设置文件夹中的图像文件名应相同:
使用本地化图像
在 Android、iOS、Mac Catalyst 和 Windows 上,可以通过将 Image 的 Source 属性设置为图像文件名来使用本地化图像:
<Image Source="flag.png" />
但是,为了能够在 Windows 上使用,如果已为每个本地化图像添加了 <Content />
MSBuild 项,则需要修改应用的项目文件。 为了实现这一点,可以通过修改 .csproj 文件来删除每个本地化图像的 <Content />
MSBuild 项。 然后,添加以下 MSBuild 项:
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
<Content Include="Platforms\Windows\Assets\Images\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
这可确保将 Platforms\Windows\Assets\Images 文件夹的子文件夹中的所有图像都复制到应用包的根目录中。
对应用名称进行本地化
必须使用平台功能来本地化应用名称。
Android
在 Android 上,会使用基于文件夹的命名约定将本地化的应用名称存储在 Platforms\Android\Resources 文件夹中。 应将文件夹命名为 values,并附上语言和区域性作为后缀。 例如,应将西班牙语文件夹命名为 values-es。 将具有 AndroidResource 生成操作的 Strings.xml 文件添加到将字符串设置为本地化应用名称的每个文件夹。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 AndroidResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<AndroidResource Include="Platforms\Android\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\Android\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 AndroidResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
指定顶级语言时,文件夹名称中只需要两个字符,例如 es。 但是,指定完整区域设置时,文件夹名称格式必须使用短划线和小写 r 将语言与区域性分开。 例如,应将墨西哥区域设置 (es-MX) 文件夹命名为 values-es-rMX。
每个可翻译字符串都是一个 XML 元素,其资源 ID 被指定为 name
特性,而翻译后的字符串会被指定为值。 需要根据常规 XML 规则对字符串进行转义,并且 name
必须是有效的 Android 资源 ID(无空格或短划线)。
因此,若要本地化应用名称,需创建 Strings.xml 文件,并将 <string>
元素添加为 <resources>
元素的子元素。 然后,将其 name
特性设置为合适的 ID(使用已翻译字符串作为值):
<resources>
<!-- French -->
<string name="app_name">Maison</string>
</resources>
然后,如果要在应用中使用本地化的应用名称,请将 Label
属性添加到应用的 MainActivity
类中的 Activity
,并将其值设置为 @string/id
:
[Activity(Label = "@string/app_name", Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
}
iOS
在 iOS 上,会使用基于文件夹的命名约定将本地化的应用名称存储在 Platforms\iOS\Resources 文件夹中。 文件夹应以语言和可选区域性命名,后跟 .lproj。 例如,西班牙语文件夹命名为 es.lproj。 向设置 CFBundleDisplayName
键和值的每个文件夹中添加一个 InfoPlist.strings 文件,该文件的生成操作为 BundleResource。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 BundleResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-ios'))">
<BundleResource Include="Platforms\iOS\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\iOS\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 BundleResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
本地化字符串值的语法为:
/* comment */
"key"="localized-value";
应转义字符串中的以下字符:
\"
报价\\
反斜杠\n
换行符
因此,如果要本地化应用名称,请创建 InfoPlist.strings 文件,并将 CFBundleDisplayName
键的值添加到文件中:
/* French */
CFBundleDisplayName="Maisons";
可用于本地化特定于应用的字符串的其他键包括:
CFBundleName
- 指定应用程序包的短名称,在缺少CFBundleDisplayName
的值等情况下,可能会向用户显示该名称。CFBundleShortVersionString
- 指定应用程序包的发布版本号。NSHumanReadableCopyright
- 应用程序包的版权声明。
Mac Catalyst
在 Mac Catalyst 上,会使用基于文件夹的命名约定将本地化的应用名称存储在 Platforms\MacCatalyst\Resources 文件夹中。 文件夹应以语言和可选区域性命名,后跟 .lproj。 例如,西班牙语文件夹命名为 es.lproj。 向设置 CFBundleDisplayName
键和值的每个文件夹中添加一个 InfoPlist.strings 文件,该文件的生成操作为 BundleResource。
注意
通过将以下 XML 添加到应用项目 (.csproj) 文件,可以将特定文件夹的内容设置为此生成操作,而不是将单个文件设置为 BundleResource 生成操作:
<ItemGroup Condition="$(TargetFramework.Contains('-maccatalyst'))">
<BundleResource Include="Platforms\MacCatalyst\Resources\**" TargetPath="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
本示例将 Platforms\MacCatalyst\Resources 文件夹中的所有内容(包括子文件夹中的内容)设置为 BundleResource 生成操作。 还会使用此生成操作设置每个文件的输出路径。
本地化字符串值的语法为:
/* comment */
"key"="localized-value";
应转义字符串中的以下字符:
\"
报价\\
反斜杠\n
换行符
因此,如果要本地化应用名称,请创建 InfoPlist.strings 文件,并将 CFBundleDisplayName
键的值添加到文件中:
/* French */
CFBundleDisplayName="Maisons";
可用于本地化特定于应用的字符串的其他键包括:
CFBundleName
- 指定应用程序包的短名称,在缺少CFBundleDisplayName
的值等情况下,可能会向用户显示该名称。CFBundleShortVersionString
- 指定应用程序包的发布版本号。NSHumanReadableCopyright
- 应用程序包的版权声明。
Windows
在 Windows 上,应用名称是在应用包清单中定义的。 本地化应用名称时,需要先指定应用的默认语言,然后为要支持的每个区域设置创建字符串资源文件。 然后,通过使用 ms-resource
URI 方案,可以在应用包清单中使用表示本地化应用名称的字符串资源。
有关本地化应用包清单中的字符串的详细信息,请参阅本地化 UI 和应用包清单中的字符串。
指定默认语言
要本地化应用名称,必须首先为 Windows 应用指定默认语言。 如果找不到特定语言的本地化资源,则使用该语言的资源。 若要指定默认语言,请执行以下步骤:
在“解决方案资源管理器”中,在包清单编辑器中打开 Package.appxmanifest 文件。
在包清单编辑器中,在“应用程序”选项卡上,将“默认语言”字段设置为所选的默认语言:
保存所做更改。
至少需要为默认语言的应用名称提供字符串资源。 如果无法为用户的首选语言或显示语言设置找到更好的匹配项,则会加载此资源。
创建 Windows 资源文件
在 Windows 上,应将本地化的应用名称存储在每个区域设置的 Windows 资源文件中。 Windows 资源文件是扩展名为 .resw 的 XML 文件,该文件编译为二进制格式并存储在 .pri 文件中。 每个区域设置的 .resw 文件应命名为 Resources.resw,并使用基于文件夹的命名约定存储在 Platforms\Windows\Strings 文件夹中。 文件夹应以语言和可选区域性命名。 例如,西班牙语文件夹以 es 命名,墨西哥区域设置文件夹应以 es-MX 命名。
目前没有用于在 .NET MAUI 应用中创建 Windows 资源文件的 Visual Studio 项模板。 因此,若要为每个区域设置创建 Windows 资源文件,请执行以下操作:
在 .NET MAUI 应用项目的 Platforms\Windows 文件夹中,创建 Strings 文件夹。
在 Strings 文件夹中,为每个区域设置创建一个文件夹。
在每个区域设置的文件夹中,创建名为 Resources.resw 的文件,其中包含以下 XML:
<?xml version="1.0" encoding="utf-8"?> <root> <!-- Microsoft ResX Schema Version 2.0 The primary goals of this format is to allow a simple XML format that is mostly human readable. The generation and parsing of the various data types are done through the TypeConverter classes associated with the data types. Example: ... ado.net/XML headers & schema ... <resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="version">2.0</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <value>[base64 mime encoded serialized .NET Framework object]</value> </data> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <comment>This is a comment</comment> </data> There are any number of "resheader" rows that contain simple name/value pairs. Each data row contains a name, and value. The row also contains a type or mimetype. Type corresponds to a .NET class that support text/value conversion through the TypeConverter architecture. Classes that don't support this are serialized and stored with the mimetype set. The mimetype is used for serialized objects, and tells the ResXResourceReader how to depersist the object. This is currently not extensible. For a given mimetype the value must be set accordingly: Note - application/x-microsoft.net.object.binary.base64 is the format that the ResXResourceWriter will generate, however the reader can read any of the formats listed below. mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64 value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:element name="root" msdata:IsDataSet="true"> <xsd:complexType> <xsd:choice maxOccurs="unbounded"> <xsd:element name="metadata"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" /> </xsd:sequence> <xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="assembly"> <xsd:complexType> <xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" /> </xsd:complexType> </xsd:element> <xsd:element name="data"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute ref="xml:space" /> </xsd:complexType> </xsd:element> <xsd:element name="resheader"> <xsd:complexType> <xsd:sequence> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:complexType> </xsd:element> </xsd:choice> </xsd:complexType> </xsd:element> </xsd:schema> <resheader name="resmimetype"> <value>text/microsoft-resx</value> </resheader> <resheader name="version"> <value>2.0</value> </resheader> <resheader name="reader"> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> <resheader name="writer"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader> </root>
注意
Windows 资源文件使用
PRIResource
生成操作。 不需要为 .NET MAUI 应用中的每个 .resw 文件设置此生成操作,因为它是隐式应用的。打开每个 Resources.resw 文件并添加一个表示应用名称的字符串资源:
注意
资源标识符不区分大小写,并且对于每个资源文件都必须是唯一的。
保存每个 Windows 资源文件。
以下屏幕截图展示了所需文件夹和文件结构的示例:
使用本地化的应用名称
可通过采用 ms-resource
URI 方案来使用表示本地化应用名称的字符串资源:
在“解决方案资源管理器”中,在包清单编辑器中打开 Package.appxmanifest 文件。
在包清单编辑器的“应用程序”选项卡中,将“显示名称”字段设置为
ms-resource:
,并在其后添加用于标识应用名称的字符串资源名称:保存所做更改。
重要
如果你的 .resw 文件存储在与你的 .NET MAUI 应用项目不同的程序集中,你需要指定资源名称的完全限定路径。 它使用格式 ms-resource:Assembly/ResourceFilename/Resource
。
从右到左本地化
流方向,也称布局方向,是指用肉眼浏览页面上 UI 元素的方向。 某些语言(例如阿拉伯语和希伯来语)需要按从右到左流动方向对 UI 元素进行布局。 .NET MAUI 应用会根据所选语言和区域自动遵循设备的流方向。 有关如何根据设备区域设置检索设备流方向的信息,请参阅获取布局方向。
若要替代应用的流方向,请设置 Window.FlowDirection 属性。 或者,根据每个元素设置 VisualElement.FlowDirection 属性。 这些属性可获取或设置 UI 元素在控制其布局的任何父元素中的流方向,并且应设置为 FlowDirection 枚举值之一:
LeftToRight
RightToLeft
MatchParent
将元素的 FlowDirection 属性设置为 RightToLeft
会将对齐方式设置为向右对齐,将读取顺序设置为从右到左,并将控件布局设置为从右向左排列。
警告
在运行时更改 FlowDirection 属性会导致布局过程的成本高昂,从而影响性能。
元素的默认 FlowDirection 属性值是 MatchParent
。 因此,元素从可视化树中的其父级处继承 FlowDirection
属性值,并且任何元素都可以替代该元素从其父级处获取的值。
提示
如果确实需要更改流方向,请设置窗口、页面或根布局上的 FlowDirection 属性。 这会导致应用、页面或根布局中包含的所有元素都能对流方向做出适当的响应。
平台设置
启用从右到左的区域设置需要特定平台设置。
Android
使用 .NET MAUI 应用项目模板创建的应用会自动支持从右到左区域设置。 此支持由在应用的 AndroidManifest.xml 文件中的 <application>
节点上设置为 true
的 android:supportsRtl
特性启用:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application ... android:supportsRtl="true" />
...
</manifest>
然后,可以通过将设备或仿真器更改为使用从右到左的语言来测试从右到左的本地化。 或者,如果在“设置”应用中激活了“开发人员”选项,则可以在“设置与开发人员”选项中启用“强制 RTL 布局方向”。 有关“配置开发人员”选项的信息,请参阅 developer.android.com 上的“配置设备上的开发人员”选项。
iOS 和 Mac Catalyst
所需的从右向左的区域设置应作为支持语言添加到 Info.plist 中的 CFBundleLocalizations
键的数组项。 下面的示例显示阿拉伯语已添加到 CFBundleLocalizations
键的数组:
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>ar</string>
</array>
然后可以通过将设备或模拟器上的语言和区域更改为 Info.plist 中指定的从右向左的区域设置,以测试从右到左的本地化。
Windows
应在“Package.appxmanifest”文件的 <Resources>
节点中指定所需语言资源。 将每种受支持语言的 <Resource Language="x-generate">
替换为 <Resource />
元素。 例如,以下标记指定 "en" 和 "ar" 本地化资源可用:
<Resources>
<Resource Language="en" />
<Resource Language="ar" />
</Resources>
然后可以通过将设备上的语言和区域更改为适当的从右向左的区域设置,测试从右到左的本地化。
对本地化进行测试
在运行时,应用会基于 CurrentUICulture 属性指定的区域性,按线程加载相应的本地化资源。
对本地化进行测试的最佳做法是通过在每台设备上的“设置”应用中更改设备语言来完成。
警告
虽然可以在代码中设置 CurrentUICulture 的值,但生成的行为在各平台之间不一致,因此不建议在测试中使用。