In my working with Windows Store apps, I’ve become increasingly fond/aware of the advantages for app localization. There are a lot of resources out there for you to localize your app using a good-better-best approach as well. I’ve previously written about localizing a Windows Store app using some of these methods and what the WinRT platform supports to make this easier in most cases.
Now that you’ve localized your app, you may be faced with the question of how you might want to respond to language choice changes by the user. Remember that the Windows Store app model is that it honors the user’s language choice preferences matching that with the available languages the app indicates it supports. This may not always map to the user’s installed OS language. For instance I can have an English OS install but prefer German in my apps and set my language preference to: de-DE, en-US. If a Windows Store app was localized in German, then I would see that version instead of English because my preferences say so, regardless of my OS install.
Language switching problem
Now, I’m not as proficient in German as I’d like to be, so there may be times where I need to flip back to English to understand certain areas of an app. I can do this easily by going to the languages panel and switching my order of preference:
But when I go back to my app, it is still in German…until I terminate/restart the app. Let’s say I started the app and it honors my language preference:
Now I go and change back to English and click the button to take me to page 2. It is still in German even though my language preference list is now: en-US; de-DE.
The XAML framework doesn’t automatically re-evaluate the resource cache in response to these changes. This is something the developer has to manage and luckily there are some easy steps you can do to make this experience better for your users.
We should point out that this is likely a rare case that a user of your app is constantly switching languages and switching back to your app, but having your app support this is a delighter for your users when it does happen.
Solution: listening to qualifier updates
There are APIs to the rescue here! When you switch your language preferences, the system actually is aware of it, however the context that your app already had at launched has been cached…and thus it will still be delivering the original context-aware resources. Good for us is that the APIs can let us know when this happens and we can respond.
Since most apps have only a single Window object and since this change is likely rare, we should manage this call and not put it on every Page load, for example, but rather higher up in the App because it will likely be rare that it happens. In our activation code path we can listen for the resource context to change
1: protected override void OnLaunched(LaunchActivatedEventArgs args)
4: ResourceManager.Current.DefaultContext.QualifierValues.MapChanged += QualifierValues_MapChanged;
In this snippet we are using the default ResourceContext and listening for when its qualifier map changes. The qualifier map is the set of context for resources like language, but also scale, phonetics (for Japanese), high contrast, etc. Once that map changes we can force a refresh of the cache essentially:
1: void QualifierValues_MapChanged(IObservableMap<string, string> sender, IMapChangedEventArgs<string> @event)
This simple flow basically says “hey, when a qualifier has changed, reset the context map so that I get the new data” and our app in subsequent calls to the resources will get the updated resources.
Here’s a video demonstrating the completed before/after approach.
There is a big caveat to this approach. The change doesn’t automatically affect your current view. So your page has rendered and is in German. If I go and change it to English, then go back to my page…it isn’t automatically in English. Subsequent view loads (and even going back to this page) will get the new resources, but already-rendered ones do not. The developer can, of course, implement way more logic to refresh the view, traverse the tree, etc. to manage this, but that experience is up to the app developer to determine what is most appropriate for the app itself.
This is a little subtle but helpful tip in enabling your localized apps to be flexible to these types of changes by users when that happens.
Hope this helps!