Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

How To Translate Your Forms Application

4.22/5 (11 votes)
7 Apr 2010Ms-PL3 min read 1   533  
Translate your forms application to multiple languages with ease

Introduction

Translating your application to multiple languages can be very hard. Fortunately, with this code you will just have to write the translated version of each sentence in a text file.

Small note: Please excuse me for providing you with a Visual Studio 2010 solution, you can modify it by opening it in Notepad and changing 2010 to 2008. It will work just fine.

How It Works

When you call the Translate("Language Here") method, the application checks if that selected language exists. By "exists", I mean if there is any text file with the translations in the "Languages" folder. If the language exists, it opens the text file, reads the data and starts translating. If not, it creates the text file.

That text file will contain the text of all the controls on your form, followed by an equal sign. What is before the equal sign is the original text, and what is after is the translated word. Write the translation after the equal mark, and then call the Translate() method again. You will see that your controls' text will be changed.

Using the Code

The code is well commented, but you still need to know the order of execution.

I started by writing the constructor:

C#
public Translator(Form toTranslate, string defaultLanguage)
{
    //Initializing variables
    mainForm = toTranslate;
    Default = defaultLanguage;
    CurrentLanguage = defaultLanguage;
            
    //Creating languages directory if it does not exist
    if (!Directory.Exists("Languages"))
    {
        Directory.CreateDirectory("Languages");
    }

    //We translate to the default language
    Translate(Default);
}

When we initialize the translator, we will have to pass as parameters the form we want to translate, and our default language.

We translate to the default language because, if this is the first time we call the method, the default language file does not exist. We will use the language file with the default language as a point of reference when translating from a language to another. Let's say I translate from French to Japanese, I need to translate to the default language first, and then to Japanese. Therefore, we will have a file with the default language that will contain the same words to the left and right of the equal mark.

Next, the variables we will use:

C#
//These variables hold the values 
//of the form we want to translate, the default 
//language, and the current language
Form mainForm;
string Default;
string CurrentLanguage;

//This is used in the words array
struct wordsList
{
    public string Original, Translated;
};

The wordsList struct is for a easier usage of the Words[] array.

The rest of the code works like this:

In the Translate() method, we check if the current language is the default language. If it isn't we translate it to the default language. If it is, then we check if the language we selected exists. If it does, we open the text file with the translation, and we load the lines into the Words[] array:

C#
//Reading data from text file
StreamReader langIn = File.OpenText("Languages\\" + Language);
//While not end of file, we read the lines
//in the Words array
while (!langIn.EndOfStream)

{
string Line = langIn.ReadLine();
Words[number] = new wordsList();
Words[number].Original = Line.Substring(0, Line.LastIndexOf("="));
Words[number].Translated = Line.Substring(Line.LastIndexOf("=") + 1);
number++;
}

langIn.Close();

We incremented the size of the Words array as we add items to it. The words to the left of the equal mark in the text file are the original words, and the one to the right, the translated version.

After we load the words, we loop through each control on the form and check if any of the words match the text of the control. If it does, we change the text to the translated version:

C#
foreach (Control control in mainForm.Controls)
{
//We loop through all the controls
//and the words array, and if any of the 
//controls has the text property 
//to match the orginal word in the array,
//we replace it with the translated version
for (int i = 0; i <= number; i++)
{
if (control.Text == Words[i].Original)
{
control.Text = Words[i].Translated;
break;
}
}
}

Finally, we check if there are any new words on the form. We loop thorough the controls and check if any of the words match the text of that control. If no word matches the control's text, we add it to the Words[] array.

Later, we rewrite the text file with all the words array. This way, if the language file does not originally exist, we create it:

C#
bool newWords = false;
foreach (Control control in mainForm.Controls)
{
//We assume it's new
bool ok = true;
for (int i = 0; i <= number; i++)
{
//If the word exists or it is empty "", we skip it
if (control.Text == Words[i].Original || control.Text == "")
ok = false;
}
//If it's a new word, we add it to the array
if (ok)
{
newWords = true;
Words[number] = new wordsList();
Words[number].Original = control.Text;
Words[number].Translated = "";
number++;
}
}
//We save the new words if any
if (newWords)
{
StreamWriter langOut = new StreamWriter("Languages\\" + Language);
for (int i = 0; i <= number; i++)
{
langOut.WriteLine(Words[i].Original + "=" + Words[i].Translated);
}
langOut.Close();
}

While all of this might translate our controls, if we have a message box to show, MessageBox.Show("Hello World"); it will not be translated. The following code can be used to translate any string inside your source code:

C#
public string tr(string toTranslate)
        {
            wordsList[] Words = new wordsList[1000];
            int number = 0; //Counter for Words[]
            Words[number] = new wordsList();

            //Checking if language exists
            if (File.Exists("Languages\\" + CurrentLanguage))
            {
                #region Reading
                //Reading data from text file
                StreamReader langIn = File.OpenText("Languages\\" + CurrentLanguage);
                //While not end of file, we read the lines
                //in the Words array
                while (!langIn.EndOfStream)
                {
                    string Line = langIn.ReadLine();
                    Words[number] = new wordsList();
                    Words[number].Original = Line.Substring(0, Line.LastIndexOf("="));
                    Words[number].Translated = 
			Line.Substring(Line.LastIndexOf("=") + 1);
                    number++;
                }
                langIn.Close();
                #endregion
                #region Translating
                for (int i = 0; i <= number; i++)
                {
                    if (toTranslate== Words[i].Original)
                    {
                        return Words[i].Translated;
                    }
                }
                #endregion
                #region Adding to translation file                    
                StreamWriter langOut = new StreamWriter
				("Languages\\" + CurrentLanguage);
                for (int i = 0; i <= number; i++)
                {
                    langOut.WriteLine(Words[i].Original + "=" + Words[i].Translated);
                }
                langOut.WriteLine(toTranslate + "=");
                langOut.Close();
                #endregion
            }

            return toTranslate;
        } 

To use it:

C#
MessageBox.Show(translator.tr("Hello World"));

It will automatically translate it to the current language.

What is NOT Implemented

This current code will not translate menus or context menus. I am planning to complete this article once I write the code for the menus.

Also, you can't add words or sentences that contain the equal sign, because the words will be read wrong:

C#
string Line = langIn.ReadLine();
Words[number] = new wordsList();
Words[number].Original = Line.Substring(0, Line.LastIndexOf("="));
Words[number].Translated = Line.Substring(Line.LastIndexOf("=") + 1);
number++; 

I hope you enjoyed this article, more coming soon.

History

  • Apr/8/10 - Added the possibility to translate strings inside the source code.
    C#
    MessageBox.Show(translator.tr("Hello World")); 

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)