WPF 应用程序本地化-资源文件方式
WPF 应用程序需要本地化处理的时候,有多种方法,这里只对原始的方式即资源文件方式实现本地化作为简单介绍,加强学习和备忘,其他方法原理类似。
1.要实现本地化,首先添加资源文件,在资源文件中添加需要实现本地化的字段(这些繁琐的活可以交给GitHub Copilot 或其他AI辅助工具干)
省下来的时间认真检查以下或者前期好好规划以下UI显示元素的命名规则和标准,不要中英文混写,拼音英文混写,或者一会拼音一会英文。
2.本地化应用
ResourceManager rm=new ResourceManager("WpfApp4.Resources.Strings",Assembly.GetExecutingAssembly()); //实例化资源读取对象,读取资源内容
CultureInfo culture=new CultureInfo("en-US");//根据名称指定区域性初始化实例的显示内容,如果不指定,默认当前操作系统设置的区域语言
System.Threading.Thread.CurrentThread.CurrentUICulture=culture; //获取或设置当前资源管理器使用当前区域性以便在运行时查找区域性特定的资源(即资源文件和其对应的属性)
3.通过MVVM方式对UI显示元素进行绑定,以便便于处理,当然也可以通过其他方式,可能比较费事
如:this.Title=rm.GetString("MainWindowTitle",CultureInfo.CultureUICulture)
下面以具体示例做说明:
- UI 界面 xaml
<Window x:Class="WpfApp4.MainWindow"
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:WpfApp4"
xmlns:vm="clr-namespace:WpfApp4.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<vm:MainViewModel x:Name="vm"/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel x:Name="sp1" Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Tag="LabelId" Text="Id" Margin="10 0"/>
<TextBlock Text="{Binding Student.Id}" Width="80"/>
<TextBlock Tag="LabelName" Text="Name" Margin="10 0"/>
<TextBlock Text="{Binding Student.Name}" Width="80"/>
<TextBlock Tag="LabelAge" Text="Age" Margin="10 0"/>
<TextBlock Text="{Binding Student.Age}" Width="80"/>
<TextBlock Text="{Binding Title}" Width="120" Margin="20 0" />
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center">
<TextBox FontSize="20" Text="{Binding Student.Id, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Width="120" Margin="10 0"/>
<TextBox FontSize="20" Text="{Binding Student.Name, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Width="120" Margin="10 0"/>
<TextBox FontSize="20" Text="{Binding Student.Age, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Width="120" Margin="10 0"/>
<TextBox Text="{Binding Title,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Width="120" VerticalAlignment="Center"/>
<Button x:Name="btnLoad" Content="加载" Width="80" Height="30" Margin="10 0" Command="{Binding LoadCommand}" />
</StackPanel>
<DataGrid x:Name="dg" ItemsSource="{Binding Courses}" Grid.Row="3" Margin="5" AutoGenerateColumns="False"
CanUserAddRows="False" AlternatingRowBackground="SkyBlue"
AlternationCount="2"
>
<DataGrid.Columns>
<DataGridTextColumn Header="课程编号" Binding="{Binding Id}" Width="*"/>
<DataGridTextColumn Header="课程名称" Binding="{Binding Name}" Width="*"/>
<DataGridTextColumn Header="辅导员" Binding="{Binding Teacher}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<!--课程信息-->
<StackPanel x:Name="sp2" Grid.Row="2" Orientation="Horizontal" Margin="5" >
<TextBlock Tag="LabelCourseId" Text="课程编号:" VerticalAlignment="Center"/>
<TextBox x:Name="tbId" Text="{Binding Course.Id}" Width="80" VerticalAlignment="Center" />
<TextBlock Tag="LabelCourseName" Text="课程名称:" Margin="10 0" VerticalAlignment="Center"/>
<TextBox x:Name="tbName" Text="{Binding Course.Name}" Width="120" VerticalAlignment="Center" />
<TextBlock Tag="LabelTeacher" Text="辅导员:" Margin="10 0" VerticalAlignment="Center"/>
<TextBox x:Name="tbTeacher" Text="{Binding Course.Teacher}" Width="120" VerticalAlignment="Center" />
<Button x:Name="btnAdd" Content="添加" Width="80" Height="30" Margin="10 0" Command="{Binding AddCourseCommand}" CommandParameter="{Binding Course}" />
</StackPanel>
</Grid>
</Window>
- Code CS
using CommunityToolkit.Mvvm;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp4.ViewModels;
namespace WpfApp4
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
ResourceManager rm = new ResourceManager("WpfApp4.Resources.Strings", Assembly.GetExecutingAssembly());
private MainViewModel main;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
ApplyLocalization();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
main = this.DataContext as MainViewModel;
if (main != null)
{
main.Student = new Models.Student
{
Id = 1,
Name = "张三",
Age = 20,
Address = "北京市"
};
main.Title = rm.GetString("MainWindowTitle", CultureInfo.CurrentUICulture) ?? "主窗口";
}
ApplyLocalizedText();
}
private void ApplyLocalizedText()
{
this.Title = main?.Title ?? this.Title;
foreach (var child in sp1.Children)
{
if (child is TextBlock tb)
{
if (tb.Tag == null || tb.Tag.ToString() == "") { continue; }
tb.Text = rm.GetString($"{tb.Tag.ToString()}", CultureInfo.CurrentUICulture);
}
}
foreach (var child in sp2.Children)
{
if (child is TextBlock tb)
{
if (tb.Tag == null || tb.Tag.ToString() == "") { continue; }
tb.Text = rm.GetString($"{tb.Tag.ToString()}", CultureInfo.CurrentUICulture);
}
}
btnLoad.Content = rm.GetString("ButtonLoad", CultureInfo.CurrentUICulture) ?? "加载";
btnAdd.Content = rm.GetString("ButtonAddCourse", CultureInfo.CurrentUICulture) ?? "添加";
}
private void ApplyLocalization()
{
// 设置当前线程的 UI 语言(可根据需要切换)
// CultureInfo culture = CultureInfo.CurrentUICulture;
// 示例:CultureInfo culture = new CultureInfo("en-US");
CultureInfo culture = new CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
ApplyLocalizedText();
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
ApplyLocalizedText();
}
}
}
- 效果