- Uses for Custom Cultures
- Using CultureAndRegionInfoBuilder
- Installing/Registering Custom Cultures
- Uninstalling/Unregistering Custom Cultures
- Public Custom Cultures and Naming Conventions
- Supplemental Substitute Custom Cultures
- Custom Culture Locale IDs
- Custom Culture Parents and Children
- Support for Custom Cultures
- Supplemental Custom Cultures
- Culture Builder Application Sample (CultureSample)
- Combining Cultures
- Exporting Operating System-Specific Cultures
- Company-Specific Dialects
- Extending the CultureAndRegionInfoBuilder Class
- Custom Cultures and .NET Framework Language Packs
- Custom Cultures in the .NET Framework 1.1 and Visual Studio 2003
- Where Are We?
Custom Culture Locale IDs
Another difference between supplemental custom cultures and replacement custom cultures is their locale ID (i.e., CultureInfo.LCID). CultureAndRegion InfoBuilder.LCID is read-only. Replacement custom cultures use the same locale ID as the cultures they replace. This is helpful because it means that there is no back door to the original culture. In the following example, both lines result in the same CultureInfo:
CultureInfo cultureInfo1 = new CultureInfo("en-GB"); // The LCID for en-GB is 2057 CultureInfo cultureInfo2 = new CultureInfo(2057);
In almost all cases, this behavior is desirable. It does mean, however, that it is not possible to create a CultureInfo for the original replaced culture, even if you wanted to. If this were absolutely necessary, you would have to save the replacement custom culture to an LDML file, unregister it, create an original CultureInfo object, extract the information you need, and then load the LDML file and register the replacement custom culture again.
Supplemental custom cultures all have the same locale ID: 0x1000 (4096). So the "bn-BD"(Bengali (Bangladesh)) locale ID is 4096, and the en-GB-Acme locale ID is also 4096. Consider the following test for equality for these two cultures:
CultureInfo cultureInfo1 = new CultureInfo("bn-BD"); CultureInfo cultureInfo2 = new CultureInfo("en-GB-Acme"); if (! cultureInfo1.Equals(cultureInfo2)) MessageBox.Show("CultureInfo objects are not the same");
The CultureInfo.Equals method reports that these cultures are not equal, even though their LCIDs are the same. Two CultureInfo objects are considered equal in the .NET Framework 2.0 if they are the same object or their Names and CompareInfo objects are the same. This contrasts to the .NET Framework 1.1 implementation, which is simply based upon a comparison of LCIDs, not object references or Names.
Also note that because all supplemental custom cultures share the same LCID, it is not possible to create a supplemental custom culture using its LCID. The following code results in an ArgumentException ("Culture ID 4096 (0x1000) is not a supported culture"):
CultureInfo cultureInfo1 = new CultureInfo(4096);
This is one of the reasons why you should treat LCIDs as a legacy feature or for use with Win32 APIs. You should also conclude from this that if you store the identities of cultures in a database or configuration file, your method should always be capable of storing the culture name instead of the culture LCID for custom cultures. Recall from the "Alternate Sort Orders" section of Chapter 6 that the .NET Framework 2.0 supports the creation of cultures with alternate sort orders using string identifiers (e.g., "es-ES_tradnl") in addition to LCIDs; it should be apparent that, when using the .NET Framework 2.0, you should always store culture identifiers using strings, not integers. If you want to enforce this in your applications, look at the "CultureInfo must not be constructed from LCID" and "RegionInfo must not be constructed from LCID" FxCop rules in Chapter 13, "Testing Internationalization Using FxCop."
Before we leave the subject of alternate sort orders, it is worth pointing out that because the custom culture mechanism is based upon culture names and not culture LCIDs, it is not possible to create replacement custom cultures for a culture with an alternate sort order. However, you can create a "supplemental substitute" custom culture for an alternate sort order:
// create the es-ES culture with the Traditional sort order CultureInfo cultureInfo = new CultureInfo("es-ES-Tradnl"); RegionInfo regionInfo = new RegionInfo(cultureInfo.Name); CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("es-ES-Tradnl-Acme", CultureAndRegionModifiers.None); // load in the data from the existing culture and region builder.LoadDataFromCultureInfo(cultureInfo); builder.LoadDataFromRegionInfo(regionInfo); // make custom changes to the culture ... ... builder.Register();