Programmatically changing UI language in Windows Phone

By | September 13, 2014

If you’ve done globally-focused development on Windows Phone, you already know that to change the display language, you have to do so in the Settings area of the phone, then reboot the emulator (or physical device) for the change to take effect.

What a pain. Wouldn’t it be better to change the UI language on-demand? Not to mention provide end users the ability to do so within your app as an added convenience. In this blog post, I’ll show you just how to make that happen.

If you haven’t already, check out my blog post on localizing your app – this is obviously the first step. Get some resource strings in other languages defined for the elements of your application.

Now that you’ve got your app all wired up with some added languages, if even machine generated, let’s get to making it on-the-fly switchable.

Let’s have a look at some tweaks to the default phone project created for Windows Phone 8.0 (and 8.1 Silverlight):

First, take a look at LocalizedStrings. This is the class that your text elements are (hopefully) already binging to in order to pull the resource from your RESX file.

Tweak it as follows:

   1: public class LocalizedStrings : INotifyPropertyChanged
   2: {
   3:     private static AppResources _localizedResources = new AppResources();
   5:     public AppResources LocalizedResources { get { return _localizedResources; } }
   7:     internal void ChangeCulture(string cultureName)
   8:     {
   9:         AppResources.Culture = new System.Globalization.CultureInfo(cultureName);
  11:         OnPropertyChanged("LocalizedResources");
  12:     }
  14:     public event PropertyChangedEventHandler PropertyChanged;
  15:     void OnPropertyChanged([CallerMemberName]string propertyName = "")
  16:     {
  17:         if (this.PropertyChanged != null)
  18:         {
  19:             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  20:         }
  21:     }
  22: }

That is, make it inherit from INotifyPropertyChanged, add the ChangeCulture and OnPropertyChanged methods.

The trick we’re exploiting here is the binding to LocalizedStrings that’s being done in your XAML when you create a localized app. It’s XAML. So when it creates a binding, it wires up PropertyChanged if the source object supports it. So we’re making LocalizedStrings support it. We’ll utilize this in a minute.

Now have a look at your XAML. Something like this I imagine:

   1: <TextBlock HorizontalAlignment="Left"
   2:            TextWrapping="Wrap"
   3:            Text="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.testString, Mode=OneWay}"
   4:            VerticalAlignment="Top"
   5:            Margin="22,10,0,0" />

Since Path is hitting the LocalizedResources property of the LocalizedStrings object, this is all we need to fire a PropertyChanged event for when we want the strings to update!

So, in my app I’ve got an INotifyPropertyChanged ViewModel that reacts to a CurrentCulture string property when it’s set as follows:

   1: private string _currentLanguage;
   2: public string CurrentLanguage
   3: {
   4:     get
   5:     {
   6:         return _currentLanguage;
   7:     }
   8:     set
   9:     {
  10:         if (_currentLanguage != value)
  11:         {
  12:             _currentLanguage = value;
  13:             OnPropertyChanged();
  15:             ChangeUICulture(_currentLanguage);
  16:         }
  17:     }
  18: }

So yeah, it updates the property’s value, but then calls another method. Let’s take a look at that dude:

   1: private void ChangeUICulture(string currentLanguage)
   2: {
   3:     ((LocalizedStrings)App.Current.Resources["LocalizedStrings"]).ChangeCulture(currentLanguage);
   4: }

And boom. We get the LocalizedStrings instance out of our App’s Resources (put there automatically as part of the project template) and call our new ChangeCulture method on it. If you don’t have your localized strings class in your app resources, just add this to App.xaml:

   1: <Application.Resources>
   2:     <local:LocalizedStrings xmlns:local="clr-namespace:PhoneApp1" x:Key="LocalizedStrings"/>
   3: </Application.Resources>

Now watch as the magic cascades string change events to all bound controls when you call our new method on LocalizedStrings!