怎样实现WPF Prism Module的国际化和本地化?

English | 简体中文

上一篇有简单介绍主工程的国际化,使用的资源字典(XAML)实现的。

这几天我添加了几个Prism模块(Module),发现子模块使用资源字典的方式实现国际化和本地化不好做,没有找到比较好的参考文章,所以换了一种方式,使用资源文件实现了。

一、本文概述

子模块的国际化和本地化要求:

    1. 各模块需要有自己单独的语言文件。
    1. 在主工程中动态切换语言时,子模块也需要跟着切换。
    1. 使用了Prism实现模块化框架,即要求主工程与各子模块不能有引用关系,即松耦合,不能直接在主工程中切换子模块的语言文件。

基于上面的要求,我尝试在各模块(Module)中也定义了语言文件(XAML),主窗体切换语言时,加载模块语言文件老是提示不存在对应的资源字典文件,我恼火呀,后面还是参考“Accelerider.Windows”国际化的方式,使用资源文件实现本地化和国际化了,不纠结Xaml的方式了,唉。

下面是修改后的效果:

和上一版异同:

    1. 标题栏国际化无变化,只是文字绑定换了种方式,实现效果一致。
    1. 左侧添加了三个子模块(Home\Client\Server),使用Prism动态加载的,并且跟随主工程主窗体语言切换而切换语言。

下面简单介绍怎么创建模块,以及主窗体和模块国际化怎么做的,真的是很简单的介绍,具体的实现可以拉代码看看。

二、 添加三个Prism模块(Module)

可安装Prism模板,快速创建模块工程,当然手工创建.Net Core工程也是可以的,就是多了几个步骤而已(需要用Nuget安装Prism.Wpf包(7.2.0.1422)),我使用得的Prism模板快速创建的。

2.1 创建模块之前的准备工作

下载上图搜索到的Prism模板,重启VS,它会自动安装,新建项目时,就有Prism模块模板选择了:

注意要选择.NET Core 3的版本,因为我是使用.NET Core创建的WPF项目。

2.2 创建模块

下面是已经创建好的三个模块工程截图:

目前三个模块文件组织结构类似:

  • I18nResources:资源文件夹,放3个语言资源文件和一个T4模板文件(用于引用语言Key),其中T4模板文件在3个模块和主工程中定义是一样的,具体可从github下载源码查看。
  • Views放置视图文件,现在只使用到了主工程主窗体中显示的TabItem视图,即MainTabItem.xaml,继承自TabItem。
  • xxxxModule.cs:prism模板定义文件,prism发现模块使用。

三个模块关键点需要注意:

    1. 编辑模块工程文件,修改模块文件输出目录:
// 省略部分代码,下面这一行设置为False,代表输出目录不带.NET Core版本信息
<AppendTargetFrameworkToOutputPath>Flase</AppendTargetFrameworkToOutputPath>
// 省略部分代码,修改Debug与Release编译输出目录,方便主工程统一加载模块
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\Build\Debug\Modules</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\Build\Release\Modules</OutputPath>
</PropertyGroup>
// 省略部分代码
    1. XXXModule中需要将资源文件的ResourceManager引用添加到另一个库中保存,待切换语言时需要使用,如在HomeModule的构造函数中添加代码如下,只添加这一句代码就好,模块的国际化及本地化就算完事了:
I18nManager.Instance.Add(TerminalMACS.Home.I18nResources.UiResource.ResourceManager);
    1. XXXModule的RegisterTypes方法中注册视图"MainTabItem"到"RegionNames.MainTabRegion",主窗体使用"RegionNames.MainTabRegion"关联模块视图显示加载。
_regionManager.RegisterViewWithRegion(RegionNames.MainTabRegion, typeof(MainTabItem));
    1. UI控件国际化文字绑定,其中markup使用的一个开源库命名空间,后面会给出链接,本项目直接将该库加载进了解决方案中;i18NResources:Language即T4模板文件生成的类,关联文字翻译的Key。绑定文字部分代码如下:
