前面 WPF & Sivlerlight 多语言解决方案-实现本地化 对本地化语言资源编辑描述了一下, 说实话, 很麻烦. 经过一天摸索和翻阅文章, 找到了相对简单很多的多语言解决方案.
动态切换软件使用的语言, 是很多软件所使用的方式, 传统的Winform, Win32程序都需要有很多类库和语言资源解析类来完成界面上语言的切换. 在WPF里面,我们可以很方便的利用 动态资源(Dynamic resource)来完成此操作.
我的系统说明:
在我的系统是基于插件的开发框架,里面有多个project, 不能在某一个project中设置所有语言资源, 每个project都可能是独立运行的; 也就是,每个project里面都需要定义语言资源. 下面就说说我的思路. 其实搞成功了也是很简单的方法.
我们首先要有规则, 这个规则就是,每个project里面需要有统一的语言命名方式和文件命名方式, 看下面demo: 我每个项目都有LanCN.xaml 和 LanEN.xaml 这是分别定义中文和英文, 是每个需要用到语言资源的project里面都需要
前面 WPF & Sivlerlight 多语言解决方案-实现本地化 对本地化语言资源编辑描述了一下, 说实话, 很麻烦. 经过一天摸索和翻阅文章, 找到了相对简单很多的多语言解决方案.
动态切换软件使用的语言, 是很多软件所使用的方式, 传统的Winform, Win32程序都需要有很多类库和语言资源解析类来完成界面上语言的切换. 在WPF里面,我们可以很方便的利用 动态资源(Dynamic resource)来完成此操作.
我的系统说明:
在我的系统是基于插件的开发框架,里面有多个project, 不能在某一个project中设置所有语言资源, 每个project都可能是独立运行的; 也就是,每个project里面都需要定义语言资源. 下面就说说我的思路. 其实搞成功了也是很简单的方法.
我们首先要有规则, 这个规则就是,每个project里面需要有统一的语言命名方式和文件命名方式, 看下面demo: 我每个项目都有LanCN.xaml 和 LanEN.xaml 这是分别定义中文和英文, 是每个需要用到语言资源的project里面都需要定义的.
具体语言内容和怎么使用字符串资源可以查看源码. 下面我来说说怎么简单的载入所有project中的字符串资源.
第一步. 设置默认和设计期语言资源
首先我们先看一下, MainApp.Controls.WinTest 这个窗口的xaml文件中引用字符串资源文件.
Window.Resources
1<Window.Resources>
2 <ResourceDictionary>
3 <ResourceDictionary.MergedDictionaries>
4 <ResourceDictionary Source="/MainApp.Controls;component/LanCN.xaml" />
5 </ResourceDictionary.MergedDictionaries>
6 </ResourceDictionary>
7 </Window.Resources>
这里我们定义了引用, 注意引用格式, 再看一下MainApp里面的App.xaml中, 我同时也用到了另一个项目的语言资源(怎么使用另一个程序集的资源就是这么搞):
Application.Resources
1 <Application.Resources>
2 <ResourceDictionary>
3 <ResourceDictionary.MergedDictionaries>
4 <ResourceDictionary Source="/MainApp;Component/LanCN.xaml"/>
5 <ResourceDictionary Source="/MainApp.Controls;Component/LanCN.xaml"/>
6 </ResourceDictionary.MergedDictionaries>
7 </ResourceDictionary>
8 </Application.Resources>
这样我都使用了LanCN.xaml,也就是中文, 这些引用的目的是默认语言资源和设计器使用的.
第二步.运行期设置语言和资源
大家首先看一下Utils这个类
Utils 类
1public class Utils
2{
3 static List<string> AssemblyLans { get; set; }
4 /**//// <summary>
5 /// Loading language resource file
6 /// </summary>
7 /// <param name="app"></param>
8 public static void LoadLanguangeResource(System.Windows.Application app)
9 {
10 AssemblyLans = new List<string>();
11 Assembly[] ps = AppDomain.CurrentDomain.GetAssemblies();
12 foreach (Assembly items in ps)
13 {
14 if (items.GlobalAssemblyCache) continue;
15 try
16 {
17 string assembly = items.FullName.Split(',')[0];
18 string lanRes = string.Format("/{0};Component/Lan{1}.xaml", assembly, Language);
19 ResourceDictionary langRd = Application.LoadComponent(new Uri(lanRes, UriKind.RelativeOrAbsolute)) as ResourceDictionary;
20
21 app.Resources.MergedDictionaries.Add(langRd);
22 AssemblyLans.Add(assembly);
23 }
24 catch (Exception exp)
25 {
26 System.Diagnostics.Trace.WriteLine(exp.Message);
27 }
28 }
29 }
30 /**//// <summary>
31 /// clear default language resource
32 /// </summary>
33 /// <param name="ele"></param>
34 public static void ClearDefaultLan(FrameworkElement ele)
35 {
36 Assembly items = Assembly.GetCallingAssembly();
37 string assembly = items.FullName.Split(',')[0];
38 if (!AssemblyLans.Contains(assembly)) return;
39 if (ele.Resources.MergedDictionaries.Count > 0)
40 {
41 ele.Resources.MergedDictionaries.Clear();
42 }
43 }
44 public static string Language
45 {
46 get
47 {
48 string result = "";
49 try
50 {
51 result = ConfigurationManager.AppSettings["lan"];
52 }
53 catch
54 {
55
56 }
57 if (string.IsNullOrEmpty(result))
58 {
59 result = "en";
60 }
61 return result.ToUpper();
62 }
63 }
64}
65
LoadLanguangeResource
是装载语言资源的方法, 这里是从配置文件中读取要取得的语言名.
大家注意这两句:
string lanRes = string.Format("/{0};Component/Lan{1}.xaml", assembly, Language);
ResourceDictionary langRd = Application.LoadComponent(new Uri(lanRes, UriKind.RelativeOrAbsolute)) as ResourceDictionary;
我这是从程序集中读取, 其实我们可以从外部文件或者URL来读取, 以方便修改.
ClearDefaultLan
是清除设计期的默认语言, 这里面我处理了一下,就是没有所指定的资源时候,用默认资源.
大家请看MainApp.Controls.WinTest的构造函数中:
InitializeComponent();
Utils.ClearDefaultLan(this);
这个Utils.ClearDefaultLan(this)一定要在InitializeComponent()之后调用, 没有初始化无效调用.
好了,这2个关键函数已经知道干什么了,我们再看 App.xaml.cs代码:
App.xaml.cs
private void OnStartup(Object sender, StartupEventArgs e)
{
LoadLanguage();
}
void LoadLanguage()
{
if (this.Resources.MergedDictionaries.Count > 0)
{
this.Resources.MergedDictionaries.Clear();
}
Controls.Utils.LoadLanguangeResource(this);
}
首先清除App全局语言资源, 然后装载所有的程序集语言资源. ok了, 大家下载源码修改App.config中语言配置跑跑看效果. 注意每个地方使用的资源(2个程序集中的).