概述
很多时候,软件都会被要求支持中英文,此时,就需要编程人员对软件进行多语种支持的开发。
解决方案有很多,这里主要介绍通过编辑xaml语言包来实现。
其功能有:
- 通过设定“ <Application.Resources>”的方式,实现控件动态加载语言
- 支持动态切换
- 支持自动加载上一次选定的语言
先来看效果
中英文切换效果
环境说明
当前样例,运行环境是:
- VS 2022
- .Net 6
- WPF
- C#
- Windows 11
原则上,windows开发平台均适用。
具体步骤
1. 编辑你的语言包
首选,你需要创建两个语言包,分别是中文、英文的xaml文件。
它们的文件【属性】,设置为如图:
2. 编辑语言包内容
我们通过定义key、value来编辑一个字典的xaml文件。
它们的每个“词条”,均为string类型。
以Chinese.xaml 为例,其内容基本如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DeviceToolsKit"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!--Common Text Dictionary-->
<sys:String x:Key="DicText_Common_Tips">提示说明:</sys:String>
<sys:String x:Key="DicText_Common_Error">错误警告:</sys:String>
<sys:String x:Key="DicText_Common_Notice">注意事项:</sys:String>
</ResourceDictionary>
以第一个词条文本举例
它的key名称是"DicText_Common_Tips",我们后面可以通过使用这个名称来调用它的具体文本值。
【提示说明:】这个是"DicText_Common_Tips"的具体文本。
请注意,下方的命名空间是必须添加的
xmlns:sys="clr-namespace:System;assembly=mscorlib"
下面附上对应的English.xaml文件
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DeviceToolsKit"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!--Common Text Dictionary-->
<sys:String x:Key="DicText_Common_Tips">Tips:</sys:String>
<sys:String x:Key="DicText_Common_Error">Error:</sys:String>
<sys:String x:Key="DicText_Common_Notice">Notice:</sys:String>
</ResourceDictionary>
通过对比,我们可以发现
- 中英文字典的Key值名称是一致的,唯一不同的是其对应的文本不同。
- 因此,这也就基本确定了后续的开发思路:
-
我们只需要加载需要的xaml文件,然后在需要的地方,使用唯一的keyName就可以了。
3. 修改App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Language packages-->
<ResourceDictionary Source="Resources\Languages\Chinese.xaml"/>
<ResourceDictionary Source="Resources\Languages\English.xaml"/>
</ResourceDictionary>
</Application.Resources>
在你的App.xaml文件中,增加上述语言包xaml文件。
此后,它将作为资源,并在程序启动的时候被加载进去。
需要注意的是
- 语言包的路径,这需要根据你自身项目来确定,我这里是把中英文的语言包放在了项目的Resources\Languages\文件夹下。
- 原则上,系统会自动采用最后一次加载的语言包,作为默认的语种显示。
- 因此,我们会在后面通过这个特性,来实现 “即时切换”、“默认加载上次选择的语言”这两个功能。
4. 使用语言包字典的Key
语言包的使用非常简单,只需要在你的UI xaml文件里面,对Text或者Content内容进行DynamicResource 的绑定即可。
<TextBlock Margin="10,0,0,0" Text="{DynamicResource DicText_Common_Tips}"/>
5. 实现动态切换语言
首先,在你项目中,添加一个语言的下拉列表,然后为其后面的按钮或者某个控件,绑定一个切换语言的函数方法。
这个步骤我就不多做赘述了,相信各位能够自己实现。
主要介绍一下动态切换的核心方法:
private void ChangeUILanguage(string targetLanguage)
{
List<ResourceDictionary> dictionaryList = new List<ResourceDictionary>();
foreach (ResourceDictionary dictionary in Application.Current.Resources.MergedDictionaries)
{
dictionaryList.Add(dictionary);
}
string requestedCulture = @"Resources\Languages\" + targetLanguage + ".xaml";
var resourceDictionary = dictionaryList.FirstOrDefault(d => d.Source.OriginalString.Equals(requestedCulture));
if (resourceDictionary != null)
{
Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
}
else
{
MessageBox.Show("Can not load the language resources.");
return;
}
}
前面提过:系统会默认使用最后一次加载的语言包,作为使用的对象。
因此,我们利用这个特性,通过以下步骤可以实现即时切换的目标:
- 获取当前App的所有ResourceDictionary资源
- 如果你现在想要使用English的xaml语言包,那么就先找到它。
- 然后再将其移除ResourceDictionary资源队列
- 最后重新将其添加
- 此时,系统便会使用“最新加载的资源”。
6. 自动加载上次选择的语言包
步骤1:添加App.config文件
向你的项目中,添加App.config文件
然后添加如下的字段:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Language" value="Chinese" />
</appSettings>
</configuration>
步骤2:重写OnStartup方法
展开App.xaml,编辑App.xaml.cs文件
添加并修改如下内容
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
List<ResourceDictionary> dictionaryList = new List<ResourceDictionary>();
foreach (ResourceDictionary dictionary in Application.Current.Resources.MergedDictionaries)
{
dictionaryList.Add(dictionary);
}
var targetLanguage = ConfigurationManager.AppSettings["Language"];
if (targetLanguage == null)
targetLanguage = "English";
string requestedCulture = @"Resources\Languages\" + targetLanguage + ".xaml";
var resourceDictionary = dictionaryList.FirstOrDefault(d => d.Source.OriginalString.Equals(requestedCulture));
if(resourceDictionary!=null)
{
Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
}
else
{
MessageBox.Show("Can not find the language resources.");
return;
}
}
}
这段代码中,我们会先行读取config的language值,然后将其作为目标,找到并重新加载对应的语言包。
步骤3:添加修改App.config 的方法
这个方法,你可以将它添加在需要的地方。
一般是把它放在选择语言的界面,也就是实现语言即时切换的地方。
private void UpdateAppConfigLanguageSetting(string valueStr)
{
Configuration _configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
_configuration.AppSettings.Settings["Language"].Value = valueStr;
_configuration.Save();
ConfigurationManager.RefreshSection("appSettings");
}
其中
ConfigurationManager.RefreshSection("appSettings");
这句刷新config section的方法是必须的。
总结
上述方法适用于中小型项目。
在大型项目中,建议使用其他资源消耗更少的方法来提升性能。