Problem:
I have a C# .NET 2.0 application developed on Windows 7 that has translated resources for multiple languages (ex. zh-CHS for Chinese, es for Spanish, etc.).
I have a customer who wants to run their Windows 7 OS in English, but run my .NET application in Spanish (es).
My application is multi-threaded, so just changing the culture of the main GUI thread is not sufficient for my needs (trust me, I tried). This is because other strings displayed to the user through the GUI are generated on other threads. In order to get 100% complete coverage, I would need to set the culture of each individual thread manually to ensure all text from resource files is in the correct language. Because my product is basically a framework for other plugins that other development groups write, I don't have control over actions performed in threads created in other plugins. Because of this, manually changing the culture for each thread is not a valid option.
What I am looking for is a way to set the overall language for the application, without having to change any of the OS user settings.
In doing some research, I came across the following method for setting the preferred UI language for a process: SetProcessPreferredUILanguages
After reading up on this, it appears that this call is what I am looking for. However, when I implemented this call in the Main method of my C# application, it doesn't appear to do anything.
The return value from the following code is true, but I never see my GUI application displaying the text in Spanish.
[DllImport("Kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern Boolean SetProcessPreferredUILanguages(UInt32 dwFlags, String pwszLanguagesBuffer, ref UInt32 pulNumLanguages);
public void SetLanguages()
{
uint numLangs = 0;
string[] langs = new string[3];
uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention
langs[0] = "es\u0000";
langs[1] = "zh-CHS\u0000";
langs[2] = "en-US\u0000";
numLangs = (uint)langs.Length;
if (SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, String.Concat(langs), ref numLangs))
{
Console.WriteLine("Successfully changed UI language");
}
}
Is there something else I am missing in order for this to successfully run my GUI application with the Spanish resources loaded?
I am trying to implement the 2nd option of the table at the bottom of the MSDN page for Building MUI Applications, where I have Application-specific UI language settings and want to achieve the desired result for resource loading:
Application calls MUI API to set application-specific UI languages or process-preferred UI languages and then calls standard resource loading functions. Resources are returned in the languages set by the application or system languages.
I have made the call to successfully set the process preferred UI languages, but my resources are not being loaded in the language I would expect. A commenter mentioned this call will only work for un-managed resources, which I could not verify 100%, but the behavior seems in indicate this is the case.
I can't be the only person who has ever tried to implement a .NET application in this manner. It's frustrating that there isn't more information about how to do this.
Thanks in advance,
Kyle
Starting with .NET 4.5 the CultureInfo.DefaultThreadCurrentCulture property allows you to set the default culture for threads in the current application domain. Other than that I have not found a way to do this elegantly.
Here is the code that will show you how to reproduce this behavior:
Output:
Here is a related question with a possible solution for .NET 4.0 or before, using a helper class to create your threads. Even though they talk about WPF in there, it applies to other .NET multi-threaded applications too.
I know you did not want to change the culture for each of the new threads, but I cannot think of any other efficient alternatives for it.