WPF 多语言支持插件的开发

本文介绍一种支持在设计时和运行时来动态更改程序运行语言支撑的实现方法。WPF多语言支持我们期望能够实现以下功能:

(1)能够与WPF的XAML直接集成;

(2)支持编码方式来访问资源;

(3)支持在运行时动态切换和动态编辑语言。

1 概述

以往多语言方式都是使用Resource文件来支持,这个文件最终会编译成资源dll文件。以这种方式实现多语言的优点是在开发的时候可以直接使用IDE,但是缺点就是动态性支撑较差,要实现动态语言切换比较麻烦,并且无法实现在运行时实现语言编辑。下图是语言切换的页面。

下图是切换成英语的显示效果。在这里,导航栏、系统菜单、状态栏和内容区域均实现语言动态切换。

以下是动态切换到中文的显示效果。

下图是运行时语言编辑器。在这里直接对资源进行翻译,翻译后立刻生效。

2 设计实现

本地化框架基于OSGi.NET框架设计,作为OSGi.NET的插件,其设计遵守以下原则:

(1)插件不依赖于具体的本地化支持方法。支持本地化的方法可以有Resource文件、自定义的XML文件等来存储本地化资源。不过,插件不能依赖于特定的实现。

(2)本地化的实现使用分级方式,第一级为应用环境无关,第二级为WPF相关。WPF相关的本地化支持,必须很好的考虑与WPF的XAML界面技术结合,尽可能提高在WPF中使用的易用性。

(3)支持本地化资源设计时、运行时动态编辑,特别是运行时编辑。支持在运行时变更语言环境。

本地化框架有本地化基础服务(UIShell.LocalizationService)、WPF本地化服务(UIShell.WpfLocalizationService)插件实现,其依赖关系如下所示。

如上图所示,第三方插件需要访问本地化资源时,只需要依赖于本地化基础服务,未来可以在不更改插件代码的情况下方便的扩展到其它本地化方法的实现。

本地化基础服务接口在UIShell.LocalizationService插件中定义,如下所示。它定义了资源获取接口、支持语言列表以及语言变更事件。

以下是本地化服务接口的描述。每一个插件均有自己的本地化存储空间,通过GetResource和GetString可以获取插件本身的本地化资源。

/// <summary>
/// 本地化服务。
/// </summary>
public interface ILocalizationService
{
    /// <summary>
    /// 支持的语言列表。
    /// </summary>
    Dictionary<string, CultureInfo> SupportCultureInfos { get; }
    /// <summary>
    /// 当前语言。
    /// </summary>
    CultureInfo CurrentCultureInfo { get; set; }
    /// <summary>
    /// 获取资源。
    /// </summary>
    /// <typeparam name="T">资源类型。</typeparam>
    /// <param name="bundle">所属插件。</param>
    /// <param name="resourceKey">资源Key。</param>
    /// <returns>返回资源对象。</returns>
    T GetResource<T>(IBundle bundle, string resourceKey, T defaultValue);
    /// <summary>
    /// 获取资源。
    /// </summary>
    /// <typeparam name="T">资源类型。</typeparam>
    /// <param name="bundleSymbolicName">所属插件标识。</param>
    /// <param name="resourceKey">资源Key。</param>
    /// <returns>返回资源对象。</returns>
T GetResource<T>(string bundleSymbolicName, string resourceKey,
T defaultValue);
    /// <summary>
    /// 获取字符串资源。
    /// </summary>
    /// <param name="bundle">插件。</param>
    /// <param name="resourceKey">资源Ke。</param>
    /// <returns>如果不存在返回string.Empty。</returns>
    string GetString(IBundle bundle, string resourceKey);
    /// <summary>
    /// 获取字符串资源。
    /// </summary>
    /// <param name="bundleSymbolicName">插件名称。</param>
    /// <param name="resourceKey">资源Ke。</param>
    /// <returns>如果不存在返回string.Empty。</returns>
    string GetString(string bundleSymbolicName, string resourceKey);
    /// <summary>
    /// 语言变更事件。
    /// </summary>
    event EventHandler<CultureInfoEventArgs> CultureInfoChanged;
}

