赞
踩
最近把 DbTool 从 WinForm 迁移到了 WPF,并更新到了 dotnet core 3.1,并实现了基于 Microsoft.Extensions.Localization
实现了基本的多语言支持。下面来分享一下如何来实现
如果不熟悉如何在 WPF 中使用依赖注入,可以参考上一篇文章 dotnetcore3.1 WPF 中使用依赖注入
在应用启动前注册 Localization 服务,我这里使用的是自己自定义的基于 JSON 的多语言服务
services.AddJsonLocalization(options => options.ResourcesPathType = ResourcesPathType.CultureBased);
服务注册的最后使用了一个 ServiceLocator 模式的代码(DependencyResolver),保存了所有的注册服务,后面的 Localizer 扩展会用到
DependencyResolver.SetDependencyResolver(services);
代码文件(如:MainWindow.xaml.cs) 中实现多语言较为简单,直接注入 IStringLocalizer
即可,获取对应的要实例化的,比如:
- public partial class MainWindow: Window
- {
- private readonly IStringLocalizer<MainWindow> _localizer;
- public MainWindow(
- IStringLocalizer<MainWindow> localizer)
- {
- InitializeComponent();
- _localizer = localizer;
- }
- // ...
- {
- // ...
- MessageBox.Show(_localizer["Success"], _localizer["Tip"]);
- }
- }
xaml 文件中使用需要自定义一个扩展,定义如下,【实现源码】:
- public class LocalizerExtension : MarkupExtension
- {
- private readonly IStringLocalizerFactory _localizerFactory;
- public string Key { get; }
- public LocalizerExtension(string key)
- {
- Key = key;
- _localizerFactory = DependencyResolver.Current.
- ResolveService<IStringLocalizerFactory>();
- }
- public override object ProvideValue(IServiceProvider serviceProvider)
- {
- var targetRootType = serviceProvider.GetType()
- .GetProperty("System.Xaml.IRootObjectProvider.RootObject", BindingFlags.Instance | BindingFlags.NonPublic)
- ?.GetValue(serviceProvider)
- ?.GetType();
- if (null == targetRootType)
- {
- targetRootType = typeof(MainWindow);
- }
- var localizer = _localizerFactory.Create(targetRootType);
- var value = localizer[Key];
- return (string)value;
- }
- }
这里使用到了上面提到的 ServiceLocator
模式的代码,从 DependencyResolver
获取注册的服务,感觉这里的实现需要优化,有更好想法的小伙伴还望一起交流一下,另外如果你的应用比较简单,我觉得上面代码里的通过反射获取 targetRootType
的代码可以直接使用某一个类型例如:typeof(MainWindow)
,这样会更高效
在 Window
标签中添加扩展对应的命令空间,例如: xmlns:loc="clr-namespace:DbTool.Localization"
在需要实现多语言的地方引用,例如: <TextBlockMargin="0,0,4,0"Text="{loc:Localizer DbConnectionString}"></TextBlock>
在对应的资源文件中配置要使用多语言资源,如上面的 DbConnectionString
- <Window x:Class="DbTool.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:loc="clr-namespace:DbTool.Localization"
- mc:Ignorable="d"
- Title="DbTool" Height="450" Width="800" FontSize="14">
- <Grid>
- <TextBlock Margin="0,0,4,0" Text="{loc:Localizer DbConnectionString}"></TextBlock>
- </Grid>
- </Window>
发生语言切换时或应用启动时设置默认语言时,要更新当前线程的 Culture 信息
- // set current culture
- var defaultCulture = "zh";
- Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(defaultCulture);
- Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(defaultCulture);
这种方式的实现,目前还需要重启之后界面的语言才会发生变化,可以进一步优化,实现动态多语言,修改语言之后界面就切换,目前不是太需要,暂时没做,有需要的可以先自己研究一下。
https://github.com/WeihanLi/WeihanLi.Extensions.Localization.Json
https://github.com/WeihanLi/DbTool
https://github.com/WeihanLi/DbTool/blob/wpf-dev/DbTool/MainWindow.xaml
https://github.com/WeihanLi/DbTool/blob/wpf-dev/DbTool/MainWindow.xaml.cs
https://github.com/WeihanLi/DbTool/blob/wpf-dev/DbTool/Localization/LocalizerExtension.cs
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。