Home > Articles > Programming > Windows Programming

This chapter is from the book

Installing/Registering Custom Cultures

The CultureAndRegionInfoBuilder Register method performs two actions:

  • Creates an NLP file in the system's Globalization folder
  • Adds an entry to the Registry in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Nls\IetfLanguage

The NLP file is a binary representation of the custom culture. No API exists for this file format, so you must treat it like a black box. The file is placed in %WINDIR%\Globalization and given the same name as the custom culture—e.g., c:\Windows\Globalization\en-GB.NLP.

The Registry entry provides the IetfLanguage name for the custom culture for static CultureInfo methods. The key is the custom culture's IetfLanguage, and the value is the semicolon-separated list of custom culture names that share the same IetfLanguage. After the call to Register in the example, there will be an entry with a key of "en-GB" and a value of "en-GB", indicating that the en-GB custom culture has an IetfLanguage of "en-GB".

This approach is fine for registering the custom culture on your own machine, but it isn't very generic. If you want to create three custom cultures—say, en-GB, fr-FR, and es-ES—on your users' machines, you would have to either create one application, called, for example, CreateAndRegisterAllThreeCultures, or create three separate applications—such as Create_enGB_Culture, Create_frFR_Culture, and Create_esES_Culture. A better solution is to create a single custom culture registration program and pass it custom culture files. In the source code for this book, you will find the RegisterCustomCulture console application, which exists for this purpose. RegisterCustomCulture accepts one or more LDML custom culture files to register. LDML is the Locale Data Markup Language and is defined in Unicode Technical Standard #35 (see http://www.unicode.org/reports/tr35/). It is an extensible XML format for the exchange of structured locale data, and it is the format that Microsoft chose for importing and exporting custom cultures. Although LDML is clearly defined by the Unicode Consortium, there is wide variation in its use. If you intend to use LDML files created by sources other than the Culture AndRegionInfoBuilder, be prepared to modify the LDML before it can be consumed by a CultureAndRegionInfoBuilder. An LDML file can be created using the CultureAndRegionInfoBuilder.Save method, so the previous example could be rewritten like this:

CultureAndRegionInfoBuilder builder =
    new CultureAndRegionInfoBuilder("en-GB",
    CultureAndRegionModifiers.Replacement);

builder.GregorianDateTimeFormat.ShortTimePattern = "HH:mm tt";

builder.Save("en-GB.ldml");

This code would become part of the application's build process, resulting in the en-GB.ldml file, which would become part of the application's installation process. The file can be loaded simply by using the CultureAndRegionInfoBuilder.CreateFromLdml method:

CultureAndRegionInfoBuilder builder =
    CultureAndRegionInfoBuilder.CreateFromLdml("en-GB.ldml");

builder.Register();

The important parts of the RegisterCustomCulture console application are shown here:

static void Main(string[] args)
{
    Console.WriteLine("RegisterCustomCulture registers custom" +
        " cultures for the .NET Framework from LDML/XML files");
    Console.WriteLine("");
    if (args.GetLength(0) == 0)
        // no parameters were passed – show the syntax
        ShowSyntax();
    else if (AllFilesExist(args))
    {
        // file parameters are all good – register the cultures
        RegisterCustomCultures(args);
    }
}

private static void RegisterCustomCultures(
    string[] customCultureFiles)
{
    foreach (string customCultureFile in customCultureFiles)
    {
        if (customCultureFile.StartsWith("/u:") ||
            customCultureFile.StartsWith("/U:"))
        {
            // unregister the culture
            string customCultureName =
                customCultureFile.Substring(3);

            CultureAndRegionInfoBuilder.Unregister(
                customCultureName);

            Console.WriteLine("{0} custom culture unregistered",
                customCultureName);
        }
        else
        {
            // register the culture
            CultureAndRegionInfoBuilder builder =
                CultureAndRegionInfoBuilder.CreateFromLdml(
                customCultureFile);
            builder.Register();

            Console.WriteLine(
                "{0} custom culture registered", customCultureFile);
        }
    }
    Console.WriteLine("");
    Console.WriteLine("Registration complete.");
}

The RegisterCustomCulture application simply iterates through each of the command-line parameters. If the parameter starts with "/u:", it attempts to unregister an existing custom culture; otherwise, it attempts to load the parameters as LDML files and then register them.

It is worth noting, however, that as the Register method writes to the Registry and to the system's Globalization folder, any code that uses it requires administrator rights to execute. This means that if you intend to deploy applications that use custom cultures, the application that creates the custom cultures (e.g., Register-CustomCulture.exe) must obviously have administrator rights (no additional rights are required to simply create CultureInfo objects from custom cultures, however). If you deploy your Windows Forms applications using ClickOnce, you should create your custom cultures using the ClickOnce Bootstrapper because the ClickOnce application itself will not be granted administrator rights.

  • + Share This
  • 🔖 Save To Your Account