public class CultureInfoEventArgs : EventArgs
{
    public CultureInfo PreviousCultureInfo { get; set; }
    public CultureInfo CurrentCultureInfo { get; set; }
}

WPF本地化服务的实现方法描述如下:

(1)语言文件使用XAML格式来存储,在插件根目录的Language目录下,语言文件文件名称为Resource.<语言>.xaml,自定义语言文件为Resource.xaml。简体中文的语言文件为Resource.zh-CN.xaml,繁体中文语言文件为Resource.zh-TW.xaml,英语为Resource.en-US.xaml。

(2)支持设置当前语言,一旦当前语言发生变更时,该服务将动态搜索当前语言的文件,并使用XamlReader类来读取资源,将资源文件序列化成ResourceDictionary类。

(3)编辑语言时,根据支持的语言动态生成一个DataGrid的列,每一个列就是对应语言的资源,语言的Key为所有语言的合并集合。

(4)语言编辑后,使用XamlWriter将ResourceDictionary序列化到指定语言文件。

WPF界面框架加载插件的用户控件后,会利用WPF本地化服务加载插件的资源,并将其ResourceDictionary与插件用户控件进行合并,因此,对于插件中直接在界面框架显示区域呈现的用户控件,可以直接使用以下方式来简便的访问服务。

{DynamicResource [ResourceKey]} ,可以在支持绑定的控件属性中直接设置。

此外,插件可以使用ILocalizationService.GetResource/GetString来获取当前语言的资源。

对于没有在主界面框架内容区域加载的控件,比如弹出一个窗口,为了使该窗口也支持通过DynamicResource来访问资源,必须通过IWpfLocalizationSerivce.GetResourceDitionary方法获取插件的资源集合,并与窗口资源进行合并。该服务实现如下所示。

WpfLocalizationServiceImpl具备动态性:

(1)它能够动态监听插件的状态变更,当插件启动时,加载插件语言资源;插件停止时,则删除语言资源。

(2)当前语言发生变更时,所有语言文件会被重新加载,并发出CultureInfoChanged事件,通知界面进行刷新。

3 XAML资源文件的处理

多语言的实现依赖于XAML文件的处理。以下代码是使用XamlReader将资源文件转换成ResourceDictionary。

以下代码则是使用XamlWriter将ResourceDictionary保存成XAML文件。

这种基于XAML的本地化实现方法能够很好的应用在WPF界面本地化、代码本地化资源访问,并且支持动态语言切换和运行时语言编辑。

时间: 2024-10-11 00:07:09

WPF 多语言支持插件的开发的相关文章

Android 原生应用开发得到Go语言支持

今天的主要内容为Android 原生应用开发得到Go 语言支持,那么我们首先简单看下GO是什么呢? Go是Google开发的一种编译型,並發型,并具有垃圾回收功能的编程语言. Google工程师和独立开发人员提出了几份不同的提案,旨在让Go语言支持开发原生的Android应用.这项工作无法让Go语言编写的应用使用Android NDK的全部接口,但有可能使用其中的一个子集. David Crawshaw是Google的工程师,他写了一份提案,旨在让Go语言部分支持编写Android应用.根据他的

WPF使用X:Static做多语言支持

原文:WPF使用X:Static做多语言支持 让程序支持多语言,一般把需要显示的字符串保存在一个资源类的static属性中. <!--[if !supportLists]--> <!--[endif]--> 微软的WPF程序多语言支持官方解决方案:使用Resource,并把Resource按语言编译成独立DLL,程序会根据系统当前语言设置,自动加载最合适的资源.(这种方法灵活性较差,而且不能满足多样的需求,于是网上各种多语言方案纷至沓来.)这里有一篇对官方方案的进一步解释. 使用X

WPF 实现多语言支持

