19

I have a WPF application (in English) and I would like to let users to select different languages. I have read some possibilities to change languages in runtime applications, but I only want to choose a language during installation time and never change it.

Do you think the fastest and easiest way to do it is developing different versions of the program (changing only text language) and let the user to select one of them during the installation?? Probably to repeat code only changing textbox or labels is not very elegant, but notice that I have the application finished in English and I don´t need to change language at runtime.

akjoshi
  • 15,374
  • 13
  • 103
  • 121
Carlos Alba Zamanillo
  • 1,271
  • 1
  • 9
  • 11

4 Answers4

43

You can follow these steps:

  1. Creating the resource files

    Add this file StringResources.xaml to Resources directory. Here is an example:

    <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">
    
         <system:String x:Key="close">Close</system:String>
    </ResourceDictionary>
    

    You can create several files, one for each language.

  2. Adding the resource (Call this when you start your application)

    private void SetLanguageDictionary()
    {
         ResourceDictionary dict = new ResourceDictionary();
         switch (Thread.CurrentThread.CurrentCulture.ToString())
         { 
           case "en-US":
             dict.Source = new Uri("..\\Resources\\StringResources.xaml", UriKind.Relative);
             break;
           case "fr-CA":
             dict.Source = new Uri("..\\Resources\\StringResources.fr-CA.xaml", UriKind.Relative);
             break;
           default :
             dict.Source = new Uri("..\\Resources\\StringResources.xaml",UriKind.Relative);
             break;
         }
         this.Resources.MergedDictionaries.Add(dict);
    }
    
  3. Using the Resource, like this -

    <Button      
       x:Name="btnLogin"
       Click="btnLogin_Click"
       Content="{DynamicResource close}"
       Grid.Row="3"
       Grid.Column="0" 
       Padding="10" />
    

Source: https://www.codeproject.com/Articles/123460/Simplest-Way-to-Implement-Multilingual-WPF-Applica

Quasimodo
  • 57
  • 1
  • 13
Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51
  • Very useful when storing all text in a database. Thank you! – BendEg Jan 12 '15 at 07:48
  • 2
    source: http://www.codeproject.com/Articles/123460/Simplest-Way-to-Implement-Multilingual-WPF-Applica – Nick Oct 14 '16 at 16:29
  • The dynamic ressource is not resolved at design time. So in my opinion that is a drawback of this solution. – DrMarbuse Sep 29 '17 at 10:44
  • I tried this solution, it works but I've got a warning error that sayd impossible to resolve the resource login, I've tried to rebuild, clean the solution, restart VS, still get this warning. Do I have to declare my resources somewhere like app.xaml, or is there something I forgot to do ? – Steeven_b Oct 17 '17 at 14:37
  • @Steeven_b - The example needs a minor update probably. It defines a string resource called "close" in step 1, but then attempts to locate and use a resource named "login" in step 3. – Mitselplik Oct 24 '18 at 16:46
  • There should be a Remove operation before adding, otherwise when this function is called multiple times, there will be more and more items in MergedDictionaries – Hanabi May 10 '22 at 06:02
  • `var existedDict = Resources.MergedDictionaries.Where(d => d.Source.OriginalString == dict.Source.OriginalString).FirstOrDefault(); if (existedDict != null) { Resources.MergedDictionaries.Remove(existedDict); }` – Hanabi May 10 '22 at 06:02
8

I think the solution proposed by Aghilas is good; but you can use StaticResource instead of using DynamicResource in step 3, DynamicResource is not required in your case as you are not going to chnage the language while application is running.

Also have a look at these articles having details about using Resx files for localization in WPF -

Localizing a WPF Application with ResX Files

WPF Localization

WPF Localization Guidance - Whitepaper

akjoshi
  • 15,374
  • 13
  • 103
  • 121
5

Just to improve @AghilasYakoub's correct answer, I think I need to point out that the following code should be added to the file App.xaml apart from what he had said:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/StringResources.xaml"/>
            <ResourceDictionary Source="Resources/StringResources.fr-CA.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
  • 3
    I am a little confused as to why you feel statically defining the resource dictionaries to merge is needed to improve Aghilas answer? The last line of code of the method defined in step 2 should ensure that the correct resource dictionary is added to the list of merged dictionaries should it not? this.Resources.MergedDictionaries.Add(dict); – Mitselplik Oct 24 '18 at 16:49
1

If you want to use RESX files instead of resource dictionaries, you can do it easily with static references in XAML.

<Window x:Class="MyApp.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:res="clr-namespace:MyApp.Resources">
    <Button Text="{x:Static res:MainWindow.MyTestKey}">
</Window>

In the Resource folder is the MainWindow.resx, MainWindow.de.resx, etc. and every file contains a key MyTestKey with a translation.

Martin Braun
  • 10,906
  • 9
  • 64
  • 105