Regarding windows form localization C# [duplicate] - c#

This question already has answers here:
What is the difference between CurrentCulture and CurrentUICulture properties of CultureInfo in .NET?
(5 answers)
Closed 8 years ago.
I have noticed people use this code to localize
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Could anyone tell me what CurrentUICulture and CurrentCulture are? Why do we need to assign same value to both
What will happen if I assign the value CultureInfo("fr-FR"); to only CurrentUICulture or CurrentCulture?
I would really like to know in detail what CurrentUICulture and CurrentCulture does?
Suppose client pc language setting could be German or French etc., but I want to develop my application in such a way that whatever language setting is there, my apps will work in that pc with their language setting. I mean that all the controls will show the text in German or French. I do not want to hard code the culture this way CultureInfo("fr-FR")
I would rather the user's language setting dictate the language of my controls. How would I go about doing this?

It's pretty simple.
CurrentCulture is the culture assigned for thread to be used in various culture-specific methods. To example, ToString() one.
CurrentUICulture is
used by the Resource Manager to look up culture-specific resources at run time.
By setting both you ensure what all ToString() works correctly and your form resources are loaded from appropriate satellite.
Regarding usage, you may think to provide user with option to change language. To example, I have native German windows, but I set English culture in it (date format and default culture for console applications), while I speak Russian. Which language do you think I will chose when using your software? =P
By default, either take language chosen in installer (if you have installer in multiple languages and options to change it there) or current Windows user language preferences.
One possible scenario:
Preconditions: application is already localized, satellites are there (if not, read this). I don't like satellites myself, but they are easy to start with.
When application starts, you create a list of available languages (either statically or by enumerating satellites).
string[] Languages = new[] {"en", "fr", "de", "ru"};
Then, if application start for the first time (to example, you have string language setting and it's by default null or "", this would be a flag what no language is selected yet), you detect default os language
var language = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName; // to ex, "fr"
and if it's in your list, then you set
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture = new new CultureInfo(language);
Otherwise, if you don't have this language, then use "default" language (to example, "en"). If its done at at the start of your application, then any further constructed and used window will use proper resources.
User should be able to change language. Give him possibility to chose one of available Languages. In winforms you will have to reload forms after change culture. Easiest solution would be to simply tell user what "software restart is required".

Related

HttpContext.Current.Request.UserLanguages is NULL when first loading IE11/Edge in European countries

I support an application (c#/asp.net) that uses multiple languages using .Resx files for numerous European countries. Recently, some users upgraded to Windows 10 and thus Internet Explorer 11. Now when they load the application, it defaults the main page to en-US and when they go to a page that calls a function that references HttpContext.Current.Request.UserLanguages[0], it comes back as NULL, thus causing a crash with a NULL reference error.
If they change their language settings in any way (add, remove or move a language up or down), then HttpContext.Current.Request.UserLanguages[0] is populated with that top language. However, once they reboot their machine and re-open IE11, then the field is NULL again until they change their settings yet again.
How can I set/detect the correct language without having the user to change their language settings every time they open IE11 after a reboot?
This error does not happen in Chrome, but some users may not have access to Chrome.
Notes I have discovered from past research and are currently in my project:
All pages have Culture="auto" and UICulture="auto";
When first loading the application, System.Threading.Thread.CurrentThread.CurrentUICulture = en-US (and not their default language); (same goes for CurrentCulture as well - both are initially set to en-US)
After they change their language settings, then System.Threading.Thread.CurrentThread.CurrentUICulture changes to be their set language (e.g.: fr-CH for French Swiss);
To summarize: How do I detect IE11's language setting for the user when Request.UserLanguages is NULL and when the CurrentThread.CurrentUICulture is defaulting to en-US and not their system's language? Is there a workaround for using Request.UserLanguages?
I had a user go into Edge and try it out and the same problems occur. The application is not picking up the local culture/language - it is defaults to en-US and not en-UK or fr-CH for example. Also, the application is coded to check different cultures to display dates in the format of the culture, so for Europe, the DD/MM/YYYY format is needed and US - MM/DD/YYYY; currency is also different. So I need to be able to detect the correct culture in Windows 10 without having the user change their language settings to set HttpContext.Current.

CultureInfo("fr-BE") different on Windows 8.1 than before

I set the culture for an .NET web app in order to use specific format for numbers, currency and date:
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-BE");
On an Windows 2008 server machine with IIS 7 I get "d/m/yy" as short date format (what I want).
On my (new) Windows 8.1 pro machine (developer and test) I get "d-m-yy" format for the same CultureInfo..."dash" instead of "slash" separator.
I've checked also in Control Panel -> Region and the settings for French(Belgium) are as mentioned above, different in W2k8 server than in W8.1pro...
The .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8... Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat; if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
Does anybody knows about it? Belgium changed national standards? Or, Microsoft did for them? Any idea?
Thanks.
Thanks for the answers. .NET version is 4, which is ok. Invariant culture doesn't help, as far as I need specific culture to display in the UI and the problem was there. It is true, changes came with Windows 8...
Finally I used to override some settings for the Thread culture, like the Date Separator:
DateTimeFormatInfo dtfi = Thread.CurrentThread.CurrentCulture.DateTimeFormat;
if (dtfi.DateSeparator != "/") dtfi.DateSeparator = "/";
This ensure that slash will be the date separator all the time in the current thread.
Thank you.
I was looking at similar issue for CultureInfo 'en-NZ', as it been changed for the same culture setting in different Windows version, and cause my web service saved different strings for the same CultureInfo, and it turns out it is provided by Windows since .Net Framework 4, and was a combination of Windows and .Net before that.
Lucky for me, I can make use of Invariant culture, which was recommended by Microsoft to make sure the string I saved into Database not going to be changed because of Windows or future .Net Framework update. The thing is, for my case it was the AM\PMDesignator changed from a.m.\p.m. to AM\PM, and the Invariant culture will make sure it saves to AM\PM I assume it will not change in the future, but if I want it save to a.m.\p.m. as it was for older version of Windows, Invariant culture wouldn't be able to do that, I will probably need define my own custom culture or overwrite the current culture as you did.
See the other question about Microsoft specified that CultureInof are subject to change without notice

Localization using resources file not working

I added new Rosource file UserNotification.resx. Then I added two files for localization and named it UserNotification.hr-HR.resx and UserNotification.sl-SI.resx. (followed thread: How to use localization in C#)
Then I changed Windows language's to "si". If i print current culture using System.Globalization.CultureInfo.CurrentCulture.ToString() the output si sl-SI
But, I allways get a string from UserNotification.resx. Seams it doesn't recognizes the localization resource files.
The problem in .NET localization if you use multithreading is that you need to set culture manualy for every thread that you spawn (in case it is different than windows culture, in case when user can choose desired language). It is not inherited from the main thread.
After you create new thread and before you start it you should set it's Culture to the Culture of main thread (which normaly uses the default culture of the windows).
So, system shows good CurrentCulture. But what does current thread says? Maybe application is started with different culture for some reason so that's why it loads default resources file? Anyway, there is no reason why you shouldn't manualy set current culture. Mostly you need to do that when you want to give user the option to change application's language.

How to load different RESX files based on some parameter

I have an ASP.NET3.5 (C#) ASPX page that is internationalized in 10 different languages.
The page is very complex in its structured with dozens of nested views driven by a state machine pattern.
EDIT: I am using the meta:resourcekey syntax in every asp control, which allows to use declarative syntax for Implicit Resource expressions.
I have been asked to "brand" the page based on some query string parameter. Branding will mean not just loading different CSS files, but also having different text blurbs (in all languages).
Is there an easy way to "swap" resx files without having to get resources manually for each of the hundreds of literals and images that I have on this page?
In other words, let's say I have the following RESX files:
brand1_myPage.aspx.en-US.resx
brand1_myPage.aspx.de-DE.resx
brand1_myPage.aspx.fr-FR.resx
brand2_myPage.aspx.en-US.resx
brand2_myPage.aspx.de-DE.resx
brand2_myPage.aspx.fr-FR.resx
myPage.aspx will be looking for resx files named myPage.xx-XX.resx.
Is there a way to load instead either the brand1xxx.resx files or the brand2xxx.resx based on some value?
Thanks in advance.
You can use custom cultures to achieve this effect.
First, create and register custom cultures in the system, for example:
CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("en-US-brand1", CultureAndRegionModifiers.None);
CultureInfo parentCI = new CultureInfo("en-US");
RegionInfo parentRI = new RegionInfo("en-US");
builder.LoadDataFromCultureInfo(parentCI);
builder.LoadDataFromRegionInfo(parentRI);
builder.Parent = parentCI;
// set other properties of the custom culture (CultureEnglishName, CultureNativeName, possibly other ones)
// ...
builder.Register();
Note that you might want to build a simple tool to automate this, since those cultures need to be installed on every system where your aplication will be compiled or executed. Administrative rights are needed to be able to register the cultures.
Once you have the cultures installed, create resx files like you would normally do, but use the custom culture names (myPage.aspx.en-US-brand1.resx etc).
Now all that's left to do is to set System.Threading.Thread.CurrentThread.CurrentUICulture based on some parameter (the sooner the better, BeginRequest is a good place; or Page_PreInit if you want this only for some pages):
CultureInfo ci = new CultureInfo(Request.QueryString["paramname"]);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
(setting CurrentCulture is not really necessary, as resources work in terms of CurrentUICulture, but setting both allows you to further customize the page for each brand, e.g. use different date/time format settings for each custom culture/brand)
Some notes:
this solution gives you great flexibility, since normal culture fallback is in effect - if an entry is not found for en-US-brandX, the runtime will fall back to en-US and so on; this can greatly reduce duplicate resx entries if the brands are mostly similar, as you can put some entries only in the parent (en-US) resx file,
you can create more levels of inherited cultures, eg en-US-brandX-variantY,
all methods for accessing resources work as expected,
changing the culture of the worker thread means you will get localized exception messages if you set the culture to, say, de-DE-brandX and you have de-DE localization installed in the OS,
for the above reason, you might want to reset the current (UI) culture to CultureInfo.InvariantCulture in Application_Error, or even better also as soon as you catch an exception which you know will lead to Application_Error; this will prevent localization of the standard yellow page of death and at least part of the exception stack,
you might consider building a service tool which will register/unregister/update the cultures, especially if you anticipate frequent changes,
this solution might be problematic if you use client-based culture detection.
If you reference resources in your code like this: Resources.brand1_myPage.WelcomeMessage then it may be difficult.
But you can also retrieve resources programmatically: GetGlobalResourceObject ("brand1_myPage", "WelcomeMessage"). Here you have some room for manipulation with the resource file name.

How does a .NET process get the culture information?

I have a Windows service running (C#, .NET 2.0) on Windows Server 2003 R2. In one server the System.Threading.Thread.CurrentThread.CurrentCulture is {en-AU} and in the other {en-US}.
This has caused a difference when calling ToString() on a DateTime object. I want the culture to be {en-AU}.
I checked the "Regional and Language Setting". In both servers, the "Regional Options" tab shows "English (Asutralia)". But in the "Advanced" tab it shows "English (United States)" for one and "English (Australia)" for the other. So this must be causing the difference. Although I want to know why exactly the "Advanced" tab says "the language version of the non-unicode programs you want to use", I thought .NET processes were Unicode and should not be affected by this.
How does the .NET runtime determine the culture to use? Any detailed reference would be helpful.
If a culture has not been set on the thread, Thread.CurrentThread.CurrentCulture defaults to the "user default culture" - which it gets from the underlying OS. This is determined by the Formats section in the regional control panel applet.
For a service, it has no control panel settings by default like for a user (the case above) as it runs under the LocalSystem account which will not have a profile, so it uses the system locale from the OS. I'm not sure if this can be set for a service by adjusting the settings in Windows.
There are a few things you could do:
you can explicitly set the CurrentCulture of the main thread when the service starts. If you do this, you will need to bear in mind that any new threads that are created in your service will also need to have their CurrentCulture set as well, as threads do not inherit their culture from parent threads.
you can set the service to run as a specific user, and set that user's regional settings (the formats section) to be the culture you want to use. When the service starts as that use,it will use that user's regional settings.
since your problem seems to be related to calling DateTime.ToString(), make sure you pass the AU culture to the ToString() method:
DateTime.ToString(new CultureInfo("en-AU"))
You could add this as an extension method to save you having to do this everywhere:
public static string ToAUString(this DateTime dateTime)
{
return dateTime.ToString(new CultureInfo("en-AU"));
}
You can then call DateTime.ToAUString() to get the correct output.
In my case it took only one line of code to change the Culture:
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo( "en-US" )
It changes default Culture of Main thread and new ones as well.
This MSDN page on CultureInfo has some information that might be relevant:
The user might choose to override some of the values associated with the current culture of Windows through the regional and language options portion of Control Panel. For example, the user might choose to display the date in a different format or to use a currency other than the default for the culture. In general, your applications should honor these user overrides.
If UseUserOverride is true and the specified culture matches the current culture of Windows, the CultureInfo uses those overrides, including user settings for the properties of the DateTimeFormatInfo instance returned by the DateTimeFormat property, and the properties of the NumberFormatInfo instance returned by the NumberFormat property. If the user settings are incompatible with the culture associated with the CultureInfo, for example, if the selected calendar is not one of the OptionalCalendars, the results of the methods and the values of the properties are undefined.
I think this might be a good starting point for your investigations.

Categories

Resources