当前位置:   article > 正文

WPF本地化/国际化,多语言切换_wpf 多语言

wpf 多语言

之前写过winformwinform使用本地化,中英文切换_winform 中英文切换_故里2130的博客-CSDN博客

基本的技术差不多,但是后来又发现了一个ResXManager工具,可以更好方便快捷的使用。

首先下载,网络不好的话,去官网下载,然后安装,重启vs即可

wpf做多语言切换

有很多种,可以使用自带的资源去做,就是使用xaml写key值,这种做法是最简单方便的,也是wpf独特使用的,如果有大量的翻译,那么需要人工去翻译,需要转折一次,此种方法就不说了。下面说2种使用.resx资源和ResXManager工具来做。唯一的好处,就是自带翻译功能,方便快捷。

第一种

1.此处使用.net6创建wpf项目,与.net framework不一样,.net framework要简单一些

建立如图项目

2.打开ResXManager工具

3.点击新增语言,增加几个语种

增加后,双击增加的语种,就会自动生成对应的.resx文件,想要多少种语言,就可以增加多少种

最后要修改一下后缀名,否则报错。

4. 点击翻译

此处,可以导出Excel,让别人翻译,然后再导入,也可以使用在线翻译的功能,点击翻译。

  

5.效果

6. 创建LanguageManager.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Globalization;
  5. using System.Resources;
  6. using System.Text;
  7. namespace WpfApp1.Resources
  8. {
  9. public class LanguageManager : INotifyPropertyChanged
  10. {
  11. /// <summary>
  12. /// 资源
  13. /// </summary>
  14. private readonly ResourceManager _resourceManager;
  15. /// <summary>
  16. /// 懒加载
  17. /// </summary>
  18. private static readonly Lazy<LanguageManager> _lazy = new Lazy<LanguageManager>(() => new LanguageManager());
  19. public static LanguageManager Instance => _lazy.Value;
  20. public event PropertyChangedEventHandler PropertyChanged;
  21. public LanguageManager()
  22. {
  23. //获取此命名空间下Resources的Lang的资源,Lang可以修改
  24. _resourceManager = new ResourceManager("WpfApp1.Resources.Lang", typeof(LanguageManager).Assembly);
  25. }
  26. /// <summary>
  27. /// 索引器的写法,传入字符串的下标
  28. /// </summary>
  29. /// <param name="name"></param>
  30. /// <returns></returns>
  31. /// <exception cref="ArgumentNullException"></exception>
  32. public string this[string name]
  33. {
  34. get
  35. {
  36. if (name == null)
  37. {
  38. throw new ArgumentNullException(nameof(name));
  39. }
  40. return _resourceManager.GetString(name);
  41. }
  42. }
  43. public void ChangeLanguage(CultureInfo cultureInfo)
  44. {
  45. CultureInfo.CurrentCulture = cultureInfo;
  46. CultureInfo.CurrentUICulture = cultureInfo;
  47. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("item[]")); //字符串集合,对应资源的值
  48. }
  49. }
  50. }

7.xaml界面

  1. <Window x:Class="WpfApp1.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:WpfApp1.Resources"
  7. mc:Ignorable="d"
  8. xmlns:res="clr-namespace:System.Windows.Resources;assembly=PresentationFramework"
  9. Title="MainWindow" Height="450" Width="800">
  10. <StackPanel HorizontalAlignment="Center">
  11. <ComboBox x:Name="LanguageList" SelectedIndex="0" Margin="10" SelectionChanged="LanguageList_SelectionChanged"/>
  12. <!--这里绑定字符串的值,Source来源于语言的集合,Mode是响应的方式,有些需要,有些不需要-->
  13. <TextBlock FontSize="20" Margin="10" Text="{Binding [String1], Source={x:Static local:LanguageManager.Instance}}"/>
  14. <TextBox FontSize="20" Margin="10" Text="{Binding [String2], Source={x:Static local:LanguageManager.Instance}, Mode=OneWay}"/>
  15. <Button FontSize="20" Margin="10" Content="{Binding [String3], Source={x:Static local:LanguageManager.Instance}}"/>
  16. </StackPanel>
  17. </Window>

