- 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?
Public Custom Cultures and Naming Conventions
The custom cultures that you create using the .NET Framework 2.0 are all public. This means that they are available to all users of all .NET Framework 2.0 applications on the machine on which they are installed. There is no concept of a private custom culture in functional terms. Let's consider what this means for a moment. The Registry key is public; the NLP file is placed in a public location; and the culture's name is public. This means that the cultures that you create live in the same space as the cultures that everyone else creates. We've seen this scenario before with DLLs, and it was often referred to as DLL Hell. Welcome to Custom Culture Hell.
The problem here is that when you create a custom culture and install it on a machine, you don't know if someone else has already created a culture with the same name or if in the future someone will create a culture with the same name. This is especially a problem with replacement cultures, such as the one in the first example. The new en-GB culture simply modifies the short time pattern. If someone else, possibly from another company, had already created an en-GB culture on the same machine, then your attempt to register your en-GB culture would fail because a custom culture with that name already exists. At this point, you have two choices:
- Don't install your culture. Respect the original application's en-GB culture and hope that it doesn't prevent your application from working properly.
- Go ahead and overwrite the custom culture with your custom culture.
The first approach represents the very definition of optimism. The second approach will give you the kind of reputation that was given to vendors when they overwrote existing DLLs in the DLL Hell scenario. Alternatively, consider what would happen if your application was installed on a machine first. All would be well right up until the second application overwrote your custom culture with its definition of the same culture. That application would function correctly. The best-case scenario for your application is that it would fail. The worst-case scenario is more likely: Your application would continue to function but would be incorrect.
A number of limited solutions exist, depending on whether you are creating a replacement custom culture or a supplemental custom culture. Let's start with supplemental custom cultures. A supplemental custom culture is a completely new culture that the .NET Framework and the operating system have not seen. The best solution here is to solve the problem by avoiding the problem (this is often my favorite solution to any problem). The solution lies in using a naming convention in which uniqueness is built into the name. A simple solution would be to suffix the culture name with your company's name. So if you create a supplemental custom culture for Bengali as spoken in Bangladesh (i.e., "bn-BD") and your company is the Acme Corporation, you would name the culture "bn-BD-Acme". Alternatively, you could take a more certain but completely unreadable solution of suffixing with a GUID—e.g., "bn-BD-b79a80f4-2e22-4af5-9b79-e362304b-5b10" (note that the GUID has been split into chunks of eight characters or less). The naming convention solution also has the benefit of being future-proof. Change is certain. Microsoft will add new cultures to Windows. If Microsoft adds the bn-BD culture to Windows, code that creates a custom "bn-BD" culture that used to work will throw an exception in the CultureAndRegionInfoBuilder constructor:
CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("bn-BD", CultureAndRegionModifiers.None);
If the culture name is suffixed to make the culture name unique, it cannot clash with new cultures or other companies' custom cultures. The downside to this naming is that it is a considerable abuse of the IETF tag that the suffix replaces. You must decide which is the lesser evil.
On the subject of supplemental custom culture names, the IETF defines a prefix ("x-" or "X-") that should be used for what are called "private" cultures (e.g., "xbn-BD"). Don't be confused by the use of the word "private"—the cultures are still publicly available to all .NET Framework 2.0 applications. The difference is that, by prefixing the culture name with the "x-" prefix, a statement is made that the culture is for "private" use—i.e., the use of one or a limited number of applications. This prefix also solves the problem that if Microsoft introduces a culture for the same language/region, no clash will occur (because Microsoft's culture will not have the "x-" prefix). The prefix solution represents a halfway house. It solves part of the problem. Of course, if another application attempts to install a culture for the same language/region and uses the same name (including the prefix), then a clash will still occur.
If you are creating a replacement culture, such as en-GB, your options are quite limited. If it is truly to be a replacement culture, changing the name is not an option. One option is to set up or seek out a public registry on the Internet for replacement custom cultures. If such a registry exists, it could be used to track requests for changes to existing cultures and offer a "standard" replacement culture upon which well-behaved applications could agree. The "standard" replacement culture would be the sum of all agreed-upon changes. Such a co-operative solution is optimistic and not guaranteed, and can be seen as only a "gentleman's agreement." Alternatively, you could simply overwrite the opposition's replacement culture with your own. Immediately before your call to CultureAndRegionInfoBuilder.Register, you would add the following code:
try { CultureAndRegionInfoBuilder.Unregister("en-GB"); } catch (ArgumentException) { }
This code attempts to unregister any existing en-GB culture and ignores any exception that would result from an existing en-GB replacement culture. If you choose this approach, be prepared for some hate mail. The only guaranteed solution is to use a supplemental custom culture instead of a replacement custom culture, and use the previously suggested naming convention to avoid a clash. The custom culture would then be called something like "x-en-GB" or "en-GB-Acme" instead of "en-GB". The obvious downside to this solution is that the custom culture is no longer a replacement custom culture. This means that your application would need to take certain steps to ensure that the x-en-GB or en-GB-Acme culture was used instead of the en-GB culture.
Regardless of how you approach this problem, you should be aware of the limits on custom culture names. The maximum length of a custom culture name is 84 characters, and each "tag" within the name is limited to 8 characters. A "tag" is a block of letters and numbers that is delimited by a dash ("-") or an underscore ("_"). So a name of "en-GB-AcmeSoftware" is invalid because the "AcmeSoftware" tag is 12 characters long. You can work around this by delimiting words using dashes or underscores (e.g., "en-GB-Acme-Software" or "en-GB-Acme_Software").