How to realize the internationalization and localization of WPF Prism Module?

How to realize the internationalization and localization of WPF Prism Module?

English | Simplified Chinese

The previous article briefly introduced the internationalization of the main project, implemented using the resource dictionary (XAML).
In the past few days, I added several Prism modules (Module), and found that the submodules use resource dictionaries to achieve internationalization and localization. It is not easy to do. I did not find a good reference article, so I changed the way to use resource files. Achieved.

Put WPF project on the international route

1. Overview of this article

Requirements for internationalization and localization of submodules:

    1. Each module needs to have its own separate language file.
    1. When dynamically switching languages ​​in the main project, submodules also need to be switched.
    1. Prism is used to implement the modular framework, which requires that the main project and each submodule cannot have a reference relationship, that is, loose coupling, and the language file of the submodule cannot be directly switched in the main project.

Based on the above requirements, I tried to define a language file (XAML) in each module. When the main form switches languages, the language file of the module always prompts that there is no corresponding resource dictionary file. I am annoyed. Still refer to the "Accelerider.Windows" internationalization method, using resource files to achieve localization and internationalization, and not entangled with the Xaml way, alas.

This road doesn't work, I'll go another way

The following is the modified effect:

Similar to the previous version:

    1. There is no change in the internationalization of the title bar, but the text binding has changed in a different way to achieve the same effect.
    1. Three sub-modules (Home \ Client \ Server) are added on the left, which are dynamically loaded by Prism, and the language is switched according to the main project main window language switch.

The following is a brief introduction to how to create a module, and how to do the main form and module internationalization. It is really a very simple introduction. You can pull the code to see the specific implementation.

Fall to, get up and continue to pit

Second, add three Prism modules (Module)

You can install the Prism template to quickly create a module project. Of course, it is also possible to manually create a .Net Core project, which is just a few more steps (you need to install Prism.Wpf package (7.2.0.1422) with Nuget). Quickly created.

2.1 Preparations before creating the module

VS2019 download Prism template

Download the Prism template searched in the picture above, restart VS, it will be automatically installed, when creating a new project, there is a Prism module template selected:

Prism template engineering

Pay attention to choose the version of .NET Core 3, because I use the WPF project created by .NET Core.

2.2 Create a module

The following is a screenshot of the three module projects that have been created:

The current organization of the three module files is similar:

  • I18nResources: Resources folder, put 3 language resource files and a T4 template file (used to reference the language Key), of which the T4 template file is defined in the 3 modules and the main project, the specific can be downloaded from github to view the source code.
  • Views place view files, and now only use the TabItem view displayed in the main form of the main project, namely MainTabItem.xaml, inherited from TabItem.
  • xxxxModule.cs: prism template definition file, used by prism discovery module.

The key points of the three modules need to be noted:

    1. Edit the module project file and modify the module file output directory:
// 省略部分代码,下面这一行设置为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. In the XXXModule, you need to add the ResourceManager reference of the resource file to another library to save it. You need to use it when you want to switch languages. For example, add the code in the constructor of HomeModule as follows, just add this sentence of code, the internationalization and localization of the module Even if it's done:
I18nManager.Instance.Add(TerminalMACS.Home.I18nResources.UiResource.ResourceManager);
    1. The view "MainTabItem" to "RegionNames.MainTabRegion" is registered in the RegisterTypes method of XXXModule. The main form uses the "RegionNames.MainTabRegion" associated module view to display and load.
_regionManager.RegisterViewWithRegion(RegionNames.MainTabRegion, typeof(MainTabItem));
    1. International control text binding for UI controls, an open source library namespace used by markup, links will be given later, this project directly loads the library into the solution; i18NResources: Language is the class generated by the T4 template file, associated text The translated key. The code of the binding text is as follows:
<TextBlock Grid.Row="2" Text="{markup:I18n {x:Static i18NResources:Language.MainTabItm_Header}}"

3. The main project

The main project directory is organized as follows:

3.1 Dynamic loading of Prism module

The key code for configuring and loading three modules is in the App.xaml.cs file. Looking at the above code, I output the three modules to the Modules directory. The main project can directly load this directory. Other loading methods also use configuration files. Wait, you can refer to the official example of Prism, the link is given at the end of the article:

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

The main form displays the TabItem view registered by the submodule. Prism: RegionManager.RegionName is the region string registered in each submodule. It is associated with the TabItem view corresponding to the module. The code is as follows:

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

The main form displays the submodule view in the form of TabControl controls:

TabItem view of submodule

If the main project can load submodules normally, the project file of the main project also needs to modify its output directory:

// 省略部分代码,下面这一行设置为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 Modify language file format

Deleted the original XAML language file and replaced it with the resource file of resx, which is similar to the resource file type of the three modules. The following is the resource file of the main project:

Use resource files as language files

Replaced with resource files, editing is more convenient than XAML files. At first, it was considered to use resource files to achieve internationalization. I wanted to try XAML files.

Tossing can be upright

3.3 The core code of language switching

The key code for dynamically switching languages ​​is changed to:

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;
}

The core language switching code is the last sentence. I won't go into details. There are libraries and source code in the solution:

I18nManager.Instance.CurrentUICulture = culture;

Four. Source code

on

5. Reference materials

Guess you like

Origin www.cnblogs.com/Dotnet9-com/p/12742046.html