Localizing a WPF program using C#

See also the article about localizing an ASP.NET system here.

See also my video about localizing an ASP.NET system here.

These days when you are designing a GUI (Graphical User Interface) one of the many topics to discuss is that of localization. Simply, localization means that local date format, currency and language will be supported within the program. If you write the program with an intention to deploy to Germany, China and the United States, you need to support the differences in the 3 cultures.

image

In the table above you can see the differences in the date format, currency and language. A well designed program will support all the culture specific attributes dynamically. The 3 WPF windows below are a single XAML window file that uses different resource files to change the Window Title, the Labels and the Button text at runtime.

image

There are a few ways to implement localization into a WPF program. In this example I will use RESX files, as it is the approach I like the best.

After you have created your new WPF project, open the Resources.resx file and add the below. You will find the Resources.resx file Properties directory inside your solution explorer.

image

  • Create a Button – ButtonSubmit, where the text will be Submit.
  • Create a Label – LabelAddress, where the text will be Address.
  • Create a Label – LabelFirstName, where the text to be First Name.
  • Create a Label – LabelLastName, where the text will be Last Name.
  • Set the title of the window to User Information.

The Resources.resx is your default Resource file. You will need to create 3 additional Resources files for this example, one for English, German and Chinese. All 3 need to be moved into the Properties directory and named like in the below picture.

image

Resources.de-DE.resx file will look like this:

image

Resource.en-US.resx will look like this:

image

Resource.zh-CN.resx will look like this:

image

It is very important to make these resource files Public. There is a drop-down list at the top of the window when you are editing the file. Make sure it shows Public. This approach will not work is the access modifier is set to Internal.

Within the Window tag of your XAML window file, add the following line of code.

[sourcecode language="xml" padlinenumbers="true"]
xmlns:properties="clr-namespace:YourAssemblyName.Properties"
[/sourcecode]

For each control within our grid (Button, Labels and Window Title) we will not set the Title or Content values to static text. Instead we will set it to use the resources file value.

[sourcecode language="xml"]
…Title="{x:Static properties:Resources.WindowTitle}"…
<Label Content="{x:Static properties:Resources.LabelFirstName}"…
<Button Content="{x:Static properties:Resources.ButtonSubmit}"…
[/sourcecode]

I don’t like to hardcode values into the my source code. Simply, because if the value needs to change you have to make the code change, rebuild the components and redeploy the program. To avoid this, I always place settings in the App.config or the Web.Config files when there is a chance they would/could change. This goes for setting the culture in this example. I add the below into the App.config file.

[sourcecode language="xml"]
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="Culture" value="de-DE" />
  </appSettings>
</configuration>
[/sourcecode]

If you try to run this example on your computer, you can change the value to de-DE, en-EN or zh-CN to see the windows change language. If you want, you can also modify the project and add a new resource file for another language, then modify the value to the language you just created.

The last step is to set the culture of the program. You do this by adding the below code to the MainWindow() method, before the InitializeComponent() method is executed.

[sourcecode language="xml"]
Properties.Resources.Culture = new
        CultureInfo(ConfigurationManager.AppSettings["Culture"]);
[/sourcecode]

You will need to add System.Configuration to your references in order to access the ConfigurationManager to function. I have found that simply adding the namespace to the class file with using is not enough.

Download the source




Leave a Comment

Your email address will not be published.