Resources (.resw) and ResourceLoader in .Net for Metro Style Apps

This post is part of a series of ‘Lessons Learnt’ from  a recent conversion of Microsoft.Practices.Prism to Net Metro Prism. See here for related posts

In Metro there is a whole new improved mechanism for dealing with resources and localization. Its quite powerful; allowing one to embed text, images  and even Resource-Dictionaries that can vary from one locality to another.

If you’re used to Resource.resx files (for specific language/culture);  then you may be surprised to find its not an option with Metro Apps.  Instead the new file type is a Resource.resw that allows one to enter String Resources.

A quick web search of this new resource file gave me the wrong impression of how to do localization in Metro. Many forums commented on the lack of the usual auto generated code to access resources. Most suggested avoiding ResourceManager and using ResourceLoader. Others commented that embedding localized image resources in metro is not supported.

It true that the new preferred way of loading resources is using the ResourceLoader class

A number of code snippets show the following code:

1ResourceLoader rl = new ResourceLoader("MyAssembly/Resources"); string localizedString = rl.GetString("MyLocalizedStringKey");  

This code will access any resources you add to “MyAssembly/Resources.resw”   

….but I was left a little confused. How do I know the path to specify for my Resource file?   How can I swap between different languages using this? I also wanted to know how to change images based on the current language of the user.

Fortunately I kept looking and came across this 3 part blog post, Part 1, Part 2and Part 3 – that do an excellent job of explaining it all.

Basically you organise you’re solution so that it contains folders for specific language codes. For example:

image

You add a resources.resw into each folder and put the appropriate language variants in each

You simply create an instance of ResourceLoader without passing a specific resource file into the ctor:

1ResourceLoader rl = new ResourceLoader(); string localizedString = rl.GetString("MyLocalizedStringKey");

And voila, you app will magically have the correct language based on your windows language settings. (To understand the magic, read Part 2and Part 3)

You can access the current User’s language choice using Windows.System.UserProfile.GlobalizationPreferences.Languages. This returns the list of language choices (a user can have a order (or fallback) of preferred languages). The most preferred language is first in the list.

1var languages = Windows.System.UserProfile.GlobalizationPreferences.Languages; string preferredLanguage = languages.ToList()\[0\];

Images (and other Assets) work in exactly the same manner. Just name a folder after the language code you’re catering for and add similar resources into it. See below

image

Note:

  • Do use an appropriate language code (en-GB, fr-FR)
  • Do use a consistent name for assets in each language folder (flag)
  • Do remember case sensitivity (it has to be consistent)

Now to use my localised flag.png file I simply use the following line of code:

1myImageControl.Source = new BitmapImage(new Uri(@"ms-appx:/Assets/flag.png"));

Notice that I do not refer to a specific file in my application; simply the assets folder.

Also notice the use of ms-appx: – In metro you cannot use relative Uri to a resource – it must be absolute. ms-appx:  is equivalent of using [packagename]

So now I could vary my application based on the users preferred language. As the user changes between English (en-GB) and French (fr-FR) language, the application automatically updates the greeting and the  flag displayed:

image

image

To automatically respond to a user changing language (cos that happens every day), there is an event that you can subscribe to.

1var manager = Windows.ApplicationModel.Resources.Core.ResourceManager.Current; manager.DefaultContext.QualifierValues.MapChanged += QualifierValues\_MapChanged;

If anyone wants the source code for this app; then let me know and I’ll make it available