WPF实现本地化多语言的几种方式


话不多说,我们直接上源码开干。

1.第一种方式: 使用字典Dictionary.xaml

搭建系统框架,使用MVVM

页面布局方式如下:

<Window x:Class="WPFDemoMVVM.View.LanguageChangeView"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:WPFDemoMVVM.View"
		xmlns:lex="http://wpflocalizeextension.codeplex.com"
		xmlns:lang="clr-namespace:WPFDemoMVVM.Resources"
		mc:Ignorable="d"
		Title="{DynamicResource Home}" Height="300" Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" >
			<TextBlock Text="{DynamicResource Welcome}" FontSize="48"/>

		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
			<Button x:Name="btnEnglish" Tag="en" Content="{DynamicResource English}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button x:Name="btnLanguage" Tag="zh-CN" Content="{DynamicResource Chinese}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button Content="{DynamicResource ShowMessage}" Margin="20" Command="{Binding ShowMessageCommand}" Width="100" Height="30"></Button>
		</StackPanel>
	</Grid>
</Window>

后端ViewModel:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using WPFDemoMVVM.Resources;
using WPFLocalizeExtension.Engine;

namespace WPFDemoMVVM.ViewModel
{
	public partial class LanguageChangeViewModel: ObservableObject
	{

		[RelayCommand]
		private void ChangeLanguage(string languageCode)
		{
			if (string.IsNullOrWhiteSpace(languageCode))
				return;
			// 切换语言资源
			var dict = new ResourceDictionary();
			switch (languageCode)
			{
				case "en":
					dict.Source = new Uri("Language/en_Dictionary.xaml", UriKind.Relative);
					break;
				case "zh-CN":
					dict.Source = new Uri("Language/zh_Dictionary.xaml", UriKind.Relative);
					break;
				default:
					return;
			}
			// 替换 Application 的 Resource
			Application.Current.Resources.MergedDictionaries.Clear();
			Application.Current.Resources.MergedDictionaries.Add(dict);
		}

		[RelayCommand]
		private void ShowMessage()
		{
			MessageBox.Show(Application.Current.TryFindResource("Hello").ToString(), Application.Current.TryFindResource("Prompt").ToString(), MessageBoxButton.OK, MessageBoxImage.Information);
		}
	}
}

新建两个资源文件:en_Dictionary.xaml和zh_Dictionary.xaml

en_Dictionary.xaml如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
					xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                 
					xmlns:sys="clr-namespace:System;assembly=netstandard">
	<sys:String x:Key="Home">Home</sys:String>
	<sys:String x:Key="MenuMsg">Menu Management</sys:String>
	<sys:String x:Key="Welcome">Welcome to you</sys:String>
	<sys:String x:Key="English">English</sys:String>
	<sys:String x:Key="Chinese">Chinese</sys:String>
	<sys:String x:Key="ShowMessage">Show Message</sys:String>
	<sys:String x:Key="Prompt">Prompt</sys:String>
	<sys:String x:Key="Hello">Hello</sys:String>
</ResourceDictionary>

zh_Dictionary.xaml如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
					xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
					xmlns:sys="clr-namespace:System;assembly=netstandard">
	<sys:String x:Key="Home">首页</sys:String>
	<sys:String x:Key="MenuMsg">菜单管理</sys:String>
	<sys:String x:Key="Welcome">欢迎你</sys:String>
	<sys:String x:Key="English">英文</sys:String>
	<sys:String x:Key="Chinese">中文</sys:String>
	<sys:String x:Key="ShowMessage">显示信息</sys:String>
	<sys:String x:Key="Prompt">提示</sys:String>
	<sys:String x:Key="Hello">你好</sys:String>
</ResourceDictionary>

在App.xaml中将资源合并进入项目:

<Application x:Class="WPFDemoMVVM.App"
			 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
			 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
			 xmlns:local="clr-namespace:WPFDemoMVVM"
			 Startup="Application_Startup">
	<Application.Resources>
		<ResourceDictionary>
			<ResourceDictionary.MergedDictionaries>
				<ResourceDictionary Source="pack://application:,,,/WPFDemoMVVM;component/Language/zh_Dictionary.xaml"/>
				<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
				<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
			</ResourceDictionary.MergedDictionaries>
		</ResourceDictionary>
	</Application.Resources>
</Application>

App进程里进行初始化配置:

效果如下图:

2. 第二种方式,使用resx资源文件,实现多语言本地化

