Localization #2: Instant language switching

In the first post of this sequence, I explained how to design a Windows Phone App that shows localized string values, depending on the currently selected device language. One common problem of that solution is that it only checks the phone’s language during App startup – you might want to provide your users with an option to change the App’s display language without the need to change the global phone settings and restart the App.

In principle, its quite easy to change an App’s language settings at runtime – this does require only one line in code:

 
Thread.CurrentThread.CurrentUICulture = new CultureInfo(LANGUAGE_CODE); 

The LANGUAGE_CODE passed to the CultureInfo constructor is a string value that represents either a 2-character language code (e.g., en, fr, de, …) or a 5-character culture code (e.g., en-US, de-DE, …)

Unfortunately, if you call this line anywhere in your App, it seems that nothing happens. First if you navigate to a new page, this new page will react to the language change and display all its localized content in the new language. To implement an instant language update that forces the currently active page to update all of its content, we need to notify the page that something has changed and parts of the page need to be re-drawn.

In pratice, this only requires a few additional lines of code inside the LocalizedStrings class. Make sure that this helper class inherits from INotifyPropertyChanged and fire the PropertyChanged event as soon as the language has changed. This way, all pages that reference the LocalizedStrings resource will be notified and update themselves.

public class LocalizedStrings : INotifyPropertyChanged
{
	private static AppResources _localizedResources = new AppResources();
	public AppResources LocalizedResources { get { return _localizedResources; } }
	
	// Update language code:
	public event PropertyChangedEventHandler PropertyChanged;
	public void RefreshLanguage()
	{
		if (PropertyChanged != null)
		  PropertyChanged(this, new PropertyChangedEventArgs("LocalizedResources"));
	}
}

(Of course, if you use some kind of MVVM framework that provides a base Viewmodel class that inherits from INotifyPropertyChanged and handles the PropertyChanged event logic, you can instead derive LocalizedStrings from this base Viewmodel.)

The only thing left to do is actually change the language and call the newly added functionality. Assuming that LocalizedStrings was defined as static resource within App.xaml, this is done in a few more lines of C# code:

Thread.CurrentThread.CurrentUICulture = new CultureInfo(LANGUAGE_CODE);
LocalizedStrings localizedStrings = Application.Current.Resources["LocalizedStrings"] as LocalizedStrings;
if (localizedStrings != null)
	localizedStrings.RefreshLanguage();

An example:

To create a quick-and-dirty test project, create a ListBox that allows the user to switch between all available languages:

<ListBox SelectionChanged="LanguageList_OnSelectionChanged">
	<ListBoxItem>en</ListBoxItem>
	<ListBoxItem>fr</ListBoxItem>
	<ListBoxItem>de</ListBoxItem>
</ListBox>

In the SelectionChanged event handler, retrieve the selected language, set it as App language and notify the page of the changes:

private void LanguageList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
	// Retrieve new language
	ListBox languageList = sender as ListBox;
	ListBoxItem languageItem = languageList.SelectedItem as ListBoxItem;
	string newLanguage = languageItem.Content as string;

	// Change language
	Thread.CurrentThread.CurrentUICulture = new CultureInfo(newLanguage);
	LocalizedStrings localizedStrings = Application.Current.Resources["LocalizedStrings"] as LocalizedStrings;
	if (localizedStrings != null)
		localizedStrings.RefreshLanguage();
}

Of course, in a “real-life” App you’ll store the language the user chose in IsolatedStorage, and retrieve and re-set it on the next App startup by changing the CurrentThread‘s CurrentUICulture in the App.xaml’s constructor, as shown above.