络腮胡菲菲 发表于 2024-8-15 23:06:35

WPF-实现多语言的静态(需重启)与动态切换(不消重启)

目次
一、多语言切换(需重启)
1、配置文件添加Key
2、新增附加属性当前选择语言
3、创建资源文件
 4、初始化多语言聚集
5、切换多语言并更新配置文件
6、应用程序启动根据配置切换多语言
 7、使用
二、多语言切换(无需重启)
1、创建多语言标志扩展基类
2、添加资源转换器
3、创建资源文件
4、继续基类创建指定资源文件扩展
5、添加资源文件管理
6、切换语言
7、使用
8、后台使用多语言
①获取多语言资源字符串
②后台绑定


一、多语言切换(需重启)

1、配置文件添加Key

        <appSettings>
                <add key="language" value="zh-CN"/>
        </appSettings> 2、新增附加属性当前选择语言

      public CultureInfo SelectLanguage
      {
            get => (CultureInfo)GetValue(SelectLanguageProperty);
            set => SetValue(SelectLanguageProperty, value);
      }

      public static readonly DependencyProperty SelectLanguageProperty =
            DependencyProperty.Register("SelectLanguage", typeof(CultureInfo), typeof(MainWindow)); 3、创建资源文件

https://i-blog.csdnimg.cn/direct/a0cba8ca73834866b73a6722d7614a7b.png
 4、初始化多语言聚集

      public ObservableCollection<CultureInfo> CultureInfos { get; private set; } = new ObservableCollection<CultureInfo>();

      private void Window_Loaded(object sender, RoutedEventArgs e)
      {
            var dir =Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var curs = CultureInfo.GetCultures(CultureTypes.AllCultures);
            foreach (CultureInfo cur in curs)
            {
                if (string.IsNullOrWhiteSpace(cur.Name)) continue;
                string landir = Path.Combine(dir, cur.Name);
                if (Directory.Exists(landir)) CultureInfos.Add(cur);
            }
            if (CultureInfos.Any(cur => cur.Name.Equals("zh-CN", StringComparison.OrdinalIgnoreCase)) is false)
            {
                var cur = curs.FirstOrDefault(c => c.Name.Equals("zh-CN", StringComparison.OrdinalIgnoreCase));
                if (cur != null) CultureInfos.Add(cur);
            }
            SelectLanguage = Thread.CurrentThread.CurrentCulture;
      } 5、切换多语言并更新配置文件

      protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
      {
            base.OnPropertyChanged(e);
            if (e.Property == SelectLanguageProperty)
            {
                if (SelectLanguage == Thread.CurrentThread.CurrentCulture) return;
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                if (ConfigurationManager.AppSettings["language"] is null)
                  config.AppSettings.Settings.Add("language", SelectLanguage.Name);
                else
                  config.AppSettings.Settings["language"].Value = SelectLanguage.Name;
                config.Save();
                ConfigurationManager.RefreshSection("appSettings");
            }
      } 6、应用程序启动根据配置切换多语言

   /// <summary>
   /// App.xaml 的交互逻辑
   /// </summary>
   public partial class App : Application
   {
       protected override void OnStartup(StartupEventArgs e)
       {
         base.OnStartup(e);
          var lan= ConfigurationManager.AppSettings["language"];
         if (!string.IsNullOrWhiteSpace(lan))
         {
               CultureInfo culture = new CultureInfo(lan);
               Thread.CurrentThread.CurrentCulture = culture;
               Thread.CurrentThread.CurrentUICulture = culture;
         }
       }
   }  7、使用

①映射定名空间
xmlns:rs="clr-namespace:WpfApp8.Resources" ②示例
    <Grid>
      <GroupBox x:Name="gbox">
            <Grid>
                <Button Width="100"
                Height="80"
                Background="LightGray"
                Content="{x:Static rs:SRS.TestLan}" />
                <ComboBox Width="150"
                  Height="50"
                  HorizontalAlignment="Left"
                  VerticalContentAlignment="Center"
                  DisplayMemberPath="NativeName"
                  ItemsSource="{Binding Path=CultureInfos, ElementName=MW}"
                  SelectedItem="{Binding Path=SelectLanguage, ElementName=MW}" />
            </Grid>
      </GroupBox>
    </Grid>
二、多语言切换(无需重启)

