I have a web application in which I set the CultureInfo on Thread.CurrentThread to ar-IL (Arabic-Israel):
Thread.CurrentThread.CurrentCulture = new CultureInfo("ar-IL")
The problem is that on my local machine (Windows 10 with IIS 10) it works just fine and no exception is being thrown. However, on Azure (Windows Server 2012 R2 with IIS 8.5) it throws CultureNotFoundException:
Culture is not supported. Parameter name: name 'ar-IL' is an invalid
culture identifier
I checked the source of CultureInfo and realized that the native call to nativeInitCultureData() is the culprit. On my Windows 10 machine it returns true but on Windows Server 2012 it returns false.
Also, checking the SSCLI for nlsinfo.cpp file reveals this comment:
// Call GetLocaleInfoEx and see if the OS knows about it.
// Note that GetLocaleInfoEx has variations:
// * Pre-Vista it fails and has to go downlevel
// * Vista succeeds, but not for neutrals
// * Win7 succeeds for all locales.
// * Mac does ???
So, how can I handle custom combinations of languages and regions (ar-IL, he-US etc) that are not recognized by Windows?
P.S I'm aware of the possibility to create and register a custom locale (using CultureAndRegionInfoBuilder) but it will take too much effort to cater for all the combinations I'm planning to support.
Yes, Windows 10 is able to provide somewhat sensible information for any culture name.
Constructing culture info yourself is an option - as long as calendar information is compatible you can merge strings from neutral ("HE") culture with data for any specific one (like "en-US"). CultureAndRegionInfoBuilder can be used to safely combine information as shown in the MSDN sample:
// Create a custom culture for ru-US.
CultureAndRegionInfoBuilder car1 = new CultureAndRegionInfoBuilder("ru-US",
CultureAndRegionModifiers.None);
car1.LoadDataFromCultureInfo(CultureInfo.CreateSpecificCulture("ru-RU"));
car1.LoadDataFromRegionInfo(new RegionInfo("en-US"));
Aleternatively you can build XML files defining cultures you need to support and either load them at run-time or even install on the servers using CultureAndRegionInfoBuilder.Register - Create custom culture in ASP.NET.
Related
I have following code to detect whether culture name represents valid culture (I check it to proceed for report rendering in given culture).
try
{
this.Culture = new CultureInfo(cultureName);
}
catch (CultureNotFoundException)
{
// on exception default culture will be used
}
When culture is found, it is set to Culture and later used in report rendering. It works fine in most cases, but if I provide "en-NL" as culture name, the code throws exception on localhost (culture is not found) which is fine (report is rendered with invariant culture).
But if I deploy it remotely on Azure, culture is found and rendering of report fails (because it cannot find such culture).
I tried this code on dotnetfiddle. And there it also returns culture name. But LCID is 4096.
I googled what 4096 stands for and realized it is LOCALE_CUSTOM_UNSPECIFIED - so some culture created by user.
The question is why it behaves differently. I have .NET 4.5 installed on local and Azure too.
Another question is whether I can handle it in a way that if LCID is 4096 I rather use invariant culture to avoid the risk culture does not really exist.
NOTE:
I do not think it is duplicate of this question. I think it has nothing with case-sensitivity, it is about not recognizing particular culture locally and recognizing it on another server.
I recently started having a problem with CultureInfo in my web application.
The code in question:
public static CultureInfo ConvertToCultureInfo(this string input)
{
try
{
return new CultureInfo(input);
}
catch (Exception)
{
return new CultureInfo("en-US");
}
}
When a user whose locale is 'en-AT' is accessing my website the request for this cultureinfo works on my local but is failing on my Windows Server 2012 box (and falling back to en-US, which is incorrect).
We tracked it down to an issue with the MS-LCID version 10.1 but this is allegedly only available for Windows Server 2016.
However, this occurs to me as kind of silly - why can't we just download a package that updates the existing LCID to support the newer locales? It's still the same list of dateformats and Windows Server 2012 is still supported. I can't find any resources on updating this and was hoping someone here knew a bit about this and could point me in the right direction.
Right now my best lead is to additionally test for custom CultureInfos and supply my own formats, but this seems like overkill when there exists the LCID, it's just somewhat out of date.
From Control Panel, I set my Region and Language setting to French (France)
When I am running my application as console application,
Thread.CurrentThread.CurrentCulture returns French
But when I'm running it as windows service, it returns invariant culture or English (US)
Is there a way to fix that?
The service is probably running as a user that has it's own culture.
Why not set the culture when you start your service
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
Also from Default Culture in a Windows Service
If your Windows Service is running under the SYSTEM account or other account without a
profile it will use the settings defined under the
"HKEY_USERS/.DEFAULT/Control Panel/International" registry key.
You can change these values from "Control Panel / Regional and Language Options / Advanced"
by checking the checkbox "Apply all settings to the current user account and to the default
user profile".
I normally use the former technique as I only need to change it for a specific service rather than for the whole OS.
.NET 4.5 added CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture i suggest setting it as early as possible and it should solve your issue.
This will change the current threads culture and all threads that are created.
I can't figure out how to get the CultureInfo of the Installed System on the Client Machine.
There is the CultureInfo.InstalledUICulture Property, but it seems to be unavailable in Silverlight.
Regards
Jonny
I believe that Culture.CurrentCulture will in fact provide you with the user's culture. It can however change or be programmatically set via current thread's Thread.CurrentCulture property. I'm not sure if Silverlight can access the user's machine/operating system culture/language settings beyond this mechanism.
As you mention in a comment, you cannot trust it as it will definitely change through the lifetime of the application. Perhaps then you should record the current culture when the application first starts up before it's programmatically changed, and store it indefinitely (statically or otherwise) to be referenced by your code.
EDIT: Another possibility is to leverage the hosting browser and its JavaScript. Googling around I see that you can access window.navigator.language which will report the language of the browser. Internet Explorer likes to do its own thing and reports the browserLanguage, userLanguage, and systemLanguage.
You can write up a small JavaScript method on the page (you will want to do more cross-browser tests, version tests, and operating system tests):
function GetUserLanguage()
{
if (window.navigator.language)
return window.navigator.language;
else //yay IE
return clientInformation.browserLanguage;
}
Then in Silverlight you might have something like:
string userLanguage = (string)HtmlPage.Window.Invoke("GetUserLanguage");
CultureInfo userCulture = new CultureInfo(userLanguage);
I'm not sure if all cultures reported by the browser (across all browsers/versions/operating systems) will match the culture listing in Silverlight.
I have a web application that will use a few different cultures, one of which is es-US (Spanish United States). However, Windows XP do not have any support for the culture es-US. To work around the problem, I've found out that one is supposed to be able to use the CultureAndRegionInfoBuilder. So I looked into CultureAndRegionInfoBuilder and did the following:
On a Windows 7 machine I saved the culture es-US to an XML-file, as follows:
private static void SaveCultureToFile() {
try {
CultureAndRegionInfoBuilder cultureAndRegionInfoBuilder = null;
Console.WriteLine("Saving es-US to xml disc...\n");
cultureAndRegionInfoBuilder = new CultureAndRegionInfoBuilder("es-US", CultureAndRegionModifiers.Replacement);
// Populate the new CultureAndRegionInfoBuilder object with culture information.
CultureInfo ci = new CultureInfo("es-US");
cultureAndRegionInfoBuilder.LoadDataFromCultureInfo(ci);
cultureAndRegionInfoBuilder.Save("es-US.xml");
}
Then I have a function that reads the xml, and registeres the culture into the system, as follows:
private static void RegisterCultureFromDisk() {
try {
CultureAndRegionInfoBuilder cultureAndRegionInfoBuilder = null;
Console.WriteLine("Loading es-US from xml...\n");
cultureAndRegionInfoBuilder = CultureAndRegionInfoBuilder.CreateFromLdml("es-US.xml");
Console.WriteLine("Culture is registred to the system...\n");
cultureAndRegionInfoBuilder.Register();
Console.WriteLine("The following culture has been registred to the system: \n");
}
So I run the program using the SaveCultureToFile method on a Windows 7 machine, thus saving the culture to an xml file. Then I copy the files to the Windows XP machine, and runs the same program but the RegisterCultureFromDisk() method. But the program fails in the CultureAndRegionInfoBuilder.CreateFromLdml("es-US.xml") method saying that:
"Culture name 'es-us' is not
supported"
Well, thats exactly why I'm trying to load the culture from the xml and registering it into the system.
Do any one know what I'm doing wrong, or how I can create the es-us culture at the Windows XP machine?
Thanx!
I know this is an ancient question, but I've recently run into this issue and managed to actually solve it.
Turns out the CreateFromLdml method can be tricked into loading a non-existing culture if you just create a temporary culture using the name of the one you want to import. Then you can unregister the temporary culture and register the one you just loaded instead.
I've made a simple command-line tool for exporting/importing cultures, which we've successfully used to add in some obscure missing cultures we needed when deploying new servers on Azure.
If you need it - the source code and a more in depth description of the solution is available here.
From MSDN:
Note that a custom culture can be registered on a computer only by a user who has administrative rights on that computer. Consequently, typical applications cannot create a custom culture.
I suspect it might be the cause of your problem... do you have admin rights on this machine ?