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

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

让程序支持多语言,一般把需要显示的字符串保存在一个资源类的static属性中。

<!--[if !supportLists]--> <!--[endif]-->

微软的WPF程序多语言支持官方解决方案:使用Resource,并把Resource按语言编译成独立DLL,程序会根据系统当前语言设置,自动加载最合适的资源。(这种方法灵活性较差,而且不能满足多样的需求,于是网上各种多语言方案纷至沓来。)这里有一篇对官方方案的进一步解释。

使用XML保存语言文件:放进来只是因为网上的确有这么个解释方案,虽然没有什么实用价值……,Resource本来就是XML,还用自己定义一个XML,还XMLDataProvider,还XML-based Data Binding,看着都累…… 
使用Project Resource的:和上面的类似,不过把字符串全放在Project Resource里,然后用ObjectDataProvider,然后也是使用Data Binding。

Assembly自带语言:每个Assembly里放上支持的所有语言,使用配置文件设置软件语言,比微软的方案更进一步,但是WPF程序多语言支持问题也还是存在的。

<!--[if !supportLists]--><!--[endif]--><!--[if !supportLists]--><!--[endif]--><!--[if !supportLists]--><!--[endif]-->

上面所有的方案都没有同时解决下面这两个问题:

<!--[if !supportLists]--> <!--[endif]-->

运行时切换语言。

加入新语言,而不需要重新编译软件。

<!--[if !supportLists]--><!--[endif]--> 
下面,就来介绍一种更灵活的,解决了上面两个问题的WPF程序多语言支持方案。

基本方式还是使用Resource,只不过Resource是运行时才加载进来的。解决方案的结构如下图所示。

其中各个语言文件的资源文件放在Resources/Langs文件夹中,这些资源文件不会被编译到Assembly中,编译之后的文件结构如下图所示,语言文件被原样复制到Output文件夹中。

先来看看程序的运行效果,再来看代码会比较直观一些。

下面就是这个界面的代码。

  1. MainWindow
  2. <Window x:Class="Localization.DemoWindow"
  3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5. xmlns:c="clr-namespace:Localization.Backend.Commands"
  6. Title="{DynamicResource MainWindowTitle}"
  7. Width="230" Height="150">
  8. <DockPanel LastChildFill="False">
  9. <Menu DockPanel.Dock="Top">
  10. <Menu.CommandBindings>
  11. <x:Static Member="c:LanguageCommands.OpenLanguageBinding"/>
  12. </< SPAN>Menu.CommandBindings>
  13. <MenuItem Header="{DynamicResource LanguageMenuHeader}">
  14. <MenuItem Header="{DynamicResource EnglishMenuHeader}"
  15. Click="OnLoadEnglishClick"/>
  16. <MenuItem Header="{DynamicResource ChineseMenuHeader}"
  17. Click="OnLoadChineseClick" />
  18. <Separator/>
  19. <MenuItem Command="c:LanguageCommands.OpenLanguage"
  20. Header="{DynamicResource OpenLanguageFileMenuHeader}"/>
  21. </< SPAN>MenuItem>
  22. </< SPAN>Menu>
  23. </< SPAN>DockPanel>
  24. </< SPAN>Window>

所有的界面上的文字,都使用DynamicResource引用资源文件中的字符串。资源文件的格式如下(英文资源文件示例):

  1. <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  3. xmlns:s="clr-namespace:System;assembly=mscorlib">
  4. <s:String x:Key="MainWindowTitle">Localization Demo</< SPAN>s:String>
  5. <s:String x:Key="LanguageMenuHeader">_Language</< SPAN>s:String>
  6. <s:String x:Key="EnglishMenuHeader">_English</< SPAN>s:String>
  7. <s:String x:Key="ChineseMenuHeader">汉语(_C)</< SPAN>s:String>
  8. <s:String x:Key="OpenLanguageFileMenuHeader">_Open Language File</< SPAN>s:String>
  9. </< SPAN>ResourceDictionary>

语言文件没有编译到Assembly中,使用起来就有些不太一样。下面是App.xaml文件中设置Application的默认加载语言的方式。

  1. <Application x:Class="Localization.App"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. StartupUri="UI\DemoWindow.xaml">
  5. <Application.Resources>
  6. <ResourceDictionary>
  7. <ResourceDictionary.MergedDictionaries>
  8. <ResourceDictionary Source="pack://siteOfOrigin:,,,/Resources/Langs/en-US.xaml"/>
  9. </< SPAN>ResourceDictionary.MergedDictionaries>
  10. </< SPAN>ResourceDictionary>
  11. </< SPAN>Application.Resources>
  12. </< SPAN>Application>

前面的内容基本上没有什么和别的方案不一样的地方,下面才是最重要的一点,就是如何运行时切换语言的呢?答案就是,只要把上面代码里的ResourceDictionary替换掉就OK了,界面会自动刷新。下面就是实现替换功能的代码。

  1. public class LanguageHelper
  2. {
  3. /// <summary>
  4. ///
  5. /// </< SPAN>summary>
  6. /// <param name="languagefileName"></< SPAN>param>
  7. public static void LoadLanguageFile(string languagefileName)
  8. {
  9. Application.Current.Resources.MergedDictionaries[0] = new ResourceDictionary()
  10. {
  11. Source = new Uri(languagefileName, UriKind.RelativeOrAbsolute)
  12. };
  13. }
  14. }