<TextBlock Grid.Row="2" Text="{markup:I18n {x:Static i18NResources:Language.MainTabItm_Header}}"

三、 主工程

主工程目录组织结构如下:

3.1 动态加载Prism模块

配置加载3个模块的关键代码在App.xaml.cs文件中,看上面的代码,我将三个模块输出到了Modules目录下,主工程直接加载此目录即可,其他加载方式还有使用配置文件等,可以参考Prism官方例子,文末给出链接:

protected override IModuleCatalog CreateModuleCatalog()
{
string modulePath = @".\Modules";
if (!Directory.Exists(modulePath))
{
Directory.CreateDirectory(modulePath);
}
return new DirectoryModuleCatalog() { ModulePath = modulePath };
}

主窗体显示子模块注册的TabItem视图,prism:RegionManager.RegionName即在各子模块中注册过的区域字符串,他与模块对应的TabItem视图关联,代码如下:

<TabControl Grid.ColumnSpan="2" SelectedIndex="0"
Style="{StaticResource MainTabControlStyle}"
ItemContainerStyle="{StaticResource MainTabItemStyle}"
prism:RegionManager.RegionName="{x:Static ui:RegionNames.MainTabRegion}"/>

主窗体以TabControl的控件形式展示子模块视图:

主工程要能正常加载子模块,主工程的工程文件也需要修改其输出目录:

// 省略部分代码,下面这一行设置为False,代表输出目录不带.NET Core版本信息
<AppendTargetFrameworkToOutputPath>Flase</AppendTargetFrameworkToOutputPath>
// 省略部分代码,修改Debug与Release编译输出目录,方便主工程统一加载模块
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\Build\Debug</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\Build\Release</OutputPath>
</PropertyGroup>
// 省略部分代码

3.2 修改语言文件格式

删除了原有的XAML语言文件,替换为resx的资源文件,和三个模块的资源文件类型类似,下面是主工程的资源文件:

替换成资源文件,编辑是要比XAML文件要方便点,起初是有考虑使用资源文件实现国际化的,作死想尝试XAML文件。

3.3 语言切换核心代码

动态切换语言的关键代码改为:

public static void SetLanguage(string language = "")
{
if (string.IsNullOrWhiteSpace(language))
{
language = ConfigHelper.ReadKey(KEY_OF_LANGUAGE);
if (string.IsNullOrWhiteSpace(language))
{
language = System.Globalization.CultureInfo.CurrentCulture.ToString();
}
} ConfigHelper.SetKey(KEY_OF_LANGUAGE, language);
_lastLanguage = language; var culture = new System.Globalization.CultureInfo(language);
I18nManager.Instance.CurrentUICulture = culture;
}

核心的语言切换代码是最后一句,不详细说了,解决方案中有库、有源码:

I18nManager.Instance.CurrentUICulture = culture;

四. 源码

五. 参考资料

