Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

.NET XML Based Localization

0.00/5 (No votes)
30 Jul 2008 1  
An article on .NET localization

Introduction & Background

During the development of my pet project, I had to solve the problem of localization. C# offers an almost perfect solution for it. If your form(s) Localization property is set to true and you give the default language, studio (or C# express) will generate a series of localizable text properties of your components, which are deployed in the project. You can edit the values in a table by you double-clicking on the *.resx file. Furthermore the editor generates a Resourcename.Designer.cs file, which contains the localized properties as static members of a class, called as the “resourcename”.

This allows for referring to any of the text values via a unique static property, to find the appropriate string values of your variables, based on the CultureInfo properties (for details please refer to the msdn). If you would like to give an additional language to your project, you have to create a new .resx file with the same name, but the name must contain the culture id. For example: LocalisationSample.resx (default resx file), LocalisationSample.en-EN.resx (English version).

Now if your project is recompiled, and the OS language settings are changed from your default language (Hungarian in my case) to English, all the translated text will be displayed in English.

Although this is a robust solution for the localization problem, I have some extra demands:

  • I wouldn’t like to recompile the project to add new languages.
  • I wouldn’t like the code size and compilation time increased by new languages.
  • I want to provide facility to the user to translate displayed texts to any language.

Result

To satisfy the above requirements, the data must be stored in a user editable XML file (.resxml). The file name of these files are created according to the following rule:

filename + _lang + .resxml, e.g.
MyResources.resxml -> English
MyResources_hu.resxml -> Hungarian

The structure of the resxml file is really simple; the following example (Fruits.resxml) contains (ids, values, description) triplets for some fruits:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <it id="APPLE_ID" value="apple" description="my favorite fruit" />
  <it id="PEAR_ID" value="pear" description="a sweet fruit" />

</root>

A static class RManager is defined, which is able to load the appropriate resxml files based on the language setting at the very beginning of the execution of your application. This class must be included in your project. To use the string variables (static properties) as global variables, an additional static class called “filename” in a filename.cs (Fruits.cs in the sample) file should be defined.

/*RMTool 1.0 generated file, do not edit!*/
using RMTool;
using System.ComponentModel;

namespace FruitsNm{
    public static class Fruits
    {
        ///<summary>
        // my favorite fruit
        ///</summary>
        public static string APPLE_ID { get { return RManager.GetValue("Fruits",
            "APPLE_ID"); } }

        ///<summary>
        // a sweet fruit
        ///</summary>

        public static string PEAR_ID { get { return RManager.GetValue("Fruits",
            "PEAR_ID"); } }

    }
} /* end of file */

To simplify the generation of resxml file and static class, I developed a free tool, called RMTool. This tool displays the data triplets (id (Name), value (Text), description) in a table of the selected resxml file.

rmtool.JPG

The Interface helps to manage, generate and translate your resource files.

Using the Code

I created a new project, and I put a Label in the Form1.

After the RManager.cs, Fruit.cs files were added to the project, and the RMTool and FruitsNm namespace were referred in the Form1 file, I was able to assign APPLE_ID language dependent string value to the Text property of label1.

The source code, the constructor of Form1:

public Form1()
{
    InitializeComponent();

    // the path of the application exe,
    // the Fruits.resxml resource file
    // is stored in this directory
    string AppPath = 
        Path.GetDirectoryName(Application.ExecutablePath);
    // get Fruits.resxml           
    RManager.GetFiles(AppPath, "");
    label1.Text = Fruits.APPLE_ID
}

and the result:

result.JPG

Summary

I presented an alternative way to the solution of the localization problem. In this way your project size and the compilation time won’t increase with new language resources, since they are stored in different XML files (resxml), which are dynamically loaded during the execution of the application. I also provided a tool to facilitate the development of resource files.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here