之前写过winformwinform使用本地化,中英文切换_winform 中英文切换_故里2130的博客-CSDN博客
基本的技术差不多,但是后来又发现了一个ResXManager工具,可以更好方便快捷的使用。
首先下载,网络不好的话,去官网下载,然后安装,重启vs即可
wpf做多语言切换
有很多种,可以使用自带的资源去做,就是使用xaml写key值,这种做法是最简单方便的,也是wpf独特使用的,如果有大量的翻译,那么需要人工去翻译,需要转折一次,此种方法就不说了。下面说2种使用.resx资源和ResXManager工具来做。唯一的好处,就是自带翻译功能,方便快捷。
第一种
1.此处使用.net6创建wpf项目,与.net framework不一样,.net framework要简单一些
建立如图项目
2.打开ResXManager工具
3.点击新增语言,增加几个语种
增加后,双击增加的语种,就会自动生成对应的.resx文件,想要多少种语言,就可以增加多少种
最后要修改一下后缀名,否则报错。
- 点击翻译
此处,可以导出Excel,让别人翻译,然后再导入,也可以使用在线翻译的功能,点击翻译。
5.效果
- 创建LanguageManager.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Resources;
using System.Text;
namespace WpfApp1.Resources
{
public class LanguageManager : INotifyPropertyChanged
{
/// <summary>
/// 资源
/// </summary>
private readonly ResourceManager _resourceManager;
/// <summary>
/// 懒加载
/// </summary>
private static readonly Lazy<LanguageManager> _lazy = new Lazy<LanguageManager>(() => new LanguageManager());
public static LanguageManager Instance => _lazy.Value;
public event PropertyChangedEventHandler PropertyChanged;
public LanguageManager()
{
//获取此命名空间下Resources的Lang的资源,Lang可以修改
_resourceManager = new ResourceManager("WpfApp1.Resources.Lang", typeof(LanguageManager).Assembly);
}
/// <summary>
/// 索引器的写法,传入字符串的下标
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public string this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
return _resourceManager.GetString(name);
}
}
public void ChangeLanguage(CultureInfo cultureInfo)
{
CultureInfo.CurrentCulture = cultureInfo;
CultureInfo.CurrentUICulture = cultureInfo;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("item[]")); //字符串集合,对应资源的值
}
}
}
7.xaml界面
<Window x:Class="WpfApp1.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:WpfApp1.Resources"
mc:Ignorable="d"
xmlns:res="clr-namespace:System.Windows.Resources;assembly=PresentationFramework"
Title="MainWindow" Height="450" Width="800">
<StackPanel HorizontalAlignment="Center">
<ComboBox x:Name="LanguageList" SelectedIndex="0" Margin="10" SelectionChanged="LanguageList_SelectionChanged"/>
<!--这里绑定字符串的值,Source来源于语言的集合,Mode是响应的方式,有些需要,有些不需要-->
<TextBlock FontSize="20" Margin="10" Text="{Binding [String1], Source={x:Static local:LanguageManager.Instance}}"/>
<TextBox FontSize="20" Margin="10" Text="{Binding [String2], Source={x:Static local:LanguageManager.Instance}, Mode=OneWay}"/>
<Button FontSize="20" Margin="10" Content="{Binding [String3], Source={x:Static local:LanguageManager.Instance}}"/>
</StackPanel>
</Window>
8.后台
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp1.Resources;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LanguageList.ItemsSource = new List<string>
{
"en-Us",
"zh-CN",
"ar"
};
//this.DataContext = new Lazy<LanguageManager>(() => new LanguageManager()).Value;
}
/// <summary>
/// 下拉框赋值语言的类型
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LanguageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LanguageManager.Instance.ChangeLanguage(new CultureInfo((sender as ComboBox).SelectedItem.ToString()));
}
}
}
**此处使用mvvm的话,可以直接绑定,1对1绑定语言 **
9.效果
第二种
1.首先创建一个程序
2.在Resources文件夹中,创建文件
3.GlobalClass.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp2.Resources
{
/// <summary>
/// 全局类
/// </summary>
public static class GlobalClass
{
static bool? inDesignMode = null;
/// <summary>
/// 判断是设计器还是程序运行
/// </summary>
public static bool InDesignMode
{
get
{
if (inDesignMode == null)
{
#if SILVERLIGHT
inDesignMode = DesignerProperties.IsInDesignTool;
#else
var prop = DesignerProperties.IsInDesignModeProperty;
inDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue;
if (!inDesignMode.GetValueOrDefault(false) && Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
inDesignMode = true;
#endif
}
return inDesignMode.GetValueOrDefault(false);
}
}
/// <summary>
/// 语言改变通知事件
/// </summary>
public static EventHandler<EventArgs> LanguageChangeEvent;
static Resource StringResource;
static GlobalClass()
{
StringResource = new Resource();
}
/// <summary>
/// 获取资源内容
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetString(string key)
{
return StringResource.GetString(key);
}
/// <summary>
/// 改变语言
/// </summary>
/// <param name="language">CultureInfo列表(http://www.csharpwin.com/csharpspace/8948r7277.shtml)</param>
public static void ChangeLanguage(string language)
{
CultureInfo culture = new CultureInfo(language);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
StringResource.CurrentCulture = culture;
if (LanguageChangeEvent != null)
{
LanguageChangeEvent(null, null);
}
}
}
}
4.Resource.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Resources;
namespace WpfApp2.Resources
{
public interface IResource
{
string GetString(string name);
CultureInfo CurrentCulture { set; }
}
public class Resource : IResource
{
private ResourceManager stringResource;
//我们这样设置的时候ResourceManager会去查找MultilanguageTest.StringResource.en-us.resx,如果没有会查找MultilanguageTest.StringResource.resx
private CultureInfo culture = new CultureInfo("zh-cn"); //默认值
public Resource()
{
//MultilanguageTest.StringResource是根名称,该实例使用指定的System.Reflection.Assmbly查找从指定的跟名称导出的文件中包含的资源
//此处注意WpfApp2.Resources.Lang,Lang是资源文件的名字
stringResource = new ResourceManager("WpfApp2.Resources.Lang", typeof(Resource).Assembly);
}
/// <summary>
/// 通过资源名称获取资源内容
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string GetString(string name)
{
return stringResource.GetString(name, culture);
}
/// <summary>
/// 改变当前的区域信息,ResourceManager可以通过当前区域信息去查找.resx文件
/// </summary>
public CultureInfo CurrentCulture
{
set
{
culture = value;
}
}
}
}
5.StringResourceExtension.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace WpfApp2.Resources
{
[MarkupExtensionReturnType(typeof(BindingExpression))]
public class StringResourceExtension : MarkupExtension, INotifyPropertyChanged
{
/// <summary>
/// 资源的名称,与资源文件StringResource.resx对应
/// </summary>
[ConstructorArgument("key")]
public string Key
{
get;
set;
}
string _DefaultValue;
/// <summary>
/// 默认值,为了使在设计器的情况时把默认值绑到设计器
/// </summary>
public string DefaultValue
{
get
{
return _DefaultValue;
}
set
{
_DefaultValue = value;
}
}
string _Value;
/// <summary>
/// 资源的具体内容,通过资源名称也就是上面的Key找到对应内容
/// </summary>
public string Value
{
get
{
///如果为设计器模式,本地的资源没有实例化,我们不能从资源文件得到内容,所以从KEY或默认值绑定到设计器去
if (GlobalClass.InDesignMode)
{
if (Key != null && DefaultValue != null)
return DefaultValue;
if (Key == null && DefaultValue != null)
return DefaultValue;
if (Key != null && DefaultValue == null)
return Key;
if (Key == null && DefaultValue == null)
return "NULL";
}
else
{
if (Key != null)
{
string strResault = null;
try
{
strResault = GlobalClass.GetString(Key);
}
catch
{
}
if (strResault == null)
{
strResault = _DefaultValue;
}
return strResault;
}
}
return _Value;
}
set
{
_Value = value;
}
}
public StringResourceExtension(string key)
: this()
{
Key = key;
GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event);
}
public StringResourceExtension(string key, string DefaultValue)
: this()
{
Key = key;
_DefaultValue = DefaultValue;
GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event);
}
public StringResourceExtension()
{
}
/// <summary>
/// 每一标记扩展实现的 ProvideValue 方法能在可提供上下文的运行时使用 IServiceProvider。然后会查询此 IServiceProvider 以获取传递信息的特定服务
///当 XAML 处理器在处理一个类型节点和成员值,且该成员值是标记扩展时,它将调用该标记扩展的 ProvideValue 方法并将结果写入到对象关系图或序列化流,XAML 对象编写器将服务环境通过 serviceProvider 参数传递到每个此类实现。
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
Setter setter = target.TargetObject as Setter;
if (setter != null)
{
return new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
}
else
{
Binding binding = new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
return binding.ProvideValue(serviceProvider);
}
}
public event PropertyChangedEventHandler PropertyChanged;
static readonly System.ComponentModel.PropertyChangedEventArgs
valueChangedEventArgs = new System.ComponentModel.PropertyChangedEventArgs("Value");
protected void NotifyValueChanged()
{
if (PropertyChanged != null)
PropertyChanged(this, valueChangedEventArgs);
}
/// <summary>
/// 语言改变通知事件,当程序初始化的时候会绑定到全局的GlobalClass.LanguageChangeEvent事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Language_Event(object sender, EventArgs e)
{
//通知Value值已经改变,需重新获取
NotifyValueChanged();
}
}
}
6.创建3个语言的文件
使用ResXManager工具进行翻译,参考上面的细节
7.效果
2种方式都可以,第一种要简单一点。
源码:
https://download.csdn.net/download/u012563853/87944124
来源:WPF本地化/国际化,多语言切换_wpf 国际化_故里2130的博客-CSDN博客
版权归原作者 故里2130 所有, 如有侵权,请联系我们删除。