I must admit that I have been fairly lucky when it comes to having to localise applications, in fact most of the times it has been a fairly academic discussion for me. Anyway, last week I got interested in resources and in particular understanding what has been done in Whidbey to better support localisation scenarios.

In the current shipping version of VS.NET doing localisation can be a little tedious because you need to do some out-of-band build steps to produce the various satellite assemblies. I was pleasantly surprised to find that Microsoft had tackled this issue head on and come up with an elegant design, code and build time experience.

Design Time

Root component designers (e.g. Form, UserControl and Component designers) now have "Localizable" and "Language" properties which seems to be provided by a built-in extender provider. When you flick localisation on in the root designer it persists relevant properties to resource files. There is one resource file per component per language plus the default or fall back resources, so for Form1.cs in your project, you might see something like this.

If you look closely at the source generated in the InitializeComponent method of the Form1.Designer.cs source file you will see that when the form is initialised it creates an instance of a ComponentResourceManager. A ComponentResourceManager is derived from ResourceManager and defines an additional method called ApplyResources.

Calls to this method are serialised into InitializeComponent method as follows:

resources.ApplyResources(this.m_OKButton, "m_OKButton");

So what ApplyResources does is spin over the properties of the component and looks in the resource set associated with it to determine what it should be set to. The side effect of this is that not only can you set things like "Text" to be something different, but also completely change the layout of the screen which has long been a difficultly (as I understand it) when localising UI layouts. Neat!

Build Time

So all of these design time enhancements are basically useless if what you do is suck all of those resources into one big assembly. If you have to support a lot of languages then you're executable would be un-usably huge.

This is where the second great localisation enhancement comes in to play. Due in part (I suspect) to the build-time enhancements in Whidbey (namely MSBuild) there is first class support for satellite resource assemblies, however, don't expect to go and create an assembly called "MyApp.en-US" or anything kludgey like that.

Instead, what Microsoft has done is automate the satellite assembly creation so that when you build a project localised resource files it goes and spits out sub-directories (e.g. de-DE, en-AU and zh-CHS) with the satellite assemblies right there for you.

What about Code Time?

A few other general enhancements have been made to resource editing. Firstly when you crack open a resource file you are now given a very clean interface which lets you manage those resources in category sets.

  • Strings
  • Images
  • Icons
  • Audio
  • Files
  • Other

If you expand out the Properties node under a project you will see that there is a Resources.resx file. This is just a normal RESX file, but it has a Custom Tool associated with it (look under the file properties for the file) called "ResXFileCodeGenerator". This creates a strongly-typed wrapper around the resources allowing you to write code like:

this.m_LogoBox = MyApp.Properties.Resources.CompanyLogo;

Which would return an Image instance which had been ripped out of one of the assemblies resource streams. It may not be immediately obvious how you can localise this particular resource file, but if you create a RESX file in the root of the project named something like "Resources.en-AU.resx" and then drag it into the Properties folder then you can also do localisation on the resources there.

Clear as mud? Hopefully it gets a little bit more obvious with a context menu that says something like "Add Language . . ." or something like that.