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

打印 上一主题 下一主题

主题 571|帖子 571|积分 1713

之前写过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.       
  10.         Title="MainWindow" Height="450" Width="800">
  11.     <StackPanel HorizontalAlignment="Center">
  12.         <ComboBox x:Name="LanguageList" SelectedIndex="0" Margin="10" SelectionChanged="LanguageList_SelectionChanged"/>
  13.         <!--这里绑定字符串的值,Source来源于语言的集合,Mode是响应的方式,有些需要,有些不需要-->
  14.         <TextBlock FontSize="20" Margin="10" Text="{Binding [String1], Source={x:Static local:LanguageManager.Instance}}"/>
  15.         <TextBox FontSize="20" Margin="10"   Text="{Binding [String2], Source={x:Static local:LanguageManager.Instance}, Mode=OneWay}"/>
  16.         <Button FontSize="20" Margin="10" Content="{Binding [String3], Source={x:Static local:LanguageManager.Instance}}"/>
  17.     </StackPanel>
  18. </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博客

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表