Click here to Skip to main content
15,307,242 members
Articles / Desktop Programming / WPF
Posted 9 Oct 2008


87 bookmarked

Simple WPF Localization

Rate me:
Please Sign up or sign in to vote.
4.84/5 (28 votes)
9 Jul 2009CPOL7 min read
An article on how to easily and effectively fully localize a WPF application.


After searching the Internet for a while on how to localize a WPF application, I found two very nice solutions which can be found here and here. However, both solutions looked too complicated to me, and I decided to implement a solution that will just do what I need with simplicity and effectiveness.

My solution by far does not have the features of the above solutions, but it still does its job perfectly: to localize the text in my project.


The basic goals are:

  • Easy to use localization that allows localizing the XAML directly during design time
  • Use of embedded resources
  • The language can be changed at runtime
  • Ability to see the localized resources in the designer of Visual Studio
  • The implementation to be as simple as possible and to not introduce performance issues

Easy to Use

To reach the first goal, I borrowed the great idea from the other two solutions to use a WPF extension. Extensions can be used directly in XAML to assign values to properties, and are extremely useful for the purpose.

For example, the localization of a TextBlock in XAML would look like this:

<TextBlock Text="{Loc Text_Hello}"/>

Use Embedded Resources

The second goal can be reached by connecting a resource manager to the localization component.

When you create a WPF application in Visual Studio, Visual Studio creates a Resources.resx file in the Properties folder of the project. Because this looks like a perfect location to put all your localizable resources in, I chose to attach the localization component to this resource file by default. This is the same resource file you normally access by using the Properties.Resources.MyResourceName expressions in your code-behind.

For flexibility, an arbitrary resource manager can be explicitly connected to the localization component at any time. This will also cause all of the localized content to be updated with the new values.

Design Time Support

