WPF的本地化或者说对多国语言的支持,微软官方给出的方案是借助Uid加上WPF Samples中的小工具locBaml来实现。这种方案的一个缺点就是界面语言的切换需要重新打开Window甚至重启程序。文章最后编辑日期是在2017年,都2021年了,WPF竟然还没有给出一个优雅的方式来支持on-the-fly的界面语言切换。说WPF已死还太早,但WPF的开发生命应该已经到头了。
寻找WPF的相关文章,仿佛是在考古。解决方案也有一些,但最终在CodeProject上找到一篇Andrew Wood的文章。里边介绍的解决方案是通过resource(也就是 *.resx文件)+ ObjectDataProvider的方式来实现on-the-fly localization。通过resx文件来实现多语言支持,早在WinForm上就应用过。并且有Visual Studio插件ResXManager的支持,十分便利。ObjectDataProvider,简单来说,就是让你可以在XAML中创建自定义的对象,并且使其能够作为binding source。我们需要通过它来绑定我们多国语言资源,是这些资源能够在通过单击按钮类似操作下,切换界面语言。
原文及其代码有点令人抓不住重点,我重新提炼下,并且采用Visual Studio 2019的样式重新实现了一个自己的版本。下面逐一介绍下实现的步骤。创建WPF project以及使用ResXManager插件产生多国语言resource就省略了。总之,我们有了两个语言资源文件,一个默认英语,一个简体中文(zh-CN)。
创建一个类名为CultureResources,用来封装ObjectDataProvider对象,并且后面会绑定到XAML资源文件里。
CultureResources.cs
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WPF_Localization_on_the_fly
{
public class CultureResources
{
private static ObjectDataProvider _provider;
public static ObjectDataProvider ResourceProvider
{
get {
return _provider ??
(_provider = ObjectDataProvider)Application.Current.FindResource("CultureRes"));
// 注意"CultureRes"必须和后面加到Application resources中的ObjectDataProvider的key名一致。
}
}
public static void ChangeCulture(CultureInfo culture)
{
Properties.Resources.Culture = culture;
ResourceProvider.Refresh(); // <- refresh the localization content with the new culture
}
public Properties.Resources GetResourceInstance()
{
return new Properties.Resources(); // Properties.Resources对象里包含着多语言字符串资源
}
}
}
在Application的resources中加入CultureResources对象。
<Application x:Class="WPF_Localization_on_the_fly.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF_Localization_on_the_fly"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ObjectDataProvider x:Key="CultureRes" ObjectType="{x:Type local:CultureResources}" MethodName="GetResourceInstance"></ObjectDataProvider>
</Application.Resources>
</Application>
在MainWindow.xaml中绑定CultureRes
<Window x:Class="WPF_Localization_on_the_fly.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Localization_on_the_fly"
mc:Ignorable="d"
Title="{Binding Path=Title, Source={StaticResource CultureRes}}" Height="450" Width="800">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Path=Hello, Source={StaticResource CultureRes}}" FontSize="48"></TextBlock>
<Button Content="{Binding Path=Switch, Source={StaticResource CultureRes}}" FontSize="24" Height="50" Width="100" Name="SwitchButton" Click="SwitchButton_OnClick"></Button>
</StackPanel>
</Grid>
</Window>
Build & F5
单击按钮,界面上的语言会在中英文之间切换。
Source Code: github
(end)