This project has moved. For the latest updates, please go here.

[Info] Localization: Localize a WPF Application

Coordinator
Aug 3, 2014 at 3:56 PM
Edited May 14, 2016 at 8:30 PM

This article has been moved to GitHub!


This article describes how a WPF Application can be localized. Please read the post Localization: CurrentCulture vs. CurrentUICulture first because it describes the basics of localization with the .NET Framework.


Display language (CurrentUICulture)

The official way to localize a WPF Application is by parsing the compiled XAML (=> BAML) file to extract the used string resources. Microsoft provides the LocBaml tool that can do the parsing but this tool is after about nearly 10 years still “not production-ready”.

If you use this approach then please keep in mind that it can only localize string resources which are defined within a XAML source file. If you want to localize messages defined in C# code (e.g. validation messages) then it does not work.

An alternative is to use the classic ResX files to localize a WPF Application. The advantages of this approach are:
  • Visual Studio comes with a Designer to edit the resource (ResX) files.
  • This approach is used by other technologies as well (e.g. ASP .NET, Windows Forms, Console Applications).
  • It can be used everywhere (e.g. in XAML, in C#).
  • It comes with an intelligent fallback mechanism if the user’s language is not supported.
How to use a ResX file in a WPF Application?
  1. Create a Resource (ResX) file in your project or you can reuse the Properties/Resources.resx file.
  2. In the Visual Studio Resource designer you have to change the Access Modifier from Internal to Public. This can be found in the top toolbar of the designer.
  3. Add the namespace to your XAML View:
xmlns:p="clr-namespace:Waf.Writer.Presentation.Properties"
  1. The Resources can be accessed via the x:Static markup extension of XAML:
Header="{x:Static p:Resources.NewMenu}"
Formatting settings (CurrentCulture)

The second part of this article describes how a WPF application can be configured to respect the Windows Format settings.

Note: Other technologies (e.g. ASP .NET, Windows Forms, Console Applications) use the Windows Format settings (CurrentCulture) by default. Only WPF needs to be configured first.

WPF uses always the culture setting “en-US” for formatting and parsing of values when Binding is used. It is possible to override this setting with the following statement:
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), 
    new FrameworkPropertyMetadata(
        XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

However, we can pass only the IETF Language Tag. This way all custom settings the user might have configured in the Windows Format settings are lost because only the language tag is passed.

I stumbled over a lot PCs where the user has modified the default Windows Format settings. But just with setting of the IETF language it is not possible to give the user the expected user experience. If you have the same issue then you might have a look at this Microsoft Connect bug entry.


Further readings
  1. MSDN: WPF Globalization and Localization Overview
Aug 14, 2014 at 8:01 PM
There is actually a bit more work required - not every element inherits FrameworkElement. The following solution:
Private Shared Sub SetXamlBindingLanguage()

    '' For correct regional settings in WPF (e.g. system decimal / dot or comma) 
    Dim lang = System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TextElement), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(DefinitionBase), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocumentSequence), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FlowDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TableColumn), New FrameworkPropertyMetadata(lang))
    FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement), New FrameworkPropertyMetadata(lang))

End Sub
As described in an answer from the following Stack Overflow question: http://stackoverflow.com/questions/520115/stringformat-localization-problem/24994689#24994689. (The answer has not been accepted, but from my testing at least works for elements such as <Run>.

Of course, that is VB.NET code, but simple enough to convert over.