Question

I've been working on a pet project on the weekends to learn more about C# and have encountered an odd problem when working with localization. To be more specific, the problem I have is with System.Threading.Thread.CurrentThread.CurrentUICulture.

I've set up my app so that the user can quickly change the language of the app by clicking a menu item. The menu item in turn, saves the two-letter code for the language (e.g. "en", "fr", etc.) in a user setting called 'Language' and then restarts the application.

Properties.Settings.Default.Language = "en";
Properties.Settings.Default.Save();
Application.Restart();

When the application is started up, the first line of code in the Form's constructor (even before InitializeComponent()) fetches the Language string from the settings and sets the CurrentUICulture like so:

public Form1()
{
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language);
    InitializeComponent();
}

The thing is, this doesn't work consistently. Sometimes, all works well and the application loads the correct language based on the string saved in the settings file. Other times, it doesn't, and the language remains the same after the application is restarted.

At first I thought that I didn't save the language before restarting the application but that is definitely not the case. When the correct language fails to load, if I were to close the application and run it again, the correct language would come up correctly. So this implies that the Language string has been saved but the CurrentUICulture assignment in my form constructor is having no effect sometimes.

Any help? Is there something I'm missing of how threading works in C#? This could be machine-specific, so if it makes any difference I'm using Pentium Dual-Core CPU.

UPDATE

Vlad asked me to check what the CurrentThread's CurrentUICulture is. So I added a MessageBox on my constructor to tell me what the CurrentUICulture two-letter code is as well as the value of my Language user string.

MessageBox.Show(string.Format("Current Language: {0}\nCurrent UI Culture: {1}", Properties.Settings.Default.Language, Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName));

When the wrong language is loaded, both the Language string and CurrentUICulture have the wrong language. So I guess the CurrentUICulture has been cleared and my problem is actually with the Language Setting.

So I guess the problem is that my application sometimes loads the previously saved language string rather than the last saved language string. If the app is restarted, it will then load the actual saved language string.

Was it helpful?

Solution

I got the same problem. I figured out that Application.Restart() do not really make an absolutely restart, see MSDN.

So Application.Restart() do not call the initializing things within the forms constructor like InitializeComponent(), more the "Applications are restarted in the context in which they were initially run."

So your code is correct

Properties.Settings.Default.Language = "en";
Properties.Settings.Default.Save();

public Form1()
{
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language);
    //...
    InitializeComponent();
}

but it doesn't work this way with Application.Restart(). If You close the app and open it again your (new) settings are taken.

So we have to find a way to initialize the form again to make the new language settings happen.

OTHER TIPS

Could you check what is your thread's CurrentUICulture?

I remember having a problem like yours; it was solved by reloading the resource dictionary containing the strings to be localized:

Thread.CurrentThread.CurrentUICulture = <new culture>;
ResourceDictionary newDict = new ResourceDictionary();
newDict.Source = localizedStrings.Source;
localizedStrings = newDict;

(and this approach worked dynamically as well; here is some more information).

You could manually change the language of the current form similar to this:

CultureInfo cInfo = new CultureInfo("en-US");
ResourceManager rm = new ResourceManager(GetType());

// For each control on the form, perform the translation manually (probably better in a loop)
control1.Text = rm.GetString(control1.Name + ".Text", cInfo);

// Now set the culture for all other dialogs
Thread.CurrentThread.CurrentUICulture = cInfo;

Hope that helps!

You could simply "reset" your application by closing the open forms and re-creating them. Then you could directly set the culture when the user changes the setting.

Also, try giving some debug output so you see what values are being set and if the culture is actually what you expect.

EDIT: My guess: Since the data has to be written to a file, and then loaded from that file, you may be restarting too quickly for the write to have been completed.

By using CurrentThread.CurrentUICulture, and then changing the form, you don't need to restart the application. Ref my old post here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top