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 DependencyObjects.
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, Images, Brushes, 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