Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: How to change the CurrentUICulture at runtime

Tags:

c#

.net

vb.net

wpf

I am trying to change the language my WPF app uses in a click event but it doesn't change.

private void menuItemGerman_Click(object sender, RoutedEventArgs e)
{
   Settings.Default.Culture = "de-DE";

   Thread.CurrentThread.CurrentCulture = new CultureInfo(Settings.Default.Culture);
   Thread.CurrentThread.CurrentUICulture = new CultureInfo(Settings.Default.Culture);
}

What am I missing?

like image 682
Bob Avatar asked Jan 07 '11 14:01

Bob


2 Answers

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.

like image 102
George Avatar answered Oct 15 '22 15:10

George


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.

like image 35
TomTom Avatar answered Oct 15 '22 16:10

TomTom