U:调整调用方式和兼容性
This commit is contained in:
1 parent
433e206d45
commit
4ec76b7855
50 files changed
+5592
-47
No files matched your search
@@ -0,0 +1,278 @@
|
||||
# 05 - 国际化(i18n)示例
|
||||
|
||||
演示如何使用 Sharp.Wpf 的国际化功能实现多语言支持,包括运行时切换语言、资源文件管理等。
|
||||
|
||||
## 🎯 学习目标
|
||||
|
||||
- 使用 `ILocalizationService` 实现多语言
|
||||
- 在 XAML 中使用 `{loc:Localize}` 绑定本地化字符串
|
||||
- 运行时动态切换语言
|
||||
- 管理资源文件(.resx)
|
||||
- 格式化带参数的本地化字符串
|
||||
|
||||
## 📦 使用的模块
|
||||
|
||||
- **Sharp.Wpf** - ILocalizationService, LocalizeExtension
|
||||
|
||||
## 🚀 快速运行
|
||||
|
||||
```bash
|
||||
cd examples/05-Localization
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## 📝 核心代码讲解
|
||||
|
||||
### 1. 创建资源文件
|
||||
|
||||
```
|
||||
Resources/
|
||||
├── Strings.resx # 默认语言(中文)
|
||||
├── Strings.en-US.resx # 英文
|
||||
└── Strings.ja-JP.resx # 日文(可选)
|
||||
```
|
||||
|
||||
**Strings.resx** (中文):
|
||||
```xml
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>欢迎使用 Sharp 框架</value>
|
||||
</data>
|
||||
<data name="Username" xml:space="preserve">
|
||||
<value>用户名</value>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
<value>密码</value>
|
||||
</data>
|
||||
<data name="Login" xml:space="preserve">
|
||||
<value>登录</value>
|
||||
</data>
|
||||
<data name="WelcomeUser" xml:space="preserve">
|
||||
<value>欢迎, {0}!</value>
|
||||
</data>
|
||||
```
|
||||
|
||||
**Strings.en-US.resx** (英文):
|
||||
```xml
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>Welcome to Sharp Framework</value>
|
||||
</data>
|
||||
<data name="Username" xml:space="preserve">
|
||||
<value>Username</value>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="Login" xml:space="preserve">
|
||||
<value>Login</value>
|
||||
</data>
|
||||
<data name="WelcomeUser" xml:space="preserve">
|
||||
<value>Welcome, {0}!</value>
|
||||
</data>
|
||||
```
|
||||
|
||||
### 2. App.xaml.cs - 注册国际化服务
|
||||
|
||||
```csharp
|
||||
using System.Globalization;
|
||||
using System.Resources;
|
||||
using Wpf.Localization;
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddSharpWpf();
|
||||
|
||||
// 添加国际化支持
|
||||
var resourceManager = new ResourceManager(
|
||||
"LocalizationExample.Resources.Strings", // 资源文件的完整命名空间
|
||||
Assembly.GetExecutingAssembly());
|
||||
|
||||
services.AddLocalization(
|
||||
resourceManager,
|
||||
new CultureInfo("zh-CN"), // 中文
|
||||
new CultureInfo("en-US"), // 英文
|
||||
new CultureInfo("ja-JP") // 日文
|
||||
);
|
||||
|
||||
services.AddViewModel<MainViewModel>();
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
var mainWindow = provider.GetRequiredService<MainWindow>();
|
||||
mainWindow.Show();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MainViewModel.cs - 语言切换
|
||||
|
||||
```csharp
|
||||
using Wpf.Localization;
|
||||
|
||||
public class MainViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ILocalizationService _localization;
|
||||
private readonly IDialogService _dialogService;
|
||||
|
||||
public ILocalizationService Localization => _localization;
|
||||
|
||||
public List<CultureInfo> AvailableLanguages { get; }
|
||||
|
||||
public CultureInfo CurrentLanguage
|
||||
{
|
||||
get => _localization.CurrentCulture;
|
||||
set
|
||||
{
|
||||
_localization.ChangeCulture(value);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ChangeLanguageCommand { get; }
|
||||
public ICommand ShowGreetingCommand { get; }
|
||||
|
||||
public MainViewModel(
|
||||
ILocalizationService localization,
|
||||
IDialogService dialogService)
|
||||
{
|
||||
_localization = localization;
|
||||
_dialogService = dialogService;
|
||||
|
||||
AvailableLanguages = localization.GetSupportedCultures().ToList();
|
||||
|
||||
// 监听语言变化
|
||||
_localization.CultureChanged += (s, culture) =>
|
||||
{
|
||||
_dialogService.ShowMessage(
|
||||
$"语言已切换到: {culture.NativeName}",
|
||||
"提示");
|
||||
};
|
||||
|
||||
ChangeLanguageCommand = new RelayCommand<CultureInfo>(culture =>
|
||||
{
|
||||
if (culture != null)
|
||||
{
|
||||
CurrentLanguage = culture;
|
||||
}
|
||||
});
|
||||
|
||||
ShowGreetingCommand = new RelayCommand(() =>
|
||||
{
|
||||
// 使用格式化字符串
|
||||
var message = _localization.GetString("WelcomeUser", "张三");
|
||||
_dialogService.ShowMessage(message, "问候");
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. MainWindow.xaml - 使用本地化绑定
|
||||
|
||||
```xml
|
||||
<Window x:Class="LocalizationExample.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:loc="clr-namespace:Wpf.Localization;assembly=Sharp.Wpf"
|
||||
Title="国际化示例" Height="400" Width="500">
|
||||
<StackPanel Margin="20">
|
||||
<!-- 方式1: 使用 LocalizeExtension(推荐) -->
|
||||
<TextBlock Text="{loc:Localize Welcome}" FontSize="24" FontWeight="Bold"/>
|
||||
|
||||
<!-- 语言选择 -->
|
||||
<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
|
||||
<TextBlock Text="选择语言:" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
||||
<ComboBox ItemsSource="{Binding AvailableLanguages}"
|
||||
SelectedItem="{Binding CurrentLanguage}"
|
||||
DisplayMemberPath="NativeName"
|
||||
Width="150"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<StackPanel Margin="0,30,0,0">
|
||||
<!-- 用户名 -->
|
||||
<TextBlock Text="{loc:Localize Username}"/>
|
||||
<TextBox Margin="0,5,0,15"/>
|
||||
|
||||
<!-- 密码 -->
|
||||
<TextBlock Text="{loc:Localize Password}"/>
|
||||
<PasswordBox Margin="0,5,0,15"/>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<Button Content="{loc:Localize Login}"
|
||||
Height="35" FontSize="14"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 方式2: 直接绑定 Localization 服务 -->
|
||||
<StackPanel Margin="0,30,0,0">
|
||||
<TextBlock Text="{Binding Localization[Welcome]}" FontStyle="Italic"/>
|
||||
<TextBlock Text="{Binding Localization[Username]}" Margin="0,5,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 测试格式化字符串 -->
|
||||
<Button Content="显示问候" Command="{Binding ShowGreetingCommand}" Margin="0,20,0,0"/>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
```
|
||||
|
||||
### 5. 在代码中使用本地化
|
||||
|
||||
```csharp
|
||||
// 方式1: 通过服务获取
|
||||
var welcomeText = _localization.GetString("Welcome");
|
||||
|
||||
// 方式2: 带格式化参数
|
||||
var greeting = _localization.GetString("WelcomeUser", username);
|
||||
|
||||
// 方式3: 索引器(用于绑定)
|
||||
var password = _localization["Password"];
|
||||
```
|
||||
|
||||
## 🎓 练习建议
|
||||
|
||||
### 练习1:添加更多语言
|
||||
添加法语(fr-FR)或德语(de-DE)资源文件。
|
||||
|
||||
### 练习2:保存语言偏好
|
||||
将用户选择的语言保存到配置文件,下次启动时自动加载。
|
||||
|
||||
### 练习3:动态加载资源
|
||||
实现从外部 JSON 文件加载翻译资源(而非编译进程序)。
|
||||
|
||||
### 练习4:翻译进度显示
|
||||
显示每种语言的翻译完成度(如:英文 95%,日文 60%)。
|
||||
|
||||
## 💡 常见问题
|
||||
|
||||
**Q: 资源文件修改后不生效?**
|
||||
A: 确保:
|
||||
1. 资源文件的"生成操作"设为"嵌入的资源"
|
||||
2. 重新生成项目(Clean + Rebuild)
|
||||
|
||||
**Q: 如何支持从右到左(RTL)语言?**
|
||||
A: 监听 CultureChanged 事件,设置 `FlowDirection`:
|
||||
```csharp
|
||||
_localization.CultureChanged += (s, culture) => {
|
||||
if (culture.TextInfo.IsRightToLeft) {
|
||||
Application.Current.MainWindow.FlowDirection = FlowDirection.RightToLeft;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Q: 能否热重载资源文件?**
|
||||
A: Sharp.Wpf 当前使用编译时嵌入资源,不支持运行时重载。可以使用外部 JSON 文件实现热重载。
|
||||
|
||||
**Q: 如何处理复数形式?**
|
||||
A: 使用不同的资源键或使用占位符:
|
||||
```
|
||||
"{Count} items" → "{0} 个项目"
|
||||
```
|
||||
|
||||
## 📚 延伸阅读
|
||||
|
||||
- [.NET 资源文件](https://learn.microsoft.com/zh-cn/dotnet/core/extensions/resources)
|
||||
- [CultureInfo 类](https://learn.microsoft.com/zh-cn/dotnet/api/system.globalization.cultureinfo)
|
||||
- [WPF 本地化](https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/globalization-for-wpf)
|
||||
- 下一个示例:[06-Theming](../06-Theming/README.md)
|
||||
|
||||
---
|
||||
|
||||
**构建面向全球用户的应用!** 🌍
|
||||
Reference in new issue
Block a user