8.后台

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Data;
  10. using System.Windows.Documents;
  11. using System.Windows.Input;
  12. using System.Windows.Media;
  13. using System.Windows.Media.Imaging;
  14. using System.Windows.Navigation;
  15. using System.Windows.Shapes;
  16. using WpfApp1.Resources;
  17. namespace WpfApp1
  18. {
  19. /// <summary>
  20. /// Interaction logic for MainWindow.xaml
  21. /// </summary>
  22. public partial class MainWindow : Window
  23. {
  24. public MainWindow()
  25. {
  26. InitializeComponent();
  27. LanguageList.ItemsSource = new List<string>
  28. {
  29. "en-Us",
  30. "zh-CN",
  31. "ar"
  32. };
  33. //this.DataContext = new Lazy<LanguageManager>(() => new LanguageManager()).Value;
  34. }
  35. /// <summary>
  36. /// 下拉框赋值语言的类型
  37. /// </summary>
  38. /// <param name="sender"></param>
  39. /// <param name="e"></param>
  40. private void LanguageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
  41. {
  42. LanguageManager.Instance.ChangeLanguage(new CultureInfo((sender as ComboBox).SelectedItem.ToString()));
  43. }
  44. }
  45. }

此处使用mvvm的话,可以直接绑定,1对1绑定语言 

9.效果

第二种

1.首先创建一个程序

2.在Resources文件夹中,创建文件

