你能推荐一个好的方式来实现WPF应用程序的多语言系统吗?我现在使用的方法涉及XML、类和XAML扩展。它在大多数情况下都运行良好,但当我必须处理动态标签或一般的动态文本时,它需要额外的努力。我希望让程序员只在主要问题上工作,并忘记语言问题。
你能推荐一个好的方式来实现WPF应用程序的多语言系统吗?我现在使用的方法涉及XML、类和XAML扩展。它在大多数情况下都运行良好,但当我必须处理动态标签或一般的动态文本时,它需要额外的努力。我希望让程序员只在主要问题上工作,并忘记语言问题。
按照以下步骤进行操作:
1) 将所有String
片段放在单独的资源文件中。
例如:StringResources.xaml
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- String resource that can be localized -->
<system:String x:Key="All_Vehicles">All Vehicles</system:String>
</ResourceDictionary>
2) 为每种语言创建副本,并将它们(翻译后的副本)添加到合并的字典中。别忘了加上国家的 ISO 代码,以便更方便地处理。
例如: App.xaml
:
<Application x:Class="WpfStringTables.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="StringResources.de-DE.xaml" />
<ResourceDictionary Source="StringResources.nl-NL.xaml" />
<ResourceDictionary Source="StringResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
将使用最后一个包含字符串的资源文件替换代码中的文本部分。
3a) 使用 String
表中的文本部分:
示例:Window1.xaml
:
<Window x:Class="WpfStringTables.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Margin="51,82,108,129" Name="AllVehiclesButton"
Content="{StaticResource All_Vehicles}"/>
</Grid>
</Window>
3b) 从代码中加载资源(仅在不想通过 XAML
设置时使用此代码):
void PageLoad()
{
string str = FindResource("All_Vehicles").ToString();
}
4) 在应用程序启动时切换到新的文化:
App.xaml.cs
中的代码片段:
public static void SelectCulture(string culture)
{
if (String.IsNullOrEmpty(culture))
return;
//Copy all MergedDictionarys into a auxiliar list.
var dictionaryList = Application.Current.Resources.MergedDictionaries.ToList();
//Search for the specified culture.
string requestedCulture = string.Format("StringResources.{0}.xaml", culture);
var resourceDictionary = dictionaryList.
FirstOrDefault(d => d.Source.OriginalString == requestedCulture);
if (resourceDictionary == null)
{
//If not found, select our default language.
requestedCulture = "StringResources.xaml";
resourceDictionary = dictionaryList.
FirstOrDefault(d => d.Source.OriginalString == requestedCulture);
}
//If we have the requested resource, remove it from the list and place at the end.
//Then this language will be our string table to use.
if (resourceDictionary != null)
{
Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
}
//Inform the threads of the new culture.
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
}
我正在使用WPF本地化扩展。这是一种非常简单的方法,可以将DependencyObject
上的任何类型的DependencyProperty
本地化。
Text = {LocText ResAssembly:ResFile:ResKey}
INotifyPropertyChanged
以进行高级用途"this is the '{0}' value"
LocText
扩展) .resx
)一起使用,跨所有程序集(包括运行时动态加载的程序集)TypeConverter
)(扩展了LocalizeExtension
)Text
、大写Text
、小写Text
、Image
、Brush
、Double
和Thickness
的支持UID
属性不变SpecificCulture
用作IFormatProvider
(例如,(123.20).ToString(LocalizeDictionary.SpecificCulture) = "123.20"
或者"123,20"
)Thread.CurrentCulture
或者Thread.CurrentUICulture
(可以轻松更改)Josh Smith撰写了一篇深入教程,介绍了他的首选方法:在WPF中创建国际化向导。
这可能会指向一个大的重新设计(它是一个MVVM解决方案),但出于其他原因使用MVVM似乎也是值得的。
{StaticResource resKey}
使应用程序在运行时可切换。 - Nam G VU