Can you recommend a good way to implement a Multilanguage system for a WPF app? The method I'm using right now involves XML, classes and a xaml extension. It Works fine in most of cases, but when I have to deal with dynamic labels or dynamic text in general it require some extra effort. I would like to let the programmer working only in the main problem and forgot the lang issues.
Follow these steps:
1) Place all String
fragments in a separate resource file.
Example: 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) Make copies for each language and add them (translated) to the merged dictionaries. Don't forget to add the country's ISO code to make things easier.
Example 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>
The last resource file with strings will be used to replace text parts in code.
3a) Use the text parts from the String
table:
Example 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) Load the resource from code (Only use this code if you don't want to set via XAML
):
void PageLoad() { string str = FindResource("All_Vehicles").ToString(); }
4) Switch to new culture at start of application:
Codesnippet from 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); }
I am using the WPF Localization Extension. It is a really easy way to localize any type of DependencyProperty
on DependencyObject
s.
Text = {LocText ResAssembly:ResFile:ResKey}
INotifyPropertyChanged
for advanced use"this is the '{0}' value"
LocText
extension) .resx
) across all assemblies (also the dynamic loaded one at runtime) TypeConverter
) for it exists (extends LocalizeExtension
) Text
, upper Text
, lower Text
, Image
s, Brush
es, Double
and Thickness
UID
property untouched SpecificCulture
to use as IFormatProvider
(e.g. (123.20).ToString(LocalizeDictionary.SpecificCulture) = "123.20"
or "123,20"
) Thread.CurrentCulture
or Thread.CurrentUICulture
(can be changed easily)Josh Smith wrote an in-depth tutorial about his preferred method for this: Creating an Internationalized Wizard in WPF.
It might point you towards a big redesign (it's a MVVM solution), but using MVVM seems worth it for other reasons as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With