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.
Related
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.
I'm having some problems with CultureInfo values for a specific culture, "pt-PT". To narrow it down I created an MVC project in VS 2017 using .net framework and added the following line to the view About.cshtml:
<p>#(new System.Globalization.CultureInfo("pt-PT").DateTimeFormat.FirstDayOfWeek)</p>
This was the only change I made to the project created by visual studio.
When I run this project in VS using the IIS Express, the value returned by FirstDayOfWeek is 'Monday'.
However if I run this project in IIS (on the same machine), the value returned by FirstDayOfWeek is 'Sunday'.
I was expecting the value to be the same and to be 'Monday'.
I'm puzzled about the diference in values and would like some help in understanding it.
Note: After further tests I concluded that if I change the first day of the week in my computer settings, that change is reflected when running the project in IIS Express. I'm more confused... I guess this property is useless...
By default, IIS uses DateTimeInfo.InvariantInfo which returns Sunday as its FirstDayOfWeek value (also using United States date format too). If you're unsure why IIS (not Express) uses different culture than you're using, set the culture information in Application_BeginRequest handler inside Global.asax code:
protected void Application_BeginRequest(object sender, EventArgs e)
{
string culture = "pt";
if (HttpContext.Current.Request.Path.Contains("pt"))
{
culture = "pt"; // Portuguese, use 'pt-PT' if not sure
}
else
{
// set to other cultures, including invariant (default) one
}
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture);
}
Or use globalization element in web.config file to set Thread.Culture & Thread.UICulture:
<globalization culture="pt-PT" uiCulture="pt" />
If all of the above settings doesn't work, use these steps below:
Open IIS Manager, select your site and open ".NET Globalization".
Open "Culture" tab, set both Culture & UI Culture section to Portuguese.
Restart the application pool or use iisreset command to apply all changes.
NB: As a general convention, the site shouldn't rely on server's application pool setup to work as expected with specified locale/culture. See Set the Culture and UI Culture for ASP.NET Web Page Globalization for further details about culture settings.
Also check if the regional settings of your application pool set to follow NetworkService's user account, change it to LocalSystem if necessary.
Similar issues:
ASP.NET Application is displaying american date formats
How do you set the IIS Application Pool Identity User Locale when it's set to ApplicationPoolIdentity
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.
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 ?