oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

.NET Localization, Part 3: Localizing Text

by Satya Komatineni


Localization is a process by which you allow people of different cultures, languages and nationalities access your Web site. Although still a difficult process, all things considered, it is gradually becoming easier. Both the Java platform and the .NET platform have some nice features to aid localization. For instance, all strings, dates, and numbers are internally locale aware and when printed or validated will honor the localization setting.

The main topic of this article is localization of text. Text localization is typically the easier of the many efforts involved in the localization process. You simply use textual keys, and the system can load these keys from resource files using utility classes. If it is that simple, then, what is the need for this writeup? Writing a line of text in multiple languages is fairly trivial. But doing that for hundreds of pages in a language-dependent way requires a process, standards, and architecture. This is similar to scaling a dog house to a multi-story building.

What follows is a discussion of process recommendation and necessary tools for helping the localization of text under .NET.

Localizing Text

It is known that for localizing text, one would use the resource managers available under .NET. These resource managers use the main assembly and language based satellite assemblies to retrieve the string resources. A main assembly is basically your main executable file, if you are writing standalone executables. When you are writing a Web application or a Web service, this main assembly will be a DLL that is accessible by IIS. A satellite assembly is a DLL that contains only resource strings. You typically have one satellite assembly DLL for each language. Because these satellite assembly DLLs are separated from the main assembly (an .exe or DLL), it is easier to drop in multi-language support as you progress in your development process.

Related Reading

.NET Framework Essentials
By Thuan L. Thai, Hoang Lam

Based on documented literature, it is not hard to build text localization using a single resource file for the entire project. When the project has multiple modules and multiple people working on it, a single resource file will present the following difficulties:

  1. Too many entries in one file.
  2. Check-in/checkout contention for multiple developers.
  3. Difficulty in finding the text string keys that you want.

The solution is to allow multiple resource files: one for each module, or even one for each page. One would think that the resource files that get automatically generated by the IDE could be used for this purpose. But these autogenerated files are hidden, and there is no easy API to retrieve resources from multiple resource files. It is not hard to unhide these hidden per-page resource files. Even if you were able to put your resources in these resource files, these resource files may change as you change your GUI. This will make it difficult to ship these resource files to translators as they change often, not necessarily because of text strings, but because of other factors. I don't think this dependency is good; it may be better to just leave them hidden.

Whichever mechanism that we are going to adapt for multiple resource files has to be simple enough for the developer and the language translator to adapt. There is a beta tool from Microsoft called "Enterprise Localization Toolkit," based on SQL server, that will supposedly simplify this process. If you are considering using this tool, then it is well and good. But if for whatever reason, you want to roll out a less encompassing solution read on.

The following points are important to consider when you are designing a localization process:

  1. Developer access to localized keys.
  2. Developer utilities to retrieve localized keys.
  3. Developer access to localized resources for updating.
  4. Transcriber access to localized resources.
  5. Making satellite assemblies.
  6. Recommended conventions.

Developer Access to Localized Keys

You have just created a new Web page and about to enter a text string, and the localization chief looks over your shoulder and says, "Ha! My friend, you can't hard code the static text like that. You need to look up an equivalent key so that we can localize that text string." Now you have to invent a new key, or worse yet, look for an existing key, if it is already available. Here are these issues, itemized:

  1. Find a key for a text string.
  2. You don't want to misspell keys.
  3. You don't want to invent new keys when they are already available. For example, you don't want 10 different keys for the same localized "Cancel" button.
  4. You want the compiler to prompt you for these keys.
  5. You want keys for your own modules isolated from other keys.
  6. You want an easy way to substitute the string value of the key in your dialog boxes, Web pages, etc.

1. Create the Following Subdirectories Under Your Project Directory

To accomodate the above needs let us start with a directory structure for our resource-related files under the a fictitious project called "MyWebProject":


The keys subdirectory will have files to identify your keys for localized content. The files subdirectory will hold the actual resource files.

2. For Each Module in Your System, Create the Following Files

(Taking "Common" as an example) 

            \one .cs file for each module
            \one .resx file for each module

CommonKeys.cs is a C# file containing project-level common definitions for the whole project, whereas module1keys.cs contains keys for your specific module. On the other hand, CommonResources.resx is an XML-based resource file that acts as a dictionary for the keys that are identified in the CommonKeys.cs key file. Easy enough so far.

3. Source Code for Your modulekeys.cs File

Let us take a look at the contents of the CommonKeys.cs file to fully understand the key definitions. Notice that the keys themselves are strings; it is important to define constants for these strings so that we don't make mistakes misspelling these keys. The provided structure for the CommonKeys.cs file will allow the IDE to prompt us for the available keys. What about root? This reserved key will define a naming context for our keys so that they are less likely to be duplicated. By convention, it can also point to the name of the module. By doing this, we can deduce the resource filename for a given resource key, without explicitly specifying the resource file from which the key originates. This property could be useful when it is time to retrieve the keys.

namespace SKLocalizationSample.resources.keys  
    public class CommonKeys  
    public static string root = "Common";  
    public static string FILE = root + ".FILE";  
    public static string NEW  = root + ".NEW";  
    public static string SAVE = root + ".SAVE";  
    public CommonKeys(){}  

4. How Can I See My Available Modules?

As new developers come on board and are given responsibility for existing modules or new modules, they can find out about resources for their respective modules by looking up the following directory:


This will tell them the available modules for which keys are defined, which will tell them either to create a new file or use an existing file. When they define keys in these key files, they are also responsible for going over to the \resources\files\ directory and updating the corresponding .resx files with proper English values for their keys.

Pages: 1, 2

Next Pagearrow