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:
ResourceLoader 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:
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:
ResourceLoader 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.
var languages = Windows.System.UserProfile.GlobalizationPreferences.Languages; string preferredLanguage = languages.ToList();
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
- 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:
myImageControl.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:
To automatically respond to a user changing language (cos that happens every day), there is an event that you can subscribe to.
var 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