Reputation: 4386
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?
Upvotes: 16
Views: 28727
Reputation: 127
this might come in handy for someone. I have used the advice given by George & Chris Schaller above to make this work in my project without creating new Application class.
public string LangSwitch { get; private set; } = null;
private void BtnLngPl_Click(object sender, RoutedEventArgs e)
{
CultureInfo current = CultureInfo.CurrentUICulture;
CultureInfo newUiCulture;
if (current.Name.Equals("en-US"))
{
newUiCulture = new CultureInfo("pl");
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
if (System.Windows.Application.Current.MainWindow != null)
((MainWindow)System.Windows.Application.Current.MainWindow).Closed += Wnd_Closed;
Thread.CurrentThread.CurrentCulture = newUiCulture;
Thread.CurrentThread.CurrentUICulture = newUiCulture;
LangSwitch = "pl";
Close();
}
else
newUiCulture = new CultureInfo("en-US");
CultureInfo.CurrentUICulture = newUiCulture;
Console.WriteLine(@"The current UI culture is now {0}",
CultureInfo.CurrentUICulture.Name);
}
and the other necessary code can be taken from George's answer. Not sure how good of a solution this is, but does the job for me.
Upvotes: 1
Reputation: 1
I also experienced this problem and my solution was:
I created a class that will return a dictionary with the key and the label:
public class Labels : ObservableObject
{
public Dictionary<string, string> Items { get; set; }
public string this[string name]
{
get
{
return Items.ContainsKey(name) ? Items[name] : "";
}
}
public Labels()
{
Items = new Dictionary<string, string>();
}
}
Next, one more class to get the Resources:
public static class LanguageUtils
{
public static Labels GetLangLables(string label)
{
var resources = Resources.ResourceManager.GetResourceSet(new CultureInfo(label), true, true);
return new Labels
{
Items = resources.Cast<DictionaryEntry>().ToDictionary(r => r.Key.ToString(), r => r.Value.ToString())
};
}
}
When you need some language:
LanguageUtils.GetLangLables("pt-PT");
Once, you can't raise (RaisePropertyChanged()) static properties, use this:
public class LanguageContext
{
private static LanguageContext _languageContext;
public static LanguageContext Instance
{
get
{
if (_languageContext == null)
{
_languageContext = new LanguageContext();
}
return _languageContext;
}
}
protected LanguageContext()
{
CurrentLangLabels = LanguageUtils.GetLangLables("en-US");
}
public Labels CurrentLangLabels { get; set; }
}
Now you can update language:
LanguageContext.Instance.CurrentLangLabels = LanguageUtils.GetLangLables(SelectedLanguage.Resource);
Raise like this:
public Labels CurrentLangLabels
{
get { return LanguageContext.Instance.CurrentLangLabels; }
set { RaisePropertyChanged(); }
}
And use label:
CurrentLangLabels.Items[LabelName]
Upvotes: 0
Reputation: 41
If you have resource files, e.g.:
... 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.
Upvotes: 4
Reputation: 62093
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.
Upvotes: 11