参数languagefileName可以是文件的绝对路径,如:C:\en-US.xaml或是和App.xaml里一样的相对路径。顺便解释一下,那个“pack://siteOfOrigin:,,,”无非就是当前执行程序的所在目录。

以目前的测试结果来看,即使界面上有大量的细粒度文字。切换语言的速度也是一瞬间的事儿,如果慢,也是因为xaml文件过大,读文件用了不少时间。

WPF程序多语言支持缺陷

其实这才是最重要的,很多文章介绍一项技术的时候都会把这个技术夸得天花乱坠,却对潜在的缺陷或问题避而不谈。

缺陷就在于,不是所有的东西都是可以运行是更新的。比如最后一个菜单项是用Command实现的,如下代码所示:

  1. <MenuItem Command="c:LanguageCommands.OpenLanguage"
  2. Header="{DynamicResource OpenLanguageFileMenuHeader}"/>

RoutedUICommand本身就已经定义了Text属性用来显示在界面上,完全没有必要为使用了这个Command的MenuItem设置Header属性。但是这里为什么还是设置了呢?因为目前还没有找到简单的方案改变Command的Text后能自动地更新界面。因为Command的Text属性不是一个Dependency Property。为了自动更新界面,不得不为MenuItem设置Header属性。

原文地址:https://www.cnblogs.com/lonelyxmas/p/9074803.html

时间: 2024-10-12 05:24:34

WPF使用X:Static做多语言支持的相关文章

WPF 多语言支持插件的开发

本文介绍一种支持在设计时和运行时来动态更改程序运行语言支撑的实现方法.WPF多语言支持我们期望能够实现以下功能: (1)能够与WPF的XAML直接集成: (2)支持编码方式来访问资源: (3)支持在运行时动态切换和动态编辑语言. 1 概述 以往多语言方式都是使用Resource文件来支持,这个文件最终会编译成资源dll文件.以这种方式实现多语言的优点是在开发的时候可以直接使用IDE,但是缺点就是动态性支撑较差,要实现动态语言切换比较麻烦,并且无法实现在运行时实现语言编辑.下图是语言切换的页面.

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

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

MVC4多语言支持

第一步 建立资源文件 为WEB项目添加Resource文件夹,然后在Resource文件夹下添加两个resx文件en-US.resx和zh-CN.resx文件. 使用Resgen.exe将resx转为resource文件(Resgen.exe可以放到windows/system32或windows/syswow64下),cmd运行下列语句: resgen D:\WORKSPACE\Locale\Locale\Resource\en-US.resx D:\WORKSPACE\Locale\Loca

Android多语言支持以及各国语言Values文件夹命名规则

创建好的项目工程由于需求 需要做多国语言的支持  下面介绍怎么快捷的创建文件夹 建好一个android 的项目后,默认的res下面 有layout.values.drawable等目录 这些都是程序默认的资源文件目录,如果要实现多语言版本的话,我们就要添加要实现语言的对应的资源文件. 首先我们点击添加Android Xml File按钮,在Resource Type中选择Values 在File中输入string.xml ,会出现下面的界面: 下面 以添加一个 英语(美国):values-en-

【转】解析JDK 7的动态类型语言支持

http://www.infoq.com/cn/articles/jdk-dynamically-typed-language Java虚拟机的字节码指令集的数量自从Sun公司的第一款Java虚拟机问世至JDK 7来临之前的十余年时间里,一直没有发生任何变化[1].随着JDK 7的发布,字节码指令集终于迎来了第一位新成员——invokedynamic指令.这条新增加的指令是JDK 7实现“动态类型语言(Dynamically Typed Language)”支持而进行的改进之一,也是为JDK 8

分享两种实现Winform程序的多语言支持的解决方案

因公司业务需要,需要将原有的ERP系统加上支持繁体语言,但不能改变原有的编码方式,即:普通程序员感受不到编码有什么不同.经过我与几个同事的多番沟通,确定了以下两种方案: 方案一:在窗体基类中每次加载并显示窗体时,会自动递归遍历含文本显示的控件(Button,CheckBox,GroupBox,Label,LinkLabel,TextBox,StatusStrip,TabPage,ToolStrip,RadioButton,DateTimePicker,DataGridView,CheckedLi

sepl 2.0,器普语言支持国际化

sepl 2.0,器普语言支持国际化 sepl 2.0 最近使用sepl编程,除了编译器有错误外,还有就是语法还有些问题. 为了把 C#程序员吸引过来不让他们回去,决定引入英文关键字.这样C#程序移植到sepl将非常容易. 而且国际用户也可以用英文编程,符合计算机语言习惯,不必一定要中文. 对于中文语法,采用强制执行,而不是禁止用英文.如果代码不需要审核,也不关心是否完全中文吧. 这样不仅能做到彻底中文化,也能保留英文编程.说到底.这是为了国际化准备,否则会丧失很大市场. 最大区别是 赋值 使用

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

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

static C语言

C语言程序可以看成由一系列外部对象构成,这些外部对象可能是变量或函数.而内部变量是指定义在函数内部的函数参数及变量.外部变量定义在函数之外,因此可以在许多函数中使用.由于C语言不允许在一个函数中定义其它函数,因此函数本身只能是"外部的". 由于C语言代码是以文件为单位来组织的,在一个源程序所有源文件中,一个外部变量或函数只能在某个文件中定义一次,而其它文件可以通过extern声明来访问它(定义外部变量或函数的源文件中也可以包含对该外部变量的extern声明). 而static则可以限定