Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C#
Article

.NET XML Based Localization

Rate me:
Please Sign up or sign in to vote.
2.60/5 (7 votes)
30 Jul 2008CPOL3 min read 38.5K   519   13   5
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
<?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.

C#
/*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:

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 3 Pin
Pedro Minatel2-Mar-11 23:39
Pedro Minatel2-Mar-11 23:39 
GeneralBug Pin
TwilightSora10-Nov-09 5:46
TwilightSora10-Nov-09 5:46 
GeneralBest Localization Plug-in for Visual Studio. Pin
Alexander Nesterenko17-Dec-08 21:46
Alexander Nesterenko17-Dec-08 21:46 
GeneralInteresting Pin
merlin98131-Jul-08 3:53
professionalmerlin98131-Jul-08 3:53 
Interesting idea, but you should show how you determine which language you need to load.



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LINQ Exchange - Learn about LINQ and Lambda Expressions
Gamehaxors.com - Bots, sploits, and How Games Work
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GeneralRe: Interesting Pin
szgerg4-Sep-08 6:29
szgerg4-Sep-08 6:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.