怎样实现WPF Prism Module的国际化和本地化?的更多相关文章

  1. WPF Prism MVVM 中 弹出新窗体. 放入用户控件

    原文:WPF Prism MVVM 中 弹出新窗体. 放入用户控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_37214567/artic ...

  2. Orchard 源码探索(Localization)之国际化与本地化

    本地化与国际化 基本上相关代码都在在Orchard.Framework.Localization中. T("english")是如何调用到WebViewPage.cs中的Local ...

  3. Django 国际化和本地化

    所谓的国际化,是指使用不同语言的用户在访问同一个网站页面时能够看到符合其自身语言的文本页面. 国际化的基本原理是: 浏览器通过LANGUAGE_CODE在HTTP请求头中告诉网站后台服务器用户所需要的 ...

  4. 第六章:Django 综合篇 - 18:国际化和本地化

    所谓的国际化,是指使用不同语言的用户在访问同一个网站页面时能够看到符合其自身语言的文本页面. 国际化的基本原理是: 浏览器通过LANGUAGE_CODE在HTTP请求头中告诉网站后台服务器用户所需要的 ...

  5. .NET:国际化和本地化

    .NET:国际化和本地化 背景 国际化(i18n)和本地化(l10n)是高端程序的必备技术,可惜从业五年从没有尝试过,下一步准备做一个多用户的博客系统,想支持多语言,今天就学习了一下,写出来,希望大家 ...

  6. IOS软件国际化(本地化Localizable)

    IOS软件国际化(本地化Localizable) iPhone是支持语言最多的手机,它支持各国语言及中国少数名族如蒙古等语言,这也是好多少数名族都用苹果的原因.在这一点上我们自主品牌还是要多学习学习. ...

  7. Spring MVC 的国际化和本地化

    国际化: i18n 本地化: l10n java.util.Locale 类表示一个语言区域.一个 Locale 对象包含 3 个主要元件:language.country.variant java. ...

  8. Django国际化和本地化

    把django的这篇文档看了一遍,基本弄懂了,讲的也挺详细的 https://docs.djangoproject.com/en/1.6/topics/i18n/ 首先是国际化和本地化概念: 1,国际 ...

  9. iOS: 设置App的国际化和本地化

    原文链接:http://www.cocoachina.com/appstore/20160310/15632.html 前言 App的名字设置方式有很多种,如果在App打包上线时不做修改,最终App的 ...

  10. 【转】iOS 设置APP的名称(浅述APP版本国际化与本地化)

    原文网址:http://www.jianshu.com/p/a3a70f0398c4 前言 App的名字设置方式有很多种,如果在App打包上线时不做修改,最终App的名字就是Xcode在建立工程时的名 ...

随机推荐

  1. Codeforces-470 div2 C题

    C. Producing Snow time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  2. 监控工具nmon使用方法

    https://blog.csdn.net/linabc123000/article/details/70833427

  3. ElasticSearch之Health API

    查看当前集群全部健康指标的信息,执行如下命令: curl -X GET "https://localhost:9200/_health_report?pretty" --cacer ...

  4. 微软真是活菩萨,面向初学者的机器学习、数据科学、AI、LLM课程统统免费

    微软真是活菩萨,面向初学者的机器学习.数据科学.AI.LLM课程统统免费 大家好,我是老章 推荐几个质量上乘且完全免费的微软开源课程 面向初学者的机器学习课程 地址:https://microsoft ...

  5. Windows 7更新失败的解决方法

    你好,1.在开始菜单中点击运行,→输入"services.msc"→找到"windows update"右击选择"停止":2.进入C:\wi ...

  6. LeetCode 栈与队列篇(12、155、84、239)

    20. 有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. ...

  7. 如何使用mock应对测试所需随机数据

    摘要:在做接口测试的时候,有的接口需要进行大量的数据进行测试,还不能是重复的数据,这个时候就需要随机生产数据进行测试了.这里教导大家使用mock.js生成各种随机数据. 一.什么是mock.js mo ...

  8. 开启一个 A/B 实验到底有多简单?

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 火山引擎 A/B 测试平台 DataTester 孵化于字节跳动业务内部,在字节跳动,"万事皆 A/B, ...

  9. 一个神奇的Python库:Evidently,机器学习必备

    Evidently 是一个面向数据科学家和机器学习工程师的开源 Python 库.它有助于评估.测试和监控从验证到生产的数据和 ML 模型.它适用于表格.文本数据和嵌入. 简介 Evidently 是 ...

  10. Axure RP 9 下载、破解激活教程、最新激活码,亲测可用

    本教程适用于 Axure RP 9 Enterprise/Pro/Team 的激活.破解,最新激活码,适用于 windows, mac系统,仅用于学习 简介 Axure RP 9.0 破解版是一款功能 ...