最近把 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