安装Nuget包:WpfExtensions.Xaml
1、创建多语言标志扩展基类

    /// <summary>
    /// 多语言绑定扩展基类
    /// </summary>
    /// <typeparam name="T">多语言文件资源类</typeparam>
   
    public class LanguageExtensionBase<T> : MarkupExtension where T : class
    {
      private static readonly ResourceConverter ResourceConverter = new ResourceConverter();
      
      public ComponentResourceKey Key { get; set; }

      public LanguageExtensionBase(string key)
      {
            Key = new ComponentResourceKey(typeof(T), key);
      }
      public override object ProvideValue(IServiceProvider serviceProvider)
      {
            if (Key == null)
            {
                throw new NullReferenceException("Key cannot be null at the same time.");
            }

            IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
            if (provideValueTarget == null)
            {
                throw new ArgumentException("The serviceProvider must implement IProvideValueTarget interface.");
            }

            if (provideValueTarget.TargetObject?.GetType().FullName == "System.Windows.SharedDp")
            {
                return this;
            }

            return new Binding("Value")
            {
                Source = new I18nSource(Key, provideValueTarget.TargetObject),
                Mode = BindingMode.OneWay,
                Converter = ResourceConverter
            }.ProvideValue(serviceProvider);
      }
    } 2、添加资源转换器

    /// <summary>
    /// 资源转换器
    /// </summary>
    public class ResourceConverter : IValueConverter
    {
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {
            Bitmap val = (Bitmap)((value is Bitmap) ? value : null);
            if (val == null)
            {
                Icon val2 = (Icon)((value is Icon) ? value : null);
                if (val2 != null)
                {
                  return ToBitmapSource(val2.ToBitmap());
                }
                return value;
            }
            return ToBitmapSource(val);
      }

      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {
            throw new NotSupportedException();
      }

      
      private static extern int DeleteObject(IntPtr o);
      public ImageSource ToBitmapSource(Bitmap bitmap)
      {
            IntPtr ptr = bitmap.GetHbitmap(); //obtain the Hbitmap
            BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            DeleteObject(ptr); //release the HBitmap
            return bitmapSource;
      }
    } 3、创建资源文件

https://i-blog.csdnimg.cn/direct/d02ad313a2574c29af61aa4410446d18.png
4、继续基类创建指定资源文件扩展

    /// <summary>
    /// 多语言绑定扩展
    /// </summary>
   
    internal class LanguageExtension : LanguageExtensionBase<DefaultLanguage>
    {
      public LanguageExtension(string key) : base(key)
      {
      }
    } 5、添加资源文件管理

try
{
    I18nManager.Instance.Add(Resource.ResourceManager);
}
catch (ArgumentException)
{
} 6、切换语言

var culture = new CultureInfo("en-US");
I18nManager.Instance.CurrentUICulture = culture;
System.Threading.Thread.CurrentThread.CurrentCulture = culture; 7、使用

①映射定名空间到XAML
xmlns:Lan="clr-namespace:SqlSugarTest.Lan"  ②资源文件中添加多语言资源
https://i-blog.csdnimg.cn/direct/06bba869efb44f72b64981f3660afa51.png
③示例
                  <GroupBox Header="多语言测试">
                        <Menu Height="NaN" HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Background="{x:Null}"
                        FontSize="12" FontWeight="Bold">
                            <MenuItem Margin="3" Padding="10,8"
                                  HorizontalAlignment="Center"
                                  HorizontalContentAlignment="Center"
                                  Header="{Lan:Language MultiLanguage}">
                              <MenuItem Margin="3" Padding="10,5"
                                    Click="MenuItem_Click_CN" Header="CN-中" />
                              <MenuItem Margin="3" Padding="10,5"
                                    Click="Button_Click_EN" Header="US-英" />
                              <MenuItem Margin="3" Padding="10,5"
                                    Header="Test">
                                    <MenuItem Margin="3" Padding="10,5"
                                          Header="111" />
                                    <MenuItem Margin="3" Padding="10,5"
                                          Header="222" />
                              </MenuItem>
                            </MenuItem>
                        </Menu>
                  </GroupBox> 8、后台使用多语言

①获取多语言资源字符串

      /// <summary>
      /// 获取Key资源
      /// </summary>
      /// <param name="key"></param>
      /// <param name="resource"></param>
      /// <returns></returns>
      public static string GetString(string key, ResourceManager resource = null)
      {
            if (resource == null)
                return DefaultLanguage.ResourceManager.GetString(key, I18nManager.Instance.CurrentUICulture);
            else
                return resource.GetString(key, I18nManager.Instance.CurrentUICulture);
      } MessageBox.Show(GetString(nameof(DefaultLanguage.Test)));
②后台绑定

      static readonly ResourceConverter converter = new ResourceConverter();

      /// <summary>
      /// 按自定义数据绑定多语言
      /// </summary>
      /// <typeparam name="T">自定义数据源</typeparam>
      /// <param name="key">数据关键字</param>
      /// <returns></returns>
      public static BindingBase GetBinding<T>(string key, object element = null)
      {
            var Key = new ComponentResourceKey(typeof(T), key);
            return new Binding("Value")
            {
                Source = new I18nSource(Key, element),
                Mode = BindingMode.OneWay,
                Converter = converter
            };
      } menu_Test.SetBinding(MenuItem.HeaderProperty, GetBinding<DefaultLanguage>(nameof(DefaultLanguage.Test)));

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: WPF-实现多语言的静态(需重启)与动态切换(不消重启)