WPF 多语言有各种实现方式.如 https://www.codeproject.com/Articles/35159/WPF-Localization-Using-RESX-Files,后来发现这个不够直接和简洁,在看到这里 https://www.cnblogs.com/yang-fei/p/4854460.html 这个朋友的实现觉得蛮不错的. 目前我觉得最好的一种或者说最适合我的一种是利用资源字典文件来做--- 就是吧各个语言创建为一个个资源字典文件,在程序启动的时候将选定的一种语言的资

《快速创建网站》 3.3 国际化高大上 - WordPress多语言支持

本文是<快速创建网站>系列的第7篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文.访问本系列目录,请点击:http://anb.io/blog/tag/wordpress-on-azure/ 1. 网站管理平台WordPress和云计算平台Azure简介 (6分钟 )2.1 在Azure上创建网站及网站运行机制 (13分钟)2.2 域名绑定操作和Azure负载均衡机制 (12分钟)2.3 WordPress 初始化和网站管理功能 (11分钟)3.1 WordP

Ubuntu 14.04下Gedit编辑器设置为多语言编辑及集成开发环境

Gedit是一个通用的编辑程序,其支持插件及自定义语言设置功能. 以Ubuntu 14.04下的Gedit编辑器为例,介绍其定制方法: 1 安装插件 sudo apt-get install gedit-plugins 2 在gedit中设置插件 略 3 设置语言配置文件 进入语言配置文件夹 cd /usr/share/gtksourceview-3.0/language-specs 查看语言配置文件(*.lang) ls 4 添加语言并根据配置文件设置对应源程序的扩展名 查看当前目录下相近语言

OS X 10.11搭建go语言1.5.1开发环境

1.安装Golang的SDKhttp://golang.org ,下载最新的安装包,之后双击安装即可.某此同学国内打不开的...我只想说,学谷歌的东西,自己想个好点办法吧...你懂的 安装完成之后,打开终端,输入go.或者go version(查看安装版本)出现如下信息即表示安装成功: $ go version go version go1.5.1 darwin/amd64 2.配置环境变量安装完sdk之后接下来便是配置环境变量了,打开终端输入cd ~ 进入用户主目录,之后输入ls -all命令

我在写多语言支持时用到的东西

我在写多语言支持时用到的东西 絮叨絮叨:好久不来写了,竟然支持markdown 了. 我也是在项目里的wiki 里干刚接触了一些, 来这里也试试.然后悲催的发现,mac 电脑在markdown下直接上传图片有bug @2015-08-19 20:28:13.一会试一下链接版的吧. 我们的37度手环一不小心要卖到国外去了,自然要支持多国家多语言啦. 等卖到阿拉伯世界的时候,我会再补充RTL(Right To Left)相关的内容. 本文仅涉及安卓(Android)客户端的实现, 服务器后台的部分没

在VC工程中添加多语言支持[转]

随着贸易国际化,在软件开发过程中,常会碰到需在现有中文版软件加入多语言支持的情况.由于不同语言版本间的差别通常仅是软件操作界面的不同,为实现多语言支持,使用纯资源DLL是一个不错的解决之道.所谓纯资源DLL是指只包含资源的DLL,譬如:快捷键.对话框.字符串.菜单.工具条.位图.图标.版本信息等等. 具体做法是:利用VC可视化编辑环境为每种语言制作一套资源ID一一对应的资源集并编译生成DLL文件.应用程序初始化时按预设的语言设置选择合适的资源DLL调入,使用资源时依据资源ID进行访问,这样即可实

一个轻客户端,多语言支持,去中心化,自动负载,可扩展的实时数据写服务的实现方案讨论

背景 背景是设计一个实时数据接入的模块,负责接收客户端的实时数据写入(如日志流,点击流),数据支持直接下沉到HBase上(后续提供HBase上的查询),或先持久化到Kafka里,方便后续进行一些计算和处理,再下沉到文件系统或做别的输出. 在设计中,对于客户端和服务端有这么些目标. 客户端需要支持多语言(Java,C++),做得尽量轻量级,只要连上服务端的ip:port,以RPC的形式调用简单的write就可以把数据写出去.客户端不承担任何逻辑的处理,服务端的负载均衡对客户端是透明的. 服务端想要