Design time support is limited only to the default culture (i.e., the resources you put in the Properties/Resources.resx file). This means you can see any localized resource rendered in the designer but only those you have put in the mentioned file. Any culture specific resource you put in additional resource files (like will not be visible during design time unless you temporarily rename the files to see your changes. If you find any simple solution to this problem, please let me know.

Design Time Issues

As simple as the code is, you may have some issues during design time, like you may not see your recent changes or you may not see any localized resources at all.

The first issue is easily solved by recompiling the project which causes Visual Studio to reload the main assembly of the project and then to refresh the designer area.

The second issue is more subtle.

At runtime, the default resource file is easily found by obtaining the main entry assembly of the application and creating a resource manager that references the file. But this does not work during design time because an assembly is deemed to be the entry assembly of an application only if the application has either been started by it or by the AppDomain.ExecuteAssembly method (refer to the documentation of the System.Windows.Application.ResourceAssembly property for more information). Therefore, the localization component uses the following procedure to try to find the main assembly of the application during design time: obtain the list of all assemblies loaded in the current domain and search for the first assembly that contains both the Main method and a MyAssemblyName.App class that derives directly or indirectly from System.Windows.Application. If the component finds such an assembly, it creates a resource manager connected to the MyAssemblyName.Properties.Resources resource file of the assembly.

If you have the above issue during design time, you can directly load the assembly of your application by replacing some of the code in the LocalizationManager.GetResourceManager class with code similar to Assembly.Load("MyassemblyName") and use it as the resource assembly.

The third and the fourth goals are strictly an implementation issue and are not covered in this article. The only thing I would mention is that the implementation consists of only two very simple classes and does not add any performance penalty to your application.

Using the Code

To use the solution, you need to do the following:

  1. Add a reference to the WPFLocalization assembly, or better - include the two source code files into one of your class library projects that accompany your applications. The second solution is better because having a library that consists of only two classes adds cost to your application.
  2. If you choose to include the two source code files in your application, note the following:

    1. I advise you to add the classes in one of your class libraries instead of to the main application project as you may have design time issues every time there are any compilation errors (i.e., Visual Studio may fail to load the assembly and raise an error in the designer).
    2. If you change the name of the namespace from "WPFLocalization" to something else, you have to make the same change on the second argument of the System.Windows.Markup.XmlnsDefinition assembly attributes at the beginning of the LocExtension.cs file.
  3. Extract all your localizable resources for the default culture and put them into the Properties/Resources.resx file. Of course, you can place the resources in a resource file anywhere else as well, but this will break the design time support unless you make changes to the code.
  4. For every additional culture, add a corresponding resource file to the Properties folder (e.g., Properties/ and create a localized version of the resources.

  5. Use the localization extension in XAML to reference the resources.

While steps 1 and 2 are straightforward, step 3 needs additional explanation.

Using the Localization Extension

To use the localization extension, you simply need to apply it in XAML on the properties you want to localize, similar to the following code:

<TextBlock Text="{Loc MyResourceKey}"/>  

MyResourceKey is the name of the resource in the Properties/Resources.resx file you want to reference.

To use formatting, use code like:

<TextBlock Text="{Loc CreatorName, Format='Created by {0}'}"/>  

You do not have to add any namespace references (like xmlns:loc="...") at the beginning of the XAML file, because the extension registers to the default Microsoft namespaces at startup (another idea I have borrowed from one of the other solutions).


I have not tested the extension with images and I have no idea if it will work. Handling images most probably requires additional effort and is something I have not planned.

Missing Resources

If a resource you reference is not found, then the following applies:

  • If the application is a debug version, the resource is substituted by the text "[Resource: ResourceKey]".
  • If the application is a release version, the resource is substituted by an empty string.

Changing the Current Culture at Runtime

The current culture can be changed during runtime at any moment by assigning a value to the LocalizationManager.UICulture property. A change to the property does the following:

  1. Changes the UI culture of the current thread to the specified culture (i.e., assigns the value to Thread.CurrentThread.CurrentUICulture).
  2. Updates all the properties localized by the extension.

Using a Different Resource Manager

To use a different resource manager, simply assign a value to the LocalizationManager.ResourceManager property. Assigning a value will also update the localized properties.


Any comments and/or suggestions are welcome.


  • 2008-10-10: Initial version.
  • 2008-11-28: Added support for templates.

Updated Version

  • 2009-07-10: Added support for non-dependency properties (i.e., standard properties) to support the Microsoft.Windows.Controls.Ribbon control.
  • 2009-07-10: If a resource is not found during design time, an ArgumentOutOfRangeException exception is thrown instead of showing a [Resource: ResourceKey] message. This makes missing resources easier to spot.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Jecho Jekov
Software Developer (Senior)
Bulgaria Bulgaria
No Biography provided

Comments and Discussions

GeneralRe: Thank you! but... Pin
bartolomeus826-Jul-09 22:43
Memberbartolomeus826-Jul-09 22:43 
GeneralRe: Thank you! but... Pin
Jecho Jekov8-Jul-09 4:37
MemberJecho Jekov8-Jul-09 4:37 
GeneralRe: Thank you! but... Pin
asdf2009-910-Jul-09 9:42
Memberasdf2009-910-Jul-09 9:42 
GeneralRe: Thank you! but... Pin
asdf2009-910-Jul-09 10:47
Memberasdf2009-910-Jul-09 10:47 
QuestionUse in styles? Pin
Michel Renaud1-May-09 8:09
MemberMichel Renaud1-May-09 8:09 
AnswerRe: Use in styles? Pin
Jecho Jekov2-May-09 4:23
MemberJecho Jekov2-May-09 4:23 
GeneralRe: Use in styles? Pin
Michel Renaud4-May-09 5:41
MemberMichel Renaud4-May-09 5:41 
GeneralGood article, but i know a better localization way Pin
SeriousM11-Apr-09 8:21
MemberSeriousM11-Apr-09 8:21 

Nice to see your article, but have a look at[^], because i think it is more useable for larger projects in productive systems.

best regards!
GeneralIt is applicable to Silverlight Pin
deBaires10-Apr-09 11:19
MemberdeBaires10-Apr-09 11:19 
GeneralRe: It is applicable to Silverlight Pin
Jecho Jekov14-Apr-09 8:14
MemberJecho Jekov14-Apr-09 8:14 
Questionhow to use it with Microsoft.Windows.Controls.Ribbon Pin
vvidov22-Mar-09 21:21
Membervvidov22-Mar-09 21:21 
AnswerRe: how to use it with Microsoft.Windows.Controls.Ribbon Pin
Jecho Jekov24-Mar-09 5:41
MemberJecho Jekov24-Mar-09 5:41 
GeneralRe: how to use it with Microsoft.Windows.Controls.Ribbon Pin
vvidov26-Mar-09 23:00
Membervvidov26-Mar-09 23:00 
GeneralRe: how to use it with Microsoft.Windows.Controls.Ribbon Pin
Jecho Jekov26-Mar-09 23:46
MemberJecho Jekov26-Mar-09 23:46 
GeneralProblem in Blend Pin
Carlos Gravato17-Mar-09 0:59
MemberCarlos Gravato17-Mar-09 0:59 
GeneralRe: Problem in Blend Pin
Jecho Jekov17-Mar-09 3:09
MemberJecho Jekov17-Mar-09 3:09 
GeneralRe: Problem in Blend Pin
Carlos Gravato17-Mar-09 4:54
MemberCarlos Gravato17-Mar-09 4:54 
GeneralRe: Problem in Blend Pin
Jecho Jekov18-Mar-09 0:11
MemberJecho Jekov18-Mar-09 0:11 
Questiondependency property bind to an object property Pin
youpili13-Mar-09 4:41
Memberyoupili13-Mar-09 4:41 
AnswerRe: dependency property bind to an object property Pin
Jecho Jekov17-Mar-09 3:04
MemberJecho Jekov17-Mar-09 3:04 
GeneralRe: dependency property bind to an object property Pin
youpili17-Mar-09 4:45
Memberyoupili17-Mar-09 4:45 
GeneralRe: dependency property bind to an object property Pin
Jecho Jekov18-Mar-09 0:23
MemberJecho Jekov18-Mar-09 0:23 
GeneralRe: dependency property bind to an object property Pin
youpili19-Mar-09 9:25
Memberyoupili19-Mar-09 9:25 
QuestionWhat about non Dependency Property? [modified] Pin
Inner Swirl9-Mar-09 10:46
MemberInner Swirl9-Mar-09 10:46 
AnswerRe: What about non Dependency Property? Pin
Jecho Jekov11-Mar-09 1:21
MemberJecho Jekov11-Mar-09 1:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.