WPF: 本地化(Localization) 实现
本文将讨论在WPF中一种较为方便的本地化方法。
由于在项目中要实现本地化,所以我在网上查找相关的解决方案。通过一系列调研,发现实现本地化的方法主要有以下三种:
- 通过编译项目以设置 x:Uid 并使用 LocBaml 工具实现;
- 通过 DynamicResource 实现;
- 通过 Resx 文件实现
其中第一种是官方介绍的方法,考虑到实现步骤略为复杂,所以直接忽略;
第二种方式的实现,主要是在程序中添加 Resource Dictionary 类型的文件,并在其中放入本地化资源字符串;在 XAML 代码中,直接使用 {DynamicResource XXXX} 来实现;这种方法比较方便,不过它也有两个缺点:
- 在 XAML 中,引用 DynamicResource 的属性必须为依赖属性,否则会出错;
- 在 C# 代码中引用稍微有点麻烦,需要从 Resource Dictionary 中获取并转化为字符串
其中第一点可以说是致命缺点,我曾在项目中添加了一个第三方控件,其 Header 属性并不是依赖属性,所以不能使用这种方式;不是依赖属性,当然,也就更不能使用绑定(Binding)来设置了。
所以,之后尝试了第三种方式——使用 resx 文件,事实上,这是一种比较传统的、且普遍的方式,说它传统,是因为在 WinForm 中就可以这么做;说它普遍,是因为在 ASP.net MVC 中也可以这么做;并且,在 UWP 中的实现方式也与此有点类似。可以说,基本上基于 .NET 的各个平台都是以这种或类似这种方式来实现本地化的。并且,事件证明,这种方式的确是非常合适的,也很好用,在 XAML 代码和 C# 代码中均可以非常方便的使用。
使用 ResX 文件实现
它的操作步骤大概如下:
1. 创建一个 WPF 项目;
2. 在主窗口中添加几个需要本地化其内容的控件,如 TextBlock、Button等;
3. 展示此项目的 Properties 文件夹,这里已经有一个默认的 Resources.resx,在其中添加本地化字符串;
4. 将其复制,并粘贴到当前位置,将新文件改名为 Resources.en-US.resx,并修改其中的本地化字符串为对应的语言值;
说明:这里我们添加了对英语语言的本地化,至于支持哪些语言的本地化,可以参考这篇文章 Supported languages,关于语言匹配可参考这篇文章 Manage language and region,尽管这两篇文章是针对 UWP 的,不过原则上,对于 WPF 也是适用的;
5. 将上述两个 resx 文件的 Access Modifier 修改为 Public,默认值是 Internal;如下图:
接下来就是如何使用了:
6. 在 Xaml 中添加命名空间引用:
xmlns:loc="clr-namespace:WpfLocalizationTest.Properties"
7. 使用 {x:Static} 标记引用资源,如下:
<TextBlock Text="{x:Static loc:Resources.Main_Menu_Home}" />
8. 如果需要在代码中引用,也非常简单:
var homePage = Properties.Resources.Main_Menu_Home;
经测试,这种方式也支持 IntelliSense(智能提示),如下图:
如果你没看到智能提示,可以先编译项目。
此时,有两种方式可以测试本地化效果,第一种方式是在控制面板中改变操作系统的语言,第二种方式是通过代码改变 CurrentUICulture;这里我们使用后者,在 App.xaml.cs 中添加如下代码:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
}
运行后就可以看到测试结果了。
在大型项目中使用
上面是在 Demo 中展示如何本地化应用,那么在大型项目中是如何来应用这种方式呢?以下简单介绍一下,可以供参考:
1. 在解决方案中创建一个类库项目(或在已有项目中进行后续操作),此项目的用途主要是作资源用;
2. 在其中创建 Localization 文件夹,在这个文件夹下可以再创建针对各个模块的子文件夹,然后在此创建 resx 文件、添加本地化字符串并复制。文件结构如下:
3. 要在主程序中使用,方式和我们在 Demo 中提到的是一样的。首先在主程序项目中添加对新创建项目的引用,然后在 XAML 中添加命名空间和相关代码:
xmlns:loc2="clr-namespace:App.Resources.Localization.MainModule;assembly=App.Resources"
<Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_New}" />
<Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_Open}" />
更方便的方式
如果软件中有大量的文本需要本地化,那么在 resx 文件中的资源项将会非常多,这时,要在两个甚至更多资源文件中添加、删除、对比、检查项目时,将会非常困难。有没有更方便的方法呢?这里推荐一个 VS Extension: ResX Manager
它可以非常方便地管理当前解决方案中的 Resx 文件以及其中的资源项,安装后,在 VS 中工具菜单中可以打开,界面如下:
需要注意的是,如果要添加新资源项时,必须在左侧仅选择目标资源文件。它的具体用法,不属于本文讨论的范围,如果大家有需要了解,可以搜索相关教程。总之,通过这个插件,可以非常方便地创建、删除、管理本地化文本。
总结
所以,通过本文所提出的 Resx 文件本地化方案再加 ResXManager 扩展,你就可以方便地在你的 WPF项目中实现本地化了。如果您有更好的建议或意见,请留言交流。
参考文章:
WPF Globalization and Localization Overview
How to: Localize an Application
Localizing WPF Applications using Locbaml
WPF: 本地化(Localization) 实现的更多相关文章
- [WPF]本地化入门
1. 前言 WPF的本地化是个很常见的功能,我做过的WPF程序大部分都实现了本地化(不管最终有没有用到).通常本地化有以下几点需求: 在程序启动时根据CultureInfo.CurrentUICult ...
- WPF 本地化(多语言)
如果你的程序需要本地化,考虑的因素诸多,例如:当文本改变后,控件的当前高度,宽度 是否合适.所在的位置是否合适.字体.布局是否合适?如果已经构建了一个真正自适应的布局,就不会有问题.用户界面应当能够调 ...
- DotNetCore 3.0 助力 WPF本地化
概览 随着我们的应用程序越来越受欢迎,我们的下一步将要开发多语言功能.方便越来越多的国家使用我们中国的应用程序, 基于 WPF 本地化,我们很多时候使用的是系统资源文件,可是动态切换本地化,就比较麻烦 ...
- .net core在Linux本地化Localization的一次填坑
使用ABP框架开发.net core程序已经有一段时间了,因为之前部署在windows服务器上,使用一直很正常.自从前段时间切换服务器上了Linux的Centos服务器,发现之前中文的语言变成了英文, ...
- WPF全球化与本地化 (二)
Visual Baml Visual Locbaml is a free and open-source software to simplify the task of WPF applicatio ...
- [UWP]本地化入门
1. 前言 上一篇文章介绍了各种WPF本地化的入门知识,这篇文章介绍UWP本地化的入门知识. 2. 使用resw资源文件实现本地化 在以前的XAML平台,resx资源文件是一种很方便的本地化方案,但在 ...
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...
- 与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密
原文:与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密 [索引页][源码下载] 与众不同 wi ...
- python 本地化 local
locale 模块提供了 C 本地化( localization )函数的接口, 如 Example 8-1 所示. 同时提供相关函数, 实现基于当前 locale 设置的数字, 字符串转换. (而 ...
随机推荐
- GIS制图人员的自我修养(1)--制图误区
GIS制图人员的自我修养 by 李远祥 最近一直坚持写GIS制图的技术专题,并不是为了要介绍有什么好的技术和方法去制图,而是要告诉所有从事这一方向的人员一个铁铮铮的实现--要做好GIS制图,必须加强自 ...
- Yii2前后台分离
Yii2前后台都需要注册的时候会产生前后台登录一个另一个同步登录和退出,这是因为登录和退出之前的sitecontroller里面公用了common/model下面的LoginForm.php和user ...
- 各类编译器 allocator 底层
我们在c++中创建数组通常使用new来分配我们需要的内存大小,之后通过delete进行释放内存 但是我们调用new的时候,通过调用的是operator new,二operator new调用的是mal ...
- 三层——vb.net版
经过不懈的努力,我的vb.net 版的三层登陆终于实现了.下面将我的成果向大家展示一下. 原则 vb.net的三层登陆跟C#的三层登陆的思想是一样的都是将系统分层--U层只负责与用户 ...
- SpringMvc拦截器小测试
前言 俗话说做项目是让人成长最快的方案,最近小编写项目的时候遇到了一个小问题.小编在项目中所负责的后台系统,但是后台系统是通过系统的页面是通过ifame联动的,那么这时候问题就来了,后台所做的所有操作 ...
- SVM入门(一)
近来,了解了一下SVM(支持向量机 support vector machine)的原理.顺便把自己理解的内容整理一下. 不讲背景啦,直接切入主题. 一.什么是支持向量机 好比说,我们现在在一 ...
- [Hadoop] - Mapreduce自定义Counter
在Hadoop的MR程序开发中,经常需要统计一些map/reduce的运行状态信息,这个时候我们可以通过自定义Counter来实现,这个实现的方式是不是通过配置信息完成的,而是通过代码运行时检查完成的 ...
- JS中都有哪些数据类型呢?
js中有5种数据类型:Undefined.Null.Boolean.Number和String.还有一种复杂的数据类型Object,Object本质是一组无序的名值对组成的.
- android学习17——命令行建gradle工程
使用命令行建gradle工程要涉及到几个工具的版本. 1.gradle的版本.这个用gradle -version查到. 2.SDK BuildTools的版本. 这个要先配好SDK的环境变量,然后在 ...
- JPA规范及其它持久层框架
JPA是一种规范,而hibernate是JPA的一种实现 JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口.J ...