What is a neutral culture? What is a neutral locale?

by Michael S. Kaplan, published on 2004/12/29 02:05 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2004/12/29/343557.aspx

I am going to take these two questions out of order because (a) locales existed before cultures did, (b) neutral locales set the stage for neutral cultures, and (c) I think it may help us look less lame. Though that third reason is probably just naive optimism on my part....

To see what Windows does with neutral locales, you can look at the documented behavior of ConvertDefaultLocale. Basically, if you pass a neutral like LANG_ENGLISH then it will return the equivalent of MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) thus 0x009 becomes 0x0409, 0x01a becomes 0x041a, and so forth. Easy, huh?

This ConvertDefaultLocale function calls an internal routine to do its work; the same routine is called by every NLS function, too. Which is a long way around to say that neutral locales do not exist to the Win32 NLS APIs.

Now there is one use for them in Win32 -- resource loading. You can use neutral LCIDs either to more accurately tag resources or to provide an easy fallback mechanism. Of course, if you want to put names on them then you cannot use GetLocaleInfo since asking for the LOCALE_SLANGUAGE of LANG_ENGLISH will give you "English (United States)" which is probably not what you wanted.

(In fact, I wonder what Visual Studio's resource editor does for its strings for these neutrals -- it must have its own strings somewhere, hard coded? Ick!)

In retrospect, it might have been a better idea to not do things that way, but it has shipped this way for at least the last ten versions of Windows. So we are kinda stuck with it.

Anyway, thats neutral locales -- at best, they are tolerated. But you can't really do much with them. Using that ConvertDefaultLocale-ish behavior can actually get you unexpected results sometimes, too. More on this another day.

This brings us to neutral cultures....

In the .NET Framework, a neutral CultureInfo mostly does not do this weird implied LCID fallback thing. There is actual data behind these culures that you can query and use -- and you can get back the actual names and everything. It also does a great job on the resource loading fallback -- using the CultureInfo object's Parent property. The parent property is not based on LCID tricks, either -- it's actual planned data for each culture. Obviously much cooler and a bit more thought out.There is even a CreateSpecificCulture method on a CultureInfo that does the same sort of thing as ConvertDefaultLocale, creating a specific culture from a neutral one.

A lot of you probably noticed where I said "mostly" in that last paragraph (an occupational hazard of having readers who can be as cynical as I am!). Unfortunately, that weird LCID-esque fallback behavior still basically happens for collation and encoding via the culture's CompareInfo and TextInfo objects. Which is not such a big deal, and it is really necessary since both of those objects need the context of a specific culture. 

In retrospect, it might have been a better idea to not do things that way -- CompareInfo and TextInfo should not have been made available (as happens for other objects like the associated DateTimeFormatInfo and NumberFormatInfo), but it has shipped this way for two versions so we are kinda stuck with it.

One important difference that distinguishes them from neutral locales is that one could create a class that is derived from CultureInfo that contains language-specific information which would make more sense in neutral cultures, which is really a fancy way of saying "language-only cultures" (which is itself kind of a fancy way of say something).

There are also some odd situations with the LCID property of the CultureInfo, but thats a separate issue. More on this another day, too.

So, thats neutral cultures. Mostly not useful, except for resources -- except in the same way that they are useful in Win32 (by pretending its a specific culture). Or for potential extensibility either by Microsoft or by developers in the future.

Three steps forward, one step back? :-)

This post brought to you by "" (U+264e, a.k.a. LIBRA)

# Luc Cluitmans on 29 Dec 2004 1:28 AM:

Quote: "So, thats neutral cultures. Mostly not useful, except for resources".

Mostly not useful? I use them all the time!

The software I write, though usually using english as a user interface language, has to run on computers with different locale settings (mostly UK English and Finnish in our case).
If I export data in a text format on one computer, which happens to use a comma as its default 'decimal point', I still need to be able to read that data on computers that use a dot as decimal point. And I cannot always control the application that writes the data, so either decimal separator may occur in the input.
The only way I have found to reliably parse such data is to simply assume that there are no thousands separators, use String.Replace() to replace any commas with dots, and use the Neutral culture (which uses a dot as decimal separator) to parse the numbers.
In reverse, when writing data, I try to standardize the output format, and I do so by using the number formatting as dictated by the neutral culture (and use the 's' format for DateTime).
Also, several blogs have warned about not passing a culture to String.ToLower or String.ToUpper: not passing any culture there will give different results on different computers; passing the neutral culture at least gives a consistent result.
As for context, all these operations are used for transforming data from one data format mostly intended for computer consumption to another data format mostly for computer consumption. Presenting data to the user in his 'own' culture is not an issue here.

# Michael Kaplan on 29 Dec 2004 2:30 AM:

Actually, that would be a misuse of the neutral culture. Neutral cultures do not provide valid or consistent formatting/parsing results.

If you need results that do not vary with user preference or machine setting, then the invariant culture is what you need to use.


# Panos Theofanopoulos on 29 Dec 2004 5:51 AM:

Michael : Infact BCL Component model is not using InvariantCulture but does it's comparisons using OrdinalIgnoreCase. What is the difference between OrdinalIgnoreCase and case insesitive comparisons using InvariantCulture ? Why we need both ?

btw if anyone finds my suggestion reasonable
please vote for it

# Michael Kaplan on 29 Dec 2004 7:42 AM:

The question that Luc raised was related to formatting, not comparison.

But to answer your question -- the OrdinalIgnoreCase type comparison does not use linguistic tables at all. It is basically a binary comparison with a quick case ignorer. So it is faster if you do not care about the right thing happening linguistically.

I will be talking about this one more in a future posting. :-)

# Michael Kaplan on 29 Dec 2004 8:04 AM:

Added to the suggestion list at:

# Panos Theofanopoulos on 29 Dec 2004 8:20 AM:

> So it is faster if you do not care about the right thing happening linguistically

That means that InvariantCulture does the right thing linguistically ?
Who can validate that it does if it's Invariant ? ;-)

# Michael Kaplan on 29 Dec 2004 8:39 AM:

I'll cover what I meant in that other post -- which I will probably do next. :-)

# Luc Cluitmans on 30 Dec 2004 12:34 AM:

Quote: "If you need results that do not vary with user preference or machine setting, then the invariant culture is what you need to use."

Oops, my bad. I mixed up the Neutral culture and the Invariant culture - I am using the Invariant culture in my code of course, I just didn't realize that the 'neutral' culture was a different beast than the 'invariant' culture...

# Michael Kaplan on 30 Dec 2004 12:45 AM:

Ah, no worries. This stuff could be much less confusing, if you ask me. :-)

# Andy on 25 Jan 2005 4:40 PM:

I appreciate this article. I was looking for something that did what CreateSpecificCulture does, but I didn't know what it was called since I hadn't used it before. The rest of the article was interesting as well.

In this case, the site was of certain value.



referenced by

2011/03/16 Reporting one casualty in the operation; luckily it was the stupidest member of the unit

2007/07/15 Neutral? I do not think that word means what you think it means!

2006/11/07 How ConvertDefaultLocale sorta broke backward compatibility in Vista, and why

2005/08/31 Sometimes it *does* pay to be neutral

2005/07/05 Change is in the cards for ConvertDefaultLocale....

2005/06/13 Using full locales rather than the neutral ones?

go to newer or older post, or back to index or month or day