There are many ways to tackle localization in WPF and Silverlight, but a lot of them lack necessary features, aren’t flexible or they’re overcomplicated and difficult to implement. I wanted to come up with a simple, lightweight solution that could be implemented easily and fit naturally into the MVVM paradigm.

Here are my key goals:

Build on top of the native resx resource system

Ability to bind my UI elements to the localized resources in a way that follows the MVVM pattern

Ability to change the current culture on the fly and have the resource values updated automatically

Option to inject overrides for specific resources and cultures at runtime

Ability to retrieve a resource value in code that honors the same culture-changing and override injection functionality

Download the solution here to follow along.





Getting Started

The first thing you’ll need to do is create the resx files that we’ll build on top of. My main resource file is called MainWindowResources.resx. Open up the file in Visual Studio, and at the top of the page change the Access Modifier to Public. This controls the underlying C# class that Visual Studio creates to expose properties for the resource keys in this file. We’ll need these to be public in order to use them for binding later on. The next step is creating locale-specific versions of the resource file. These files will follow the specific naming conventions needed for the built-in .Net localization mechanisms. If you’re unfamiliar with how .Net handles this, I’d recommend reading through this article. For the sake of this sample, I’ll create a version of this file for the UK and call it MainWindowResources.en-GB.resx.

Note: in Silverlight, you’ll need to edit your .csproj file to specify the cultures to support. To do this, right-click on your Silverlight project and choose Unload Project. Right-click on the unloaded project and choose Edit projectName.csproj. Find the <SupportedCultures> tag and fill in the culture codes you want to support. You should end up with something like this: <SupportedCultures>en-GB</SupportedCultures>.

Application Culture

In order to allow the selected language to be changed at runtime, we need a mechanism to monitor and update the current culture. The ApplicationCulture class exposes a property of type CultureInfo for this. Setting this property to a new value will cause the CultureChanged event to be raised. We’ll use this event later on to listen for changes and allow the UI to update automatically.

ApplicationCulture.Instance.CurrentCulture = new CultureInfo("en-GB");

MVVM Support

For my project I wanted to be able to incorporate an object in my view model that contained all my resource strings. I wanted to be able to bind to these strings the same way I would to any other property on a view model, and not have to consume it as a separate static resource in XAML. These resource values also need to automatically update when the application’s culture is changed. The classes that Visual Studio auto-generates for each resource file will allow you to bind to them. The problem is that the properties are read-only and therefore don’t have support for property change notifications when the application culture is updated.

I added support for property change notifications by creating a wrapper class called ResourceLibrary, which allows you to pass in an instance of a resource class (such as MainWindowResources). The ResourceLibrary exposes the object you passed in as a property called Resource. This allows you to bind to any of the resource keys on that object. ResourceLibrary also subscribes to the CultureChanged event I mentioned above. When the culture changes, the ResourceLibrary will raise a property changed notification on the Resource property which will trigger all the bindings to update their values.

Using the ResourceLibrary wrapper in your project is fairly straightforward. You’ll need to create a new resource “model” class that inherits from the ResourceLibrary.

public class MainWindowResourceLibrary : ResourceLibrary<MainWindowResources>

Next, add a property to your view model that is of type MainWindowResourceLibrary. Your view can now bind to your resources, and will be notified when the current culture changes!

private MainWindowResourceLibrary _localizedStrings; public MainWindowResourceLibrary LocalizedStrings { get { return _localizedStrings; } }

<TextBlock Text="{Binding Path=LocalizedStrings.Resource.FirstName}" />

Resource Overrides

I’ll admit this might be a bit of a niche feature, but it’s something that has come up more than once on projects I’ve worked on in the past. The general idea is that you normally want to use all the default resources that are defined in your resx files, but on occasion you might want to show a different value based on some contextual criteria. This could be something like customer-specific labels in a multi-tenant solution, or a different value based on the user’s role.

The overrides functionality revolves around the interface IResourceOverrideProvider. This exposes the basic functions that an override provider needs to implement in order for the ResourceLibrary to work with it. I’ve included a basic implementation of this in the ResourceOverrides class. This just keeps an internal dictionary of overridden resource keys and values. You can either override this class to add extra functionality if you need, or you can create your own completely separate implementation as long as you follow the IResourceOverrideProvider contract.

To pass the overrides into the ResourceLibrary, we’ll simply update our resource model to accept an instance of a resource override provider and pass it along to the base class. This will allow you to determine at the view model level whether or not you want to pass in overrides for a particular scenario, as well as how the overrides list is populated. This piece of the solution is very flexible, so you can definitely tweak this to suit your specific needs.

Earlier I talked about how to incorporate your resource model into your view model, and bind directly to the resource keys contained in that model. Unfortunately this doesn’t quite allow for overrides to be injected into that same binding path. As I mentioned above, the properties on the auto-generated resource class are read-only. This means we need an alternate method of getting a resource value that allows checking for an override. The ResourceLibrary class exposes a method called GetString(“resourceKey”) that was created for this purpose. This method lets you pass in the resource key and get back the value based on the current culture, but also checks to see if there are any overrides that match the resource key you provided. If a match is found, the override value is returned instead of the normal resource value.

To maintain our MVVM support with resource overrides, we’ll have to expose new properties on our resource model. The properties will follow the same names as the resource keys. In the property getter, you’ll just make a call to the GetString(“resourceKey”) method and pass in the matching resource key. Now just update the binding on your view to point to this new property, and that’s it.

public string Title { get { return GetString("Title"); } } <TextBlock Text="{Binding Path=LocalizedStrings.Title}" />

This GetString() method can be used anywhere in your code to get the value for a resource key based on the current culture as well as any overrides that were injected. This can be very useful for things like localized error messages.

Conclusion

The attached solution contains the library project with all the base classes you’ll need. I’ve also included sample projects for both WPF and Silverlight to demonstrate how you can use this for your own projects.

Feel free to use or modify the code for your own needs. If you have any questions or suggestions, leave a comment below and I will gladly help you out.

Thanks for reading!

Download the solution.