WPF: How to change the CurrentUICulture at runtime

If you have resource files, e.g.:

  • Resources.resx
  • Resources.hu-hu.resx

... and want to change the localization at runtime,

... and do not want to mess with additional resource dictionaries and recoding all UI localizations,

it will work with the

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

But it will not change the already shown window's language.

To achieve that, more coding is required - the Application lifecycle must be managed, instead of the default.

First, remove the StartupUri from App.xaml:

<Application
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="ADUI.App"
         xmlns:System="clr-namespace:System;assembly=mscorlib" >
     <!--StartupUri="wndMain.xaml">-->
<Application.Resources>
</Application.Resources>

Second, implement a class, which is now responsible for the application lifecycle:

public class LocApp: Application
{
    [STAThread]
    public static void Main()
    {
        App app = new App();
        app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
        wndMain wnd = new wndMain();
        wnd.Closed += Wnd_Closed;
        app.Run(wnd);
    }

    private static void Wnd_Closed(object sender, EventArgs e)
    {
        wndMain wnd = sender as wndMain;
        if (!string.IsNullOrEmpty(wnd.LangSwitch))
        {
            string lang = wnd.LangSwitch;

            wnd.Closed -= Wnd_Closed;

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

            wnd = new wndMain();
            wnd.Closed += Wnd_Closed;
            wnd.Show();
        }
        else
        {
            App.Current.Shutdown();
        }
    }
}

Do not forget to change the startup object on your Project properties / Application page to LocApp!

Finally, implement some code which switches the languages in the main window's code:

public partial class wndMain : Window
{
    public string LangSwitch { get; private set; } = null;

    // ... blah, blah, blah

    private void tbEn_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        LangSwitch = "en";
        Close();
    }

    private void tbHu_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        LangSwitch = "hu-hu";
        Close();
    }

    // ... blah, blah, blah

}

Make sure, that the provided localization code matches with one of the resx file language code ("hu-hu" in this example)!

This solution will close and reopen the main window, with the chosen language, and will exit if the main window closed by other means.


What am I missing?

You changed the culture registered with the thread, and String.Format will use this now, but you need to reload all localized items in the WPF hierarchy.

WPF Localization – On-the-fly Language Selection has more information.

Tags:

C#

.Net

Vb.Net

Wpf