最近把 DbTool 从 WinForm 迁移到了 WPF,并更新到了 dotnet core 3.1,并实现了基于 Microsoft.Extensions.Localization
实现了基本的多语言支持。下面来分享一下如何来实现html
若是不熟悉如何在 WPF 中使用依赖注入,能够参考上一篇文章 dotnetcore3.1 WPF 中使用依赖注入git
在应用启动前注册 Localization 服务,我这里使用的是本身自定义的基于 JSON 的多语言服务github
services.AddJsonLocalization(options => options.ResourcesPathType = ResourcesPathType.CultureBased);
服务注册的最后使用了一个 ServiceLocator 模式的代码(DependencyResolver),保存了全部的注册服务,后面的 Localizer 扩展会用到express
DependencyResolver.SetDependencyResolver(services);
代码文件(如:MainWindow.xaml.cs) 中实现多语言较为简单,直接注入 IStringLocalizer
便可,获取对应的要实例化的,好比:ide
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)
,这样会更高效spa
Window
标签中添加扩展对应的命令空间,例如: xmlns:loc="clr-namespace:DbTool.Localization"
<TextBlock Margin="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);
这种方式的实现,目前还须要重启以后界面的语言才会发生变化,能够进一步优化,实现动态多语言,修改语言以后界面就切换,目前不是太须要,暂时没作,有须要的能够先本身研究一下。code