By Tim Landgrave
If you plan your applications to include support for an international audience, the cost to develop them isn’t much more than developing an English-only version. But if you need to retrofit an existing application, the cost can be as much as for the development of the original application.
The .NET Framework has built-in support for globalization in its System.Globalization namespace that can help you build international support into your applications. This namespace includes classes for handling many key globalization issues such as culture-aware string comparisons, date and time formatting, numeric formatting, and calendar support for both Gregorian and non-Gregorian calendars. The key class that you need to understand first is the CultureInfo class.
Using the CultureInfo class
The CultureInfo class provides support for cultural preferences and can be controlled on a per-thread basis. The CurrentCulture property handles date and number formatting, string comparison, and casing. The CurrentUICulture property can be set by the developer and used by the CLR to load the proper resources for the user interface. You can use the CultureInfo class to set the CurrentCulture and CurrentUICulture explicitly for the current thread, like this:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja")
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP")
Also, some APIs can use the CultureInfo class to control the output:
Str = DateTime.Now.ToString(cultureInfo);
All culture-aware classes are culture-sensitive by default, so simply setting the culture of the current thread will automatically give you culture-specific support for classes such as CompareInfo, StringInfo, and Calendar in the System.Globalization namespace and core system classes such as Resources, DateTime, and String.
To support the largest number of cultures, you’ll also want to use Unicode strings everywhere in your application. The .NET Framework includes support for Unicode throughout, but you still need to write code with an understanding that all strings use Unicode formatting. And be aware that many operating system-dependent operations (including file system access and many controls) don’t support Unicode strings, so you’ll have to make explicit conversions to perform these operations.
Planning for localization
Globalization will present some key data in familiar international formats, but if you want users to have applications that are very specific to their culture, you’ll need to localize your application. Localization involves creating specific resources for specific cultures and then writing your application so that it loads the appropriate resource for a culture that the application either sets or detects. Let’s look at the resource model in more detail.
The .NET Framework’s resource model includes support for any serializable object and can be extended to support new formats. This means that in addition to culture-specific text strings for prompts, labels, and other UI elements, you can also use sound, images, and other binary data as a resource. The resource model is supported for ASP.NET applications and Windows Forms, including the .NET Compact Framework—with some limitations based on the size of the runtime and the memory on the device.
To build a localized application, you have to identify the culture-specific resources you need to deploy and then put them in a resource file. For simple applications that require only string resources stored as name/value pairs, you can create culture-specific text files. Although this makes for an interesting demonstration, you should create your resource files using the Microsoft ResX format. Visual Studio includes tool support for creating the .resx file that includes an XML-formatted description of the resource and the .resources file that includes the binary compiled file. You can either distribute these files with your application or compile them into a satellite assembly.
You should use consistent naming and storage conventions for your resource files. Microsoft recommends that you name your .resources files with the culture embedded in the filename (e.g., <myproject>.<xx-XX>.resources), with one resource file for each culture you will support. Satellite resource assemblies should be named with just the project name (e.g., <myproject>.resources.dll) and then placed in a different subdirectory for each culture. These directories can either be neutral cultures (e.g., \fr\myproject.resources.dll) or specific cultures (e.g., \fr-FR\myproject.resources.dll).
Using resource files at runtime
Once the resource files are created, you use the resource manager to load strings and objects at runtime. Resources can either be loaded based on the CurrentUICulture setting for the CurrentThread (e.g., RM.GetObject("Button1.Cursor")), or you can specify a culture when loading a resource (e.g., RM.GetString("mystring", new CultureInfo("en-NZ")).
The resource manager is available for ASP.NET applications, .NET Compact Framework applications, and Windows Forms applications. And the Windows Forms engine provides some additional localization support. Every form has a localizable property that can be set. When set to True, the project system automatically keeps track of different language versions of a form and builds the different language forms into satellite assemblies.
Building international applications isn’t much more difficult than building single-culture applications as long as you plan for localization in your original design. .NET architects should ask specific questions regarding the anticipated support for other cultures before building an application that assumes an English-only UI.