3.GlobalClass.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using System.Windows;
  11. namespace WpfApp2.Resources
  12. {
  13. /// <summary>
  14. /// 全局类
  15. /// </summary>
  16. public static class GlobalClass
  17. {
  18. static bool? inDesignMode = null;
  19. /// <summary>
  20. /// 判断是设计器还是程序运行
  21. /// </summary>
  22. public static bool InDesignMode
  23. {
  24. get
  25. {
  26. if (inDesignMode == null)
  27. {
  28. #if SILVERLIGHT
  29. inDesignMode = DesignerProperties.IsInDesignTool;
  30. #else
  31. var prop = DesignerProperties.IsInDesignModeProperty;
  32. inDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue;
  33. if (!inDesignMode.GetValueOrDefault(false) && Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
  34. inDesignMode = true;
  35. #endif
  36. }
  37. return inDesignMode.GetValueOrDefault(false);
  38. }
  39. }
  40. /// <summary>
  41. /// 语言改变通知事件
  42. /// </summary>
  43. public static EventHandler<EventArgs> LanguageChangeEvent;
  44. static Resource StringResource;
  45. static GlobalClass()
  46. {
  47. StringResource = new Resource();
  48. }
  49. /// <summary>
  50. /// 获取资源内容
  51. /// </summary>
  52. /// <param name="key"></param>
  53. /// <returns></returns>
  54. public static string GetString(string key)
  55. {
  56. return StringResource.GetString(key);
  57. }
  58. /// <summary>
  59. /// 改变语言
  60. /// </summary>
  61. /// <param name="language">CultureInfo列表(http://www.csharpwin.com/csharpspace/8948r7277.shtml)</param>
  62. public static void ChangeLanguage(string language)
  63. {
  64. CultureInfo culture = new CultureInfo(language);
  65. Thread.CurrentThread.CurrentCulture = culture;
  66. Thread.CurrentThread.CurrentUICulture = culture;
  67. StringResource.CurrentCulture = culture;
  68. if (LanguageChangeEvent != null)
  69. {
  70. LanguageChangeEvent(null, null);
  71. }
  72. }
  73. }
  74. }

4.Resource.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Resources;
  8. namespace WpfApp2.Resources
  9. {
  10. public interface IResource
  11. {
  12. string GetString(string name);
  13. CultureInfo CurrentCulture { set; }
  14. }
  15. public class Resource : IResource
  16. {
  17. private ResourceManager stringResource;
  18. //我们这样设置的时候ResourceManager会去查找MultilanguageTest.StringResource.en-us.resx,如果没有会查找MultilanguageTest.StringResource.resx
  19. private CultureInfo culture = new CultureInfo("zh-cn"); //默认值
  20. public Resource()
  21. {
  22. //MultilanguageTest.StringResource是根名称,该实例使用指定的System.Reflection.Assmbly查找从指定的跟名称导出的文件中包含的资源
  23. //此处注意WpfApp2.Resources.Lang,Lang是资源文件的名字
  24. stringResource = new ResourceManager("WpfApp2.Resources.Lang", typeof(Resource).Assembly);
  25. }
  26. /// <summary>
  27. /// 通过资源名称获取资源内容
  28. /// </summary>
  29. /// <param name="name"></param>
  30. /// <returns></returns>
  31. public string GetString(string name)
  32. {
  33. return stringResource.GetString(name, culture);
  34. }
  35. /// <summary>
  36. /// 改变当前的区域信息,ResourceManager可以通过当前区域信息去查找.resx文件
  37. /// </summary>
  38. public CultureInfo CurrentCulture
  39. {
  40. set
  41. {
  42. culture = value;
  43. }
  44. }
  45. }
  46. }

5.StringResourceExtension.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Windows;
  8. using System.Windows.Data;
  9. using System.Windows.Markup;
  10. namespace WpfApp2.Resources
  11. {
  12. [MarkupExtensionReturnType(typeof(BindingExpression))]
  13. public class StringResourceExtension : MarkupExtension, INotifyPropertyChanged
  14. {
  15. /// <summary>
  16. /// 资源的名称,与资源文件StringResource.resx对应
  17. /// </summary>
  18. [ConstructorArgument("key")]
  19. public string Key
  20. {
  21. get;
  22. set;
  23. }
  24. string _DefaultValue;
  25. /// <summary>
  26. /// 默认值,为了使在设计器的情况时把默认值绑到设计器
  27. /// </summary>
  28. public string DefaultValue
  29. {
  30. get
  31. {
  32. return _DefaultValue;
  33. }
  34. set
  35. {
  36. _DefaultValue = value;
  37. }
  38. }
  39. string _Value;
  40. /// <summary>
  41. /// 资源的具体内容,通过资源名称也就是上面的Key找到对应内容
  42. /// </summary>
  43. public string Value
  44. {
  45. get
  46. {
  47. ///如果为设计器模式,本地的资源没有实例化,我们不能从资源文件得到内容,所以从KEY或默认值绑定到设计器去
  48. if (GlobalClass.InDesignMode)
  49. {
  50. if (Key != null && DefaultValue != null)
  51. return DefaultValue;
  52. if (Key == null && DefaultValue != null)
  53. return DefaultValue;
  54. if (Key != null && DefaultValue == null)
  55. return Key;
  56. if (Key == null && DefaultValue == null)
  57. return "NULL";
  58. }
  59. else
  60. {
  61. if (Key != null)
  62. {
  63. string strResault = null;
  64. try
  65. {
  66. strResault = GlobalClass.GetString(Key);
  67. }
  68. catch
  69. {
  70. }
  71. if (strResault == null)
  72. {
  73. strResault = _DefaultValue;
  74. }
  75. return strResault;
  76. }
  77. }
  78. return _Value;
  79. }
  80. set
  81. {
  82. _Value = value;
  83. }
  84. }
  85. public StringResourceExtension(string key)
  86. : this()
  87. {
  88. Key = key;
  89. GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event);
  90. }
  91. public StringResourceExtension(string key, string DefaultValue)
  92. : this()
  93. {
  94. Key = key;
  95. _DefaultValue = DefaultValue;
  96. GlobalClass.LanguageChangeEvent += new EventHandler<EventArgs>(Language_Event);
  97. }
  98. public StringResourceExtension()
  99. {
  100. }
  101. /// <summary>
  102. /// 每一标记扩展实现的 ProvideValue 方法能在可提供上下文的运行时使用 IServiceProvider。然后会查询此 IServiceProvider 以获取传递信息的特定服务
  103. ///当 XAML 处理器在处理一个类型节点和成员值,且该成员值是标记扩展时,它将调用该标记扩展的 ProvideValue 方法并将结果写入到对象关系图或序列化流,XAML 对象编写器将服务环境通过 serviceProvider 参数传递到每个此类实现。
  104. /// </summary>
  105. /// <param name="serviceProvider"></param>
  106. /// <returns></returns>
  107. public override object ProvideValue(IServiceProvider serviceProvider)
  108. {
  109. IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
  110. Setter setter = target.TargetObject as Setter;
  111. if (setter != null)
  112. {
  113. return new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
  114. }
  115. else
  116. {
  117. Binding binding = new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
  118. return binding.ProvideValue(serviceProvider);
  119. }
  120. }
  121. public event PropertyChangedEventHandler PropertyChanged;
  122. static readonly System.ComponentModel.PropertyChangedEventArgs
  123. valueChangedEventArgs = new System.ComponentModel.PropertyChangedEventArgs("Value");
  124. protected void NotifyValueChanged()
  125. {
  126. if (PropertyChanged != null)
  127. PropertyChanged(this, valueChangedEventArgs);
  128. }
  129. /// <summary>
  130. /// 语言改变通知事件,当程序初始化的时候会绑定到全局的GlobalClass.LanguageChangeEvent事件
  131. /// </summary>
  132. /// <param name="sender"></param>
  133. /// <param name="e"></param>
  134. private void Language_Event(object sender, EventArgs e)
  135. {
  136. //通知Value值已经改变,需重新获取
  137. NotifyValueChanged();
  138. }
  139. }
  140. }

6.创建3个语言的文件

使用ResXManager工具进行翻译,参考上面的细节

7.效果

2种方式都可以,第一种要简单一点。 

源码:

https://download.csdn.net/download/u012563853/87944124

来源:WPF本地化/国际化,多语言切换_wpf 国际化_故里2130的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/863546?site
推荐阅读
相关标签
  

闽ICP备14008679号