使用 Xamarin Forms 和 Calcium 构建本地化的跨平台应用






4.76/5 (8投票s)
利用现有的 .resx 文件在 Xamarin.Forms 中本地化 Windows Phone、Android 和 iOS 应用。
引言
Xamarin.Forms 是 Xamarin 的新跨平台 UI 框架,允许您使用 XAML 为 iOS、Android 和 Windows Phone 构建用户界面。
在本系列的前一部分中,您了解了如何通过绑定到 ViewModel 集合来创建选项卡页面或轮播页面。您学习了如何使用 MVVM 实现准数据模板选择器来具体化 ViewModel。
在本系列的第三部分中,您将了解如何在 Windows Phone、iOS 和 Android 这三个平台上使用相同的 .resx 文件。您将看到如何将 .resx 文件正确地链接到您的 Xamarin.iOS 项目中。您将学习如何设置 T4 模板并链接到提供的 T4 包含文件以生成 Android 友好的资源。最后,您将看到如何使用 x:Static 标记扩展从 XAML 中使用您的本地化资源。
在开始之前,如果您还没有阅读,我建议您先阅读本系列中的第一篇文章,然后再阅读本文。
本系列文章
- 第一部分. 介绍适用于 Xamarin Forms 的 Calcium
- 第2部分。使用 MVVM 和 Calcium for Xamarin Forms 创建选项卡式界面
- 第 3 部分:使用 Xamarin Forms 和 Calcium 构建可本地化的跨平台应用(本文)
- 第 4 部分:使用 Xamarin Forms 和 Calcium 创建跨平台应用程序栏
- 第5部分。使用 Calcium for Xamarin Forms 在共享资产项目中解析图像
- 第6部分。使用 Calcium for Windows Phone 创建用户选项页面
Calcium 和示例应用程序的源代码
Calcium for Xamarin.Forms 及示例的源代码位于 https://calcium.codeplex.com/SourceControl/latest
存储库中有各种解决方案。您感兴趣的是位于 \Trunk\Source\Calcium\Xamarin\Installation 目录下的 CalciumTemplates.Xamarin.sln。
CalciumTemplates.Xamarin 解决方案的结构如图 1 所示。您可以看到示例“模板”项目已被突出显示。这些项目包含本系列文章中介绍的大部分示例源代码。
图 1. CalciumTemplates.Xamarin 解决方案的结构
在项目之间共享本地化资源
在构建应用程序时,最好提前考虑本地化,而不是以后再尝试改造。在本文中,您将看到如何在 Windows Phone、iOS 和 Android 这三个平台上使用相同的 .resx 文件来本地化您的应用程序。不久前我写过一篇关于为 Android 应用程序添加本地化支持的文章。我们将回顾一些工作,同时也将涵盖在 iOS 中使用 resx 文件以及使用 x:Static 标记扩展以允许我们直接从 XAML 文件中使用本地化资源的新领域。我们首先查看资源目录命名约定以及将 .resx 文件集成到 iOS 项目中。
在共享来自 Windows Phone 应用程序的 .resx 文件时,需要注意一件事,即目录名“Resource”与内置的 Xamarin.Android 资源系统发生冲突。我开始新的 Xamarin 解决方案时做的第一件事就是将 Windows Phone 项目中 Resources 目录中的 AppResources.resx 文件移动到另一个目录中。我使用 CommonResources,但您可以随意命名。然后我将 AppResources.resx 文件链接到我的 iOS 项目中;在同名目录中。
在创建默认 .resx 文件的本地化版本时,此文件需要链接到您的 iOS 项目中,并且文件的“生成操作”设置为“BundleResource”。您可能会遇到设计器文件未正确位于 resx 文件下方的问题。您可以卸载您的 Windows Phone 项目和 iOS 项目并手动编辑 iOS .csproj 文件以对齐文件,或者,我建议使用 VSCommands 等工具正确嵌套设计器文件。如果您遇到麻烦,请卸载并仔细查看可下载的示例 iOS 项目以了解它应该是什么样子。您的 iOS 项目需要类似于列表 1 中所示的 ItemGroups。一旦您正确设置了这一点,您应该就可以开始了。
列表 1. 带有 Resx 文件的 iOS 项目
<ItemGroup>
<Compile Include="..\CalciumSampleApp.WindowsPhone\CommonResources\AppResources.Designer.cs">
<Link>CommonResources\AppResources.Designer.cs</Link>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>AppResources.resx</DependentUpon>
</Compile>
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<None Include="Info.plist" />
<Compile Include="Properties\AssemblyInfo.cs" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="..\CalciumSampleApp.WindowsPhone\CommonResources\AppResources.fr.resx">
<Link>CommonResources\AppResources.fr.resx</Link>
</BundleResource>
<EmbeddedResource Include="..\CalciumSampleApp.WindowsPhone\CommonResources\AppResources.resx">
<Link>CommonResources\AppResources.resx</Link>
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
<CustomToolNamespace>CalciumSampleApp</CustomToolNamespace>
</EmbeddedResource>
</ItemGroup>
Android 则是一个完全不同的故事。对于 Android,使用 .resx 文件需要像麦克吉弗那样使用 T4。在本节中,您将看到如何使用 T4 模板将 .resx 文件转换为 Android 友好的资源文件。
首先,在您的 Android 项目中创建一个存储本地化模板的位置。请注意不要将它们放在 Android 项目的 Resources 目录中。您可以创建如图 2 所示的目录结构。
图 2. Android 本地化目录结构
以下步骤将引导您创建此结构并设置 T4 模板以支持本地化
步骤 1。在您的 Android 项目中创建一个子目录来存储您的 T4 模板。在可下载的示例解决方案中,我创建了一个 ResourcesModel/T4Templates 子目录。您可以随意命名,但如果您偏离此命名方案,则可能需要对文件路径进行一些调整。
步骤 2。将可下载示例项目中的两个文本文件:ResxToAndroidAccessorClass.ttinclude 和 ResxToAndroidXml.ttinclude 放入 ResourcesModel/T4Templates/。将它们包含在您的项目中,并将其“生成操作”设置为“无”。
步骤 3。在 Visual Studio 中右键单击 ResourcesModel/T4Templates/ 目录,然后选择“添加新项”,并选择“文本文件”。在单击“添加”之前,将文件名称更改为“AppResources.tt”。
步骤 4。将以下文本粘贴到您新创建的 AppResources.tt 文件中
<#@ include file="ResxToAndroidAccessorClass.ttinclude " #>
<#@ output extension=".cs" #>
<#@ template language="C#" hostSpecific="true" #>
<#
Process(Path.GetDirectoryName(Host.TemplateFile) + "../../../../CalciumSampleApp.WindowsPhone/CommonResources/AppResources.resx", "CalciumSampleApp");
#>
步骤 5。将 "../../../../CalciumSampleApp.WindowsPhone/CommonResources/AppResources.resx" 替换为您 Windows Phone 项目中 .resx 文件的路径。并将 "CalciumSampleApp" 替换为您用于资源的命名空间。这在所有项目中必须保持一致。命名空间不匹配会阻止您从共享项目中消耗强类型资源。当您按下 Ctrl+S 保存 AppResources.tt 文件时,如果您的路径正确,您应该能够打开 AppResources.cs 文件以显示您的 Android 兼容的强类型资源属性。
步骤 6。您快完成了。在 Visual Studio 中,在 Android 项目的 Resources 目录中创建一个 Values 目录。这是您将生成字符串资源的地方。
步骤 7。就像在步骤 3 中一样,创建一个名为“Strings.tt”的新 T4 模板,并将以下文本粘贴到文件中
<#@ include file="..\..\ResourcesModel\T4Templates\ResxToAndroidXml.ttinclude" #>
<#@ output extension=".xml" #>
<#@ template language="C#" hostSpecific="true" #>
<#
Process(Path.GetDirectoryName(Host.TemplateFile)
+ "../../../../CalciumTemplateApp.WindowsPhone/CommonResources/AppResources.resx");
#>
步骤 8。再次修改 "../../../../CalciumTemplateApp.WindowsPhone/CommonResources/AppResources.resx" 以对应于您的 Windows Phone 项目中 .resx 文件的位置。保存模板将使其生成一个包含默认语言资源字符串的 XML 文件。将生成的 String.xml 文件的“生成操作”设置为“AndroidResource”。如果您未设置“生成操作”,则 Resource.Designer.cs 文件将不会填充强类型资源名称,您的项目将无法构建。
步骤 9。在 Resources 目录中创建与您的其他本地化 resx 文件对应的目录。例如,可下载的示例代码有一个本地化为法语的 resx 文件。因此,有一个 Values-fr 目录。对后续的本地化 resx 文件重复步骤 7、8 和 9。
请记住,当您修改字符串资源时,您需要右键单击每个 T4 模板并选择“运行自定义工具”。另外,在“构建”工具栏中有一个“转换所有 T4 模板”工具栏项。要显示“构建”工具栏,请右键单击工具栏区域并确保“构建”已选中。此外,还有一些自定义工具能够根据各种条件处理 T4 模板。有关更多信息,请查看 Visual Studio 扩展库。
您可以在http://danielvaughan.org/post/Generating-Localized-Resources-in-Mono-for-Android-Using-T4.aspx的另一篇文章中找到有关这项工作的更详细信息
在 Xamarin 项目中使用本地化字符串
在您的应用程序中使用代理类显示字符串资源的一个主要优点是,您可以立即更新 UI 以反映用户在应用程序中首选语言设置的更改。Windows Phone 版的 Calcium 可以很好地处理这个问题。您可以通过切换 Windows Phone 版 Surfy 中的语言设置来查看它的实际示例。UI 会立即更新,无需重启;瞧,它就在那里。这提供了无摩擦的用户体验,因为用户通常不理解“请重启应用程序以使更改生效”的含义。
虽然 Windows Phone 允许这种方法无缝地工作,但使用 Xamarin 当前的绑定基础设施很难实现。我尝试了许多方法,但都没有成功。如果没有能力明确设置绑定表达式的源属性,就无法定位可以引发属性更改事件的资源代理。
然而,好消息是 Xamarin Forms 支持 x:Static 标记表达式,这使得绑定到本地化资源变得容易。如果您熟悉 WPF,您就会知道它有多有用。这是 Silverlight for web、Windows Phone 和 WinRT 中一直明显缺失的功能。x:Static 标记表达式允许您检索静态属性的值,在本例中是我们生成的本地化资源字符串。
要在 Xamarin Forms XAML 中显示本地化字符串,请在文件顶部放置 XML 命名空间定义,如下所示
xmlns:local="clr-namespace:CalciumSampleApp;assembly=CalciumSampleApp"
“local”部分是您可以在文件中使用的别名。clr-namespace 和程序集名称标识将与别名关联的类型的位置。
以下摘录是如何使用 x:Static 标记表达式在 .resx 文件中使用 Label 元素显示本地化字符串的示例
<Label Text="{x:Static local:AppResources.AppTitle}" />
这比使用代理对象来显示字符串更简洁,事实上,随着 Xamarin 改进其围绕 XAML 的工具,如果找不到资源路径,我们可能会看到编译错误;就像 WPF 的情况一样。目前,Xamarin Forms 还没有这样的工具。但是,我抱有很大的希望。
结论
在本文中,您了解了如何使用相同的 .resx 文件在 Windows Phone、iOS 和 Android 这三个平台上本地化您的应用程序。您了解了如何将 .resx 文件正确链接到您的 Xamarin.iOS 项目中。您学习了如何配置提供的 T4 包含文件以生成 Android 友好的资源。最后,您了解了如何使用 x:Static 标记扩展从 XAML 中使用您的本地化资源。
在下一篇文章,第 4 部分:使用 Xamarin Forms 和 Calcium 创建跨平台应用程序栏中,您将学习如何使用 Xamarin Forms 本机渲染 API 创建一个跨平台应用程序栏组件,该组件支持菜单项,可在 iOS、Android 和 Windows Phone 上运行;并且比内置的 Windows Phone 应用程序栏提供更多功能
我希望您觉得这个项目有用。如果有用,我将不胜感激您能对其进行评分和/或在下方留下反馈。这将帮助我写出更好的下一篇文章。
历史
2014 年 10 月
- 首次发布。