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.
Related
tl;dr: Is it possible to define and register en-BS as a culture on Windows Server 2012 R2?
I'm trying to introduce international currency options to some software I'm working on. That process by itself has not been difficult. I use a culture code such as "en-US" to get a CultureInfo object, and I use NumberFormat from the CultureInfo object to format the currency. Great! We have some clients in the Bahamas, so among the currencies we're looking to support is the Bahamian Dollar, which comes from the culture en-BS.
This worked very well all throughout development. But after we deployed the feature, trying to retrieve the CultureInfo for en-BS came back with the following error.
Culture is not supported.
Parameter name: name
en-BS is an invalid culture identifier.
In researching this error, I learned that cultures are not defined by .NET, but rather by the OS. Windows 10 natively supports en-BS. Great news for my development environment! Windows Server 2012 R2 does not support en-BS. Bad news for our production environment.
So now it looks like I need to utilize CultureAndRegionInfoBuilder. It's not the most convenient solution, but I can make it work. I know nothing about the cultural nuances of Bahamian Dollars, so all I want to do is take the info that is defined on Windows 10 and register it on our 2012 R2 servers. Since I can't just pull up the en-BS CultureInfo via code on the older servers, I thought the next best thing would be to serialize the CultureInfo to a file on my development machine, and deserialize that file on the older servers to then use with CultureAndRegionInfoBuilder.
const string identifier = "en-BS";
string cultureFile = String.Format("{0}-Culture.txt", identifier);
string regionFile = String.Format("{0}-Region.txt", identifier);
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(cultureFile, FileMode.Open, FileAccess.Read, FileShare.Read);
CultureInfo cultureObject = (CultureInfo)formatter.Deserialize(stream);
stream.Close();
stream = new FileStream(regionFile, FileMode.Open, FileAccess.Read, FileShare.Read);
RegionInfo regionObject = (RegionInfo)formatter.Deserialize(stream);
stream.Close();
CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder(identifier, CultureAndRegionModifiers.None);
builder.LoadDataFromCultureInfo(cultureObject);
builder.LoadDataFromRegionInfo(regionObject);
builder.Register();
It's not the most elegant code I've ever written, but it's straightforward and should be good enough for something I'm going to run once and then archive forever. Unfortunately, when I try to deserialize the CultureInfo object from the file, it once again hits me with the exact same "en-BS is an invalid culture identifier" error, as if it's actively rejecting any culture by that name.
I'm at a loss. Is it at all possible to register en-BS, or any other unsupported culture, to a 2012 R2 server?
it is a web page (Asp.Net MVC), multi-language including english, latvian, lithuvian, russian, polonia.
For selecting a date we choose the jQuery-Ui-datepicker including extra localization files for each language. (Date is given as string: "DateTime".ToString("d", new CultureInfo("lv")) )
All runs fine with all languages at my development computer (Win10, DotNet 4.5, Visual Studio 2012).
Running the web application at the server (Windows Server 2012 R2) other languages without problems. But the latvian language leads to problems.
I added trace code around the CultureInfo for Latvian 'lv'.
There is an difference between the CultureInfo.DateTimeFormat.ShortDatePattern between development notebook and web Server.
CultureInfo.DateTimeFormat.ShortDatePattern
- my computer: 'dd.MM.yyyy'
- web server : 'dd.MM.yyyy.'
the fastest solution would be: trim final point at datetime format.
(the javascript seems to work without the 'final point')
Is it a Framework Bug ?
which system needs a fix ? the server or my computer (inclusing javascript datepicker localization source)
How to solve it in a nice way (so it doesnt seems hacky)
thanks,
Mathias
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 ?