Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multilanguage in WPF [closed]

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.

like image 664
Jonathan Avatar asked May 02 '09 10:05

Jonathan


3 Answers

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);  } 
like image 182
Andre van Heerwaarde Avatar answered Oct 06 '22 00:10

Andre van Heerwaarde


I am using the WPF Localization Extension. It is a really easy way to localize any type of DependencyProperty on DependencyObjects.

  • is in a real stable state
  • supports binding-like writing style like Text = {LocText ResAssembly:ResFile:ResKey}
  • works with the .resx-fallback mechanism (e.g. en-us -> en -> independent culture)
  • supports culture forcing (e.g. "this has to be English all the time")
  • works with normal dependency properties
  • works with control templates
  • can be used in XAML (really :P) without any additional namespaces
  • can be used in code behind to bind localized values to dynamic generated controls
  • implements INotifyPropertyChanged for advanced use
  • supports string formatting e.g. "this is the '{0}' value"
  • supports prefix and suffix values (currently with LocText extension)
  • is in use in productive systems (like my public relation product)
  • switching of the language to runtime affects NO timeslice
  • can be used with any resource file (.resx) across all assemblies (also the dynamic loaded one at runtime)
  • doesn't need any initializing process (like "call xyz to register a special localize dictionary")
  • is available at design-time (MS Expression Blend, MS Visual Studio 2008 (Normal and SP1)
  • change of the chosen language is possible at design-time
  • can localize any type of data type, as long as a converter (TypeConverter) for it exists (extends LocalizeExtension)
  • has built in support for Text, upper Text, lower Text, Images, Brushes, Double and Thickness
  • doesn't affects any memory leaks
  • leaves the UID property untouched
  • offers a SpecificCulture to use as IFormatProvider (e.g. (123.20).ToString(LocalizeDictionary.SpecificCulture) = "123.20" or "123,20")
  • offers some functionality to check and get resource values in code behind
  • doesn't alter the culture on Thread.CurrentCulture or Thread.CurrentUICulture (can be changed easily)
like image 23
CSharper Avatar answered Oct 06 '22 01:10

CSharper


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.

like image 23
Wilka Avatar answered Oct 06 '22 01:10

Wilka