System Locale in .NET - c#

I have set the system locale to Chinese (Simplified PRC) via
ControlPanel >> Region and Language >> Administrative >> Change System locale
I then restarted my computer and run my .NET 4.0 application.
Running
Thread.CurrentThread.CurrentCulture.Name
Returns
en-GB
Why?

MSDN says that
Information, such as the default culture and format patterns, is
cached the first time it is requested. That information can change
during the life of the AppDomain, for example, when the user modifies
the regional and language options portion of Control Panel. However,
the CultureInfo class does not automatically detect changes in the
system settings.
call this first
Thread.CurrentThread.CurrentCulture.ClearCachedData();

Looks like the place to see the system locale is System.Text.Encoding.Default
PS: The "...Change system locale" affects the ANSI codepage used for "non-Unicode" applications (the *A() calls from Win32 API). In most cases .NET applications do not need to care about it because they use Unicode strings and Unicode API. But I have to interact with non-unicode application, so I need to inquire the current system locale.

Related

Where System.Threading.Thread.CurrentThread.CurrentCulture is set

Where is System.Threading.Thread.CurrentThread.CurrentCulture set? I have a US customer (and I am in US); the debugging code shows the value equals "en-GB". And therefore dates are shown in British format ('DD/MM/YYYY'). Where is this set, in which file?
You can force current CultureInfos by CultureInfo.CurrentUICulture and CultureInfo.CurrentCulture.
The first one effects to text based things such like datetime etc. The second one effects to numbers such like floating points. Setting both to same CultureInfo is basic implement.
Note that, this will work fine if you don't consider multi-languages. Or you need to add language selecting menus.
Generally, CultureInfo comes from the OS (presuming it's not explicitly overridden in code); in case of a web application, CultureInfo typically comes from the client OS, via HTTP's Accept-Language header (you can likely monitor this with tools like Fiddler, etc).
In your case, if it's possible to ask the client to check their system setting - on Windows 10, the PowerShell command Get-Culture will return the current culture set in the OS, for instance - you might be able to determine the source of the problem.
Furthermore, it is possible to set a different culture for the current user (no Admin required, I believe), using the PowerShell Set-Culture -CultureInfo en-US command, where en-US is the desired culture (no pun intended). There is also a way to reset it for the entire machine, with the PowerShell Set-WinSystemLocale -SystemLocale en-US command (Admin rights and a reboot are required).

Identify unlocalized text

In ASP.NET, an application can be localized using resource files. Resource files hold different translations. For example, one might have an English resource file and a Spanish resource file. When resource files are used, an attribute can be applied to controls on a web page to automatically populate that control with values from a resource file. Alternatively, the values can be programmatically loaded from a resource file and assigned to a control's property.
ASP.NET uses a fallback mechanism for loading translations. It tries to find the resource file that is most similar to the current user's culture. If the current user's culture is Spanish, ASP.NET tries to load the appropriate resource from the Spanish resource file. If the Spanish resource is not available, it falls back to a default resource file. Because of this behavior, text for a Spanish user may be shown in the default language for two reasons:
No Spanish translation is available. (The translators haven't provided a translation for this item yet.)
The text is not localized. (This may be the result of plain text appearing in the page or the message being hard-coded somewhere.)
If text appears in the default language, I want to know whether it was because of reason 1 or because of reason 2.
For every missing translation, I could insert some kind of placeholder text in a resource file. However, this means that I am throwing away the fallback mechanism. Even worse, if placeholder text accidentally makes it through to production, it looks much worse than showing the default text.
Does anyone have any suggestions (or solutions) for determining which of these two conditions is the reason for default text appearing during manual testing?
If I understood you correctly you want to verify that every localizable text is indeed in fact localizable and not burned in the code. To do this you should not be using a real culture (Spanish), instead you should create resources for a fake unsupported culture and provide an automatic translation for every localizable resource entry available in the default resources.
For example, if you have a default resource containing:
Entry1: This is a test!
you should create a resource in your fake culture containing:
Entry1: Th1s 1s # t€st!
You could even (and should) perform the creation of the fake resources automatically using a simple character mapping. This way, when you set the application to use your custom fake culture you know that every entry has a translation so you can find harcoded text. This strategy is used by Windows and is known as pseudo-locales. The use of pseudo translated strings makes it possible do development using the fake culture because the text is still readable and this improves your probability of finding hardcoded text.
Windows supports pseudo-locales since Windows Vista and Windows 2008 R2, so if your build and testing environment uses these operating systems you can associate your fake culture to one of these pseudo locales (for example qps-ploc). If you have unsupported operating systems just associate your fake resources to a real culture that you probably will never be supporting or just create your own culture.
Also note that even in a supported operating system, Visual Studio will not create satellite assemblies for these pseudo-locales unless you enable them on the registry.

ResourceManager and not supported platform

I use ResourceManager for UI localization of my WinCE 5 software. I have some resource files with text strings on different languages
Resourse.resx
Resourse.de-DE.resx
Resourse.ru-RU.resx
When I want to display UI in English I call:
Resourse.Culture = new CultureInfo("en-US");
label1.Text = Resourse.LabelText;
in German:
Resourse.Culture = new CultureInfo("de-DE");
label1.Text = Resourse.LabelText;
in Russian:
Resourse.Culture = new CultureInfo("ru-RU");
label1.Text = Resourse.LabelText;
but here I get PlatformNotSupportedException.
I know that my WinCE does not contain Russian and I cannot modify OS to appened this, so my question is how I can say to ResourceManger to use Resourse.ru-RU.resx when I set Culture = new CultureInfo("ru-RU") ?
The answer Jonathan provided is the exact work around I had to do to get my device to show Simplified Chinese. I used "en-ZW" English(Zimbabwe). This worked on 3 different devices all running a different OS (CE5, CE6, and WEH/WM 6.5.3)
If the base Tahoma font doesn't contain everything you need, as in my case, you also need to put the font on the device and make some additional registry changes to enable font linking. It's not very complex, only a couple of registry entries.
This MSDN link provides the information for the Chinese fonts but it would be used the same way for any other font set.
http://msdn.microsoft.com/en-us/library/ms901082.aspx
The more generic MSDN articles on font linking can be found here:
http://msdn.microsoft.com/en-us/library/ms901098.aspx
Other than this the only other option I was able to determine was to roll your own translation resource class.
The following is a rather HACKED workaround, but it will solve the PlatformNotSupportedException issue. I would also recommend doing this only as a last resort. Please note that I have only tested this on WinCE 6.0.
If the culture you are attempting to implement is not supported by WinCE 6.0, simply re-label it as a different culture. For example, rather than marking the Russian culture as "ru-RU" (as above), you could re-name it as "eu-ES" (Basque). Provided that the font being used supports the Cyrillic character set, the values should display as you have written them.
Note: You MUST also rename your resource file to match the target culture you are substituting. If you are using "eu-ES" in place of "ru-RU", you must rename your "Resourse.ru-RU.resx" to "Resourse.eu-ES.resx".
What you lose: Any native support provided by the target culture (Russian in this case), (e.g. correctly formatted currencies, dates, etc), since these would now be being drawn from the work-around target culture (Basque in this case). Note that this should only be a problem in your application if you are formatting your strings via culture (i.e. stringFormat({some CultureInfo.GetCurrentCulture}, {additional formatting}, {some numerical value})).
Seems like you're stuck unfortunately. Your issue is unusual because typically a mobile app does not need to decide on which culture identifier to use. If it just relies on whatever culture the system has set up for it when launches, then users can switch the global culture setting which would affect your app and make it use your localizations if present.
If you are implementing a language selector inside your app, then I guess you need to filter down your list of choices so that you only offer cultures which the device supports (CultureInfo.GetCultures will give you a list of supported cultures, and you can find the subset for which you have localizations available).

EXE shows exception when run in mandarin language machines

I have a winform EXE running using .NET 2.0 framework, when i sent this EXE to my friend who is using a machine where ALL the settings/OS(windows) are displayed in mandarin language.
When i try to open the EXE, i straight away get exceptions in mandarin language.
Is there something i need to change if i need to run an winforms .net EXE in mandarin machines?
Thanks.
There are going to be a whole host of localization issues. My own software has only been used with European scripts, but I still have to handle different number and date formats. So even simple things like reading and writing numbers from the registry (for default settings) require localization support. .NET 2 provides localization support - use the CultureInfo class to determine which formatting method/etc is causing the problem.
You will also need to do everything in Unicode (which you probably already know).
Running your program in a debugger should give insights as to what exactly is failing.

Where is the system locale/culture set for .Net

I have a problem with a c# assembly (.net 2.0 written using Visual studio 2005) that is installed on a UK server and should use UK regional settings.
What my code does is to convert a date in the form dd/MM/yyyy into utc. i.e. yyyy-mm-dd. The problem arose with dates like 16/02/2010 where the component failed to convert the date and returned Error. After debugging I realised that, for a strange reason, the CultureInfo returned by System.CultureInfo is en-US.
I can programatically change those settings using:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB", false);
and my code works fine.
However I don't want to do that all the time as my system should be UK. Not US.
So, how do I change the default culture for .Net framework to be by default en-GB instead of en-US ?
For information:
I have tried to update the machine.config file and specify culture=en-GB for the globalization section (it was set to neutral) but it doesn't work either [have done that for 1.1 and 2.0] but it's possible I have not changed it correctly.
I have verified my windows regional settings and they are definitely set-up to UK with dates as dd/MM/yyyy
I am running in a Virtual server and have verified my host system. It too is set to UK
Edit:
A bit of extra detail about the context. The assembly in question is being called via COM interop from a native C++ third party component that is running as a COM+ application.
The server is not configured correctly. Control Panel + Region and Language, Location tab. Changing this could be a bit tricky. The server may well have been mis-configured on purpose. Talk to the server administrator first before doing anything.
Your fallback plan is to use the DateTime.TryParse() method overload that takes the IFormatProvider argument. Pass CultureInfo.GetCultureInfo("en-gb").DateTimeFormat.
To set the UI culture and culture for all pages, add a globalization section to the Web.config file, and then set the uiculture and culture attributes, as shown in the following example:
<globalization uiCulture="en" culture="en-GB" />
Hmmm, according to the API Docs:
When a thread is started, its culture is initially determined by using GetUserDefaultLCID from the Windows API.
This method derives it's locale from the (as the name implies) User's Default Locale, which I assume is in the Control Panel. NOTE: This is NOT the same as the UI Locale.
thanks for your answers (andy posted the question on my behalf). It was indeed an issue with regional settings but neither with the user I was connected under, nor with the user the process was running under. That would have been too easy. It looks like that the default user was still en-US. I did reset by clicking the checkbox "Apply settings to the current user and default user..." in the advanced tab and rebooting the server. System.Globalization.CultureInfo now return {en-GB}. And a MyDate.ToString(yyyy-mm-dd) works fine whether the date is passed as dd/MM/yyyy or dd-MM-yyyy or yyyy-MM-dd without the need to parse.
However thanks you all very much for your suggestions (ParseExact, etc) that did indeed work. They ill be very helpful for other date formats that I was not able to handle in a nice way (yyyyMMdd).
Marc
I believe this is represented by System.Globalization.CultureInfo.InstalledUICulture, so if nothing else maybe you can copy that to the thread's current culture. I'm surprised that you found a case where the threads culture is different than the installed culture. Perhaps your code is running in a process that changed the culture?
It is possible the account running the code has different regional settings than the system default. Have you checked that?
You do not have to change the CurrentCulture to do the transformation. If you are certain that the date is in the form of "dd/MM/yyyy" you could use
DateTime dtTemp = DateTime.ParseExact(dateString, "dd/MM/yyyy", null) // in order not to have to specify a FormatProvider
and then use
dtTemp.ToString("yyyy-MM-dd")
This way you will not have a problem no matter what the CurrentCulture is. However, if you are not certain that the Date is of the form "dd/MM/yyyy" rather it is based on the CurrentCulture short date format, then you should use
DateTime dtTemp = DateTime(dateString, CurrentCulture.DateTimeFormat.ShortDatePattern, CurrentCulture.DateTimeFormat);
Assemblies in .net framework are culture neutral.
What code are you trying to convert the date?
If you are using Parse or TryParse, try providing the culture argument for it to understand the date.

Categories