Why are my different language resx files being ignored - c#

I have been following this page to make my site support multiple cultures.
the code all compiles and runs, but it seems to be ignoring my culture specific resx files.
Right now the test is pretty superficial, and I simply have 2 resource files;
Resources.resx and Resources.au.resx
My template is calling #Resources.PageFooter which is the only string defined in both files.
If I browse to http://mysite/index and inspect the page footer it contains my default value. If I change my url to http://mysite/au/index then it still displays the default value. However inspecting CurrentThread.CurrentUICulture and CurrentThread.CurrentCulture shows that both are now set to au, but it is still picking up and using Resources.resx not Resources.au.resx
My Resource files are in a separate folder Resources, as the article suggests.
So I am stuck.
After some investigation, I have found that if I create another resx file (for Italian), then that works.
So it looks like the files that are being ignored are the 'variations' such as American English, Australian English and so on.

First, please change au to en-AU, since this is the correct colture code for Australian English.
In your Global.asax file, set the Application_BeginRequest method like below:
void Application_BeginRequest(Object sender, EventArgs e)
{
string langCode = "en"; //default
if (somecondition)
langCode = "en-AU";
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(langCode);
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(langCode);
}
You need the somecondition I mentioned above to check where the user is coming from - by header, cookie, URI or any other way you want.

Related

Why wpf ResourceManager GetString (localization) returns english only

I have a localization issue.
Here,in below code (auto generated in designer file) the str always returns english values even if the application is in other locale.
.
ResourceManager rm = new System.Resources.ResourceManager("A.b.Properties.Resources", typeof(Resources).Assembly);
.
.
var culture = Thread.CurrentThread.CurrentUICulture; //zh-CN selected as locale
var str = rm.GetString(key, culture); //always returns english :(
.
My resource file sits under the zh-CN folder wherever the executables got built:
"..\zh-CN\A.b.resources.dll" (checked the dll internally, it has the all the strings-values available in cn language)
Project name is: A.b
Namespace in the designer file is: A.b.Properties
I am not able to figure out why the application returns only the english values and not the locale specific ones!
I tried it a lot but unable to figure out whats wrong!
Though i, noticed that the _resourceSets [zh-CN] object Values has all english items in it.
Any idea/reference is much much appreciated.
At application startup, my application determines my preferred language culture, gets the system CultureInfo object for it, and sets the following two values. Are you doing something like this?
System.Threading.Thread.CurrentThread.CurrentUICulture = desiredCulture;
CultureInfo.DefaultThreadCurrentUICulture = desiredCulture;
Also, I don't know if it matters but all of my language-specific resource DLLs live in subfolders that are just the TwoLetterISOLanguageName code from the CultureInfo in question.
So for example, my French translations live in the "fr" subfolder. Are you sure your resources should not live in a "\zh" subfolder, instead of "\zh-cn"?

Viewing Properties.Settings.Default variables

I am trying to use Settings.settings to define/persist some vars. For brevity, I've set up a test file to demonstrate the behavior I'm seeing:
First, I define a setting in Settings.settings:
I then have the following code to test changing variableName:
public Form1()
{
InitializeComponent();
string newString = Properties.Settings.Default.variableName;
Properties.Settings.Default.variableName = "This is a new string";
Properties.Settings.Default.Save();
}
Running the above in the debugger for the first time, I grab the current value (the value I set in the Settings.settings window initially) of variableName from Properties.Settings. As expected, newString is set to "This is a string". Good.....
After executing the next two lines, the debugger shows variableName changed to "This is a new string". Good....
I then run the app through the debugger again. I hit the string newString line and, prior to execution, newString is undefined (of course). Good....
As soon as I execute...
string newString = Properties.Settings.Default.variableName;
... and on subsequent executions of the code, the actual value of variableName is defined as "This is a new string" (Good...as expected).
I then go back to the Settings.settings window. variableName has not changed - it's still "This is a string". I've even closed VSE 2012 and re-opened the project. Settings.settings never changes.
Where is the new value being stored? I've checked all of the .config files ([appname].exe.config, [appname].vshost.exe.config, app.config, and the Settings.settings file) and the new value, "This is a new string" isn't anywhere to be found.
In summary, I'm getting the result I desire from the code, but I can't seem to view the result at design time other than to check the value of the var in the debugger. This seems not only peculiar to me, but impossible.
What am I missing/where am I not looking? I would fully expect the value of variableName to change in the Settings.settings window, but it never does. I've looked everywhere on StackOverflow/Google and can't seem to find the answer.
Thanks in advance....
The original value that you configured via Settings.settings is stored in a .config file alongside your executable's assembly. This will never change unless you modify the Settings file directly via Visual Studio; it's essentially a read-only file.
The user's customized setting is stored in a separate config file within the user's profile. The location of this file depends on your assembly's metadata. For example, on Windows 7/Vista the location might look like:
C:\Users\<user name>\AppData\Local\<company name>\<assembly name>\
AssemblyName\<version>\user.config
If you haven't customized the company name in your assembly's metadata then it may default to Microsoft. Also note that AppData is a hidden folder that may not be visible in Windows Explorer depending on your view settings.
I am not sure if I understand your question. That variable content stay persistent. Thats it. Why you would set a persistent variable to change it later?

Add / switch between embedded / linked resources at running time

I have the resources.resx in my c# code with some strings filled:
Text1,"Some Text"
and i can call it during running time by
Properties.Resources.Text1
which results in
"Some Text"
Now i want to have Text1 a different output (another language for example or something)
so that Properties.Resources.Text1 results in "Different Text".
How can i achieve this?
EDIT1: i discovered this but i was looking for a different approach with the resource files.
If you want to use different Resource Files, you can use the ResourceManager:
ResourceManager rm;
if (Configuration.Default.Culture == "en-US")
rm = new ResourceManager(typeof(Resource1));
else
// ...
String label = rm.GetString("Text1");
Save the the Culture in the User Settings, add a configuration file and define a user variable.
Configuration.Default.Culture= "en-US";
Configuration.Default.Save();
Updated question according to information
I am afraid you have to add another resource file for other culture. just look into this thread
How to use localization in C#
In reference to a comment:
get the current cultureinfo and load resources like this:
Thread.CurrentThread.CurrentCulture.ClearCachedData();
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
if(currentCulture.Name == "en-US")
Console.WriteLine(resources.Text1);
else if if(currentCulture.Name == "ja-JP")
Console.WriteLine(resourcesJapan.Text1);

Always returns the string with the default language from a resource file

I have two resources files, Emails.es.resx (es-ES) and Emails.eu.resx (eu-ES), and I have a problem to retrieve a string from eu-ES file with myLib.Emails.ResourceManager.GetString("textKey", "eu-ES");
At local this works properly but at server, is a web app + IIS, not works, always return a correct value of "textKey" but with default language es-ES.
I cleaned the solution and rebuilded all, but without results.
Does anyone knows what could happen?
Make sure you set the correct culture. Suppose you have given option somewhere at website default page where user can choose language. On language change save the selected language in application state somewhere.. session or catch or whatever suite you. Set culture as following
explained at following link:
protected void Page_PreInit(object sender, System.EventArgs e) {
System.Globalization.CultureInfo lang = null;
lang = new System.Globalization.CultureInfo("zh-CN");
System.Threading.Thread.CurrentThread.CurrentCulture = lang;
System.Threading.Thread.CurrentThread.CurrentUICulture = lang;
}
Now retrieve your resources.. it should return correct one.
Rename your files to Emails.es-ES.resx and Emails.eu-ES.resx

Thread.CurrentThread.CurrentUICulture not working consistently

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.
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.
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

Categories