dotnetcore3.1 WPF 实现多语言
dotnetcore3.1 WPF 实现多语言
Intro
最近把 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 实现方式
LocaliazerExtension
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)
,这样会更高效
在 xaml 中使用
- 在
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);
实现效果
More
这种方式的实现,目前还需要重启之后界面的语言才会发生变化,可以进一步优化,实现动态多语言,修改语言之后界面就切换,目前不是太需要,暂时没做,有需要的可以先自己研究一下。
Reference
- 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
dotnetcore3.1 WPF 实现多语言的更多相关文章
- dotnetcore3.1 WPF 中使用依赖注入
dotnetcore3.1 WPF 中使用依赖注入 Intro 在 ASP.NET Core 中默认就已经集成了依赖注入,最近把 DbTool 迁移到了 WPF dotnetcore 3.1, 在 W ...
- WPF 实现多语言支持
WPF 多语言有各种实现方式.如 https://www.codeproject.com/Articles/35159/WPF-Localization-Using-RESX-Files,后来发现这个 ...
- WPF国际化(多语言)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- 设置 WPF 的全球化语言
https://stackoverflow.com/questions/7454024/setting-culture-en-in-globally-in-wpf-app Thread.Current ...
- WPF使用X:Static做多语言支持
让程序支持多语言,一般把需要显示的字符串保存在一个资源类的static属性中. <!--[if !supportLists]--> <!--[endif]--> 微软的WPF程 ...
- WPF 获得当前输入法语言区域
原文:WPF 获得当前输入法语言区域 本文告诉大家如何获得 WPF 输入法的语言区域 需要使用 user32 的方法,很简单,请看下面 [DllImport("user32.dll" ...
- [No000012C]WPF(4/7)类型转换器和标记扩展[译]
介绍 之前讨论了WPF的基础架构,然后逐步开始学习布局面板,转换,介绍了不同的控件,容器,UI转换等.在这篇文章中,我将讨论每个创建XAML应用前的开发人员应该了解的关于XAML最重要的东西. 标记扩 ...
- WPF入门(三)->几何图形之线条(LineGeometry)
原文:WPF入门(三)->几何图形之线条(LineGeometry) 前一章我们对wpf的xaml语言有了一定的了解,那么我们现在开始来学习如何使用wpf来画出几何图形. LineGeometr ...
- 2019-6-23-WPF-获得当前输入法语言区域
title author date CreateTime categories WPF 获得当前输入法语言区域 lindexi 2019-06-23 11:51:21 +0800 2018-10-12 ...
随机推荐
- [bzoj2120] [洛谷P1903] 数颜色
Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜 ...
- elasticsearch为什么比mysql快
mysql关系型数据库索引原理 数据库的索引是B+tree结构 主键是聚合索引 其他索引是非聚合索引,先从非聚合索引找,见下图 elasticsearch倒排索引原理 两者对比 对于倒排索引,要分两种 ...
- copy and swap技巧与移动赋值操作符
最近在实现一个Delegate类的时候碰到了一个问题,就是copy and swap技巧和移动赋值操作符有冲突. 比如有以下一个类: class Fun { public: Fun(const Fun ...
- PHP批量去除文件BOM头
auto 是否自动替换 默认否 dir 检查目录 默认./ display 是否显示所有文件 默认只显示有bom头的文件 <?php empty($_GET['auto']) && ...
- 看看AQS阻塞队列和条件队列
上一篇简单介绍了AQS,我们大概知道AQS就是一个框架,把很多功能都给实现了(比如入队规则,唤醒节点中的线程等),我们如果要使用的话只需要实现其中的一些方法(比如tryAcquire等)就行了!这次主 ...
- Vertx使用EventBus发送接受自定义对象
先看官方文档步骤: 需要一个编解码器,看源码: 可见内置了需要数据类型的实现,所以发送其他消息可以发送,但是如果发送自定义对象就需要自己实现编解码逻辑了 一 自定义编解码器 /** * 自定义对象编解 ...
- Shrio | java.io.IOException: Resource [classpath:shiro.ini] could not be found
案例 今天项目启动时一直报异常,看了错误日志发现是shrio文件找不到引起的,异常: java.io.IOException: Resource [classpath:shiro.ini] could ...
- Flink 1.10 正式发布!——与Blink集成完成,集成Hive,K8S
Apache Flink社区宣布Flink 1.10.0正式发布! 本次Release版本修复1.2K个问题,对Flink作业的整体性能和稳定性做了重大改进,同时增加了对K8S,Python的支持. ...
- Qt qApp
qApp A global pointer referring to the unique application object. It is equivalent to the pointer re ...
- 解决dotnet错误 System.InvalidOperationException Message=Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found.
开始=>设置=>manage user certificats (管理用户证书),里面所有的.net core的全部删除 然后控制台执行: dotnet dev-certs https ...