新建资源文件Lang.resx和Lang.zh-CN.resx

新建LanguageChangeView页面布局:

<Window x:Class="WPFDemoMVVM.View.LanguageChangeView"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:WPFDemoMVVM.View"
		xmlns:lex="http://wpflocalizeextension.codeplex.com"
		xmlns:lang="clr-namespace:WPFDemoMVVM.Resources"
		mc:Ignorable="d"
		Title="{x:Static lang:Lang.Home}" Height="300" Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" >
			<TextBlock Text="{x:Static lang:Lang.Welcome}" FontSize="48"/>

		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
			<Button x:Name="btnEnglish" Tag="en" Content="{x:Static lang:Lang.English}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button x:Name="btnLanguage" Tag="zh-CN" Content="{x:Static lang:Lang.Chinese}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button Content="{x:Static lang:Lang.ShowMessage}" Margin="20" Command="{Binding ShowMessageCommand}" Width="100" Height="30"></Button>
		</StackPanel>
	</Grid>
</Window>

ViewModel页如下:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using WPFDemoMVVM.Resources;
using WPFLocalizeExtension.Engine;

namespace WPFDemoMVVM.ViewModel
{
	public partial class LanguageChangeViewModel: ObservableObject
	{

		[RelayCommand]
		private void ChangeLanguage(string languageCode)
		{
			//第二种方式切换语言资源
			var culture = new CultureInfo(languageCode);
			Thread.CurrentThread.CurrentCulture = culture;
			Thread.CurrentThread.CurrentUICulture = culture;
		}


		[RelayCommand]
		private void ShowMessage()
		{
			MessageBox.Show(Lang.Hello,Lang.Prompt, MessageBoxButton.OK, MessageBoxImage.Information);
		}
	}
}

3.第三种方式,使用第三方库:wpflocalizeextension,可以实现热重载【推荐使用】

引用三方库:wpflocalizeextension

视图页面LanguageChangeView 如下:
导入命名空间:xmlns:lex=”http://wpflocalizeextension.codeplex.com
使用绑定方式:Text=”{lex:Loc WPFDemoMVVM:Lang:Welcome}”

<Window x:Class="WPFDemoMVVM.View.LanguageChangeView"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:WPFDemoMVVM.View"
		xmlns:lex="http://wpflocalizeextension.codeplex.com"
		xmlns:lang="clr-namespace:WPFDemoMVVM.Resources"
		mc:Ignorable="d"
		Title="{lex:Loc WPFDemoMVVM:Lang:Home}" Height="300" Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" >
			<TextBlock Text="{lex:Loc WPFDemoMVVM:Lang:Welcome}" FontSize="48"/>
		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
			<Button x:Name="btnEnglish" Tag="en" Content="{lex:Loc WPFDemoMVVM:Lang:English}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button x:Name="btnLanguage" Tag="zh-CN" Content="{lex:Loc WPFDemoMVVM:Lang:Chinese}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button Content="{lex:Loc WPFDemoMVVM:Lang:ShowMessage}" Margin="20" Command="{Binding ShowMessageCommand}" Width="150" Height="30"></Button>
		</StackPanel>
	</Grid>
</Window>

或者也可以使用如下的方式,如果整个页面都是引用同一个命名空间下的资源文件:
需要设置
lex:ResxLocalizationProvider.DefaultAssembly=”WPFDemoMVVM”;
lex:ResxLocalizationProvider.DefaultDictionary=”Lang”;

如果需要在设计的时候显示当前的语言的文本可以设置:
lex:LocalizeDictionary.DesignCulture=”zh-CN”

<Window x:Class="WPFDemoMVVM.View.LanguageChangeView"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:WPFDemoMVVM.View"
		xmlns:lex="http://wpflocalizeextension.codeplex.com"
		xmlns:lang="clr-namespace:WPFDemoMVVM.Resources"
		lex:ResxLocalizationProvider.DefaultAssembly="WPFDemoMVVM"
		lex:ResxLocalizationProvider.DefaultDictionary="Lang"
		lex:LocalizeDictionary.DesignCulture="zh-CN"
		mc:Ignorable="d"
		Title="{lex:Loc Home}" Height="300" Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" >
			<TextBlock Text="{lex:Loc Welcome}" FontSize="48"/>
		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
	 <!--<Button x:Name="btnEnglish" Tag="en" Content="{lex:Loc English}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
	 <Button x:Name="btnLanguage" Tag="zh-CN" Content="{lex:Loc Chinese}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>-->
	 <Button x:Name="btnEnglish" Tag="en" Content="{lex:Loc English}" Margin="10" Command="{Binding Source={x:Static lex:LocalizeDictionary.Instance},Path=SetCultureCommand}" CommandParameter="en" Width="100" Height="30"/>
	 <Button x:Name="btnLanguage" Tag="zh-CN" Content="{lex:Loc Chinese}" Margin="10" Command="{Binding Source={x:Static lex:LocalizeDictionary.Instance},Path=SetCultureCommand}" CommandParameter="zh-CN" Width="100" Height="30"/>
			<Button Content="{lex:Loc ShowMessage}" Margin="20" Command="{Binding ShowMessageCommand}" Width="150" Height="30"></Button>
		</StackPanel>
	</Grid>
</Window>

viewModel实现类如下:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using WPFDemoMVVM.Resources;
using WPFLocalizeExtension.Engine;

namespace WPFDemoMVVM.ViewModel
{
	public partial class LanguageChangeViewModel: ObservableObject
	{
		[RelayCommand]
		private void ChangeLanguage(string languageCode)
		{
			////第三种方式切换语言资源
			var culture = new CultureInfo(languageCode);
			Thread.CurrentThread.CurrentCulture = culture;
			Thread.CurrentThread.CurrentUICulture = culture;
			LocalizeDictionary.Instance.Culture = culture;
		}

		[RelayCommand]
		private void ShowMessage()
		{
			MessageBox.Show(Lang.Hello,Lang.Prompt, MessageBoxButton.OK, MessageBoxImage.Information);
		}
	}
}

效果如下:
英文界面:

中文界面:

3.第四种方式,使用第三方库:Antelcat.I18N.WPF,

引入第三方库:Antelcat.I18N.WPF,

然后新建LangKeys类,包装资源文件Lang:

using Antelcat.I18N.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LanguageLibrary.Resources
{
	[ResourceKeysOf(typeof(Lang))]
	public partial class LangKeys
	{
	}    
}

视图页面如下:

<Window x:Class="WPFDemoMVVM.View.LanguageChangeView"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:WPFDemoMVVM.View"
		xmlns:lang="clr-namespace:WPFDemoMVVM.Resources"
		mc:Ignorable="d"
		Title="{I18N {x:Static lang:LangKeys.Home}}" Height="300" Width="600">
	<Grid>
		<Grid.RowDefinitions>
			<RowDefinition/>
			<RowDefinition/>
		</Grid.RowDefinitions>
		<StackPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center" >
			<TextBlock Text="{I18N {x:Static lang:LangKeys.Welcome}}" FontSize="48"/>
		</StackPanel>
		<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
			<Button x:Name="btnEnglish" Tag="en" Content="{I18N {x:Static lang:LangKeys.English}}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button x:Name="btnLanguage" Tag="zh-CN" Content="{I18N {x:Static lang:LangKeys.Chinese}}" Margin="10" Command="{Binding ChangeLanguageCommand}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource Self}}" Width="100" Height="30"/>
			<Button Content="{I18N {x:Static lang:LangKeys.ShowMessage}}" Margin="20" Command="{Binding ShowMessageCommand}" Width="150" Height="30"></Button>
		</StackPanel>
	</Grid>
</Window>

viewmodel类:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using WPFDemoMVVM.Resources;
using WPFLocalizeExtension.Engine;

namespace WPFDemoMVVM.ViewModel
{
	public partial class LanguageChangeViewModel: ObservableObject
	{
		[RelayCommand]
		private void ChangeLanguage(string languageCode)
		{
			////第四种方式换语言资源
			var culture = new CultureInfo(languageCode);
			Thread.CurrentThread.CurrentCulture = culture;
			Thread.CurrentThread.CurrentUICulture = culture;
			I18NExtension.Culture = culture;
		}

		[RelayCommand]
		private void ShowMessage()
		{
			MessageBox.Show(Lang.Hello,Lang.Prompt, MessageBoxButton.OK, MessageBoxImage.Information);
		}
	}
}

效果如下:
英文界面:

中文界面:

源码地址:https://gitee.com/chenshibao/wpfdemo.git

可参考学习开源项目:
WPFLocalizeExtension:https://github.com/XAMLMarkupExtensions/WPFLocalizeExtension
Antelcat.I18N:https://github.com/Antelcat/I18N

如果本文介绍对你有帮助,可以一键四连:点赞+评论+收藏+推荐,谢谢!