Click here to Skip to main content
13,296,407 members (48,113 online)
Click here to Skip to main content
Add your own
alternative version


23 bookmarked
Posted 25 Sep 2009

User-Defined Multi-Lingual Applications

, 25 Sep 2009
Rate this:
Please Sign up or sign in to vote.
Developing multilingual applications that allow users to create their own language files


A recent application of mine required multi-lingual capabilities. The user of the software is happy to provide the language-specific strings for his language. I just need to give him the file. Multi-lingual applications and localization are discussed in lots of places, but I've not seen any easy approaches whereby the end user can create his own language by simply creating and editing a new “language file”. This skin-able approach to language provides a great deal of user customization, yet minimal expense in terms of hiring translators.


This approach created an interesting programming challenge. What would this language file look like? How would the application load the language file and update the controls? What happens when I create new forms and controls in the future versions of the application (which have new text items) and the user is using an old language file? How do I access the “language library” from anywhere in my application without having to pass it from form to form?

These questions were basically answered by two words: Reflection and Singleton. OK, there are a lot more words that apply, but those were the two concepts that helped me finally get to a solution that I liked.
So without any further ado, here’s the approach.

  1. The LanguageLoader is a Singleton class that contains the applications strings and can read/write language files. This class can be accessed from anywhere in the project. If you update it from anywhere in the application, the updates are available elsewhere. This Singleton stuff is cool!
  2. You add strings to an “ApplicationStrings” class. This class is accessed by the LanguageLoader (for loading and saving) via reflection. This reflection stuff is pretty cool too!
  3. For easy updating of controls, it helps if each form has a method that updates all of the strings on the form. This method can be called in the form’s “Load” method and can also be called when the language is changed by the user.

Using the Code

So let’s do it:

  1. Create a Windows Forms Application.
    Let’s add a label. Visual Studio calls it “label1.”  I'm not feeling too creative, so let’s stay with that. We can also add a button and call it “button1”.

  2. Now for the fun part. Add LanguageLoader and IniAccess to the solution. In the LangaugeLoader file, fill in the default value for the strings. (Look for the ApplicationStrings class at the bottom of the file).

    The strings need to be of the format: ParentForm_StringName (more on this later):

    // This is at the bottom of the LanguageLoader.cs file:
    public class ApplicationStrings
        public String MainForm_Button1Text = "Click me for a new dialog/form";
        public String MainForm_Label1Text = "Hello, I'm a text label on the main form";
  3. To get these strings to show up on the main form, add this method.You can call it from the Form’s “Load” method or anytime you want to update the strings.
    // These are in the application’s main form source file:
    private void UpdateLanguageOnControls()
        // this function places language specific text on all "skin-able" text items
        button1.Text = LanguageLoader.appStrings.MainForm_Button1Text;
        label1.Text = LanguageLoader.appStrings.MainForm_Label1Text;
    private void Form1_Load(object sender, EventArgs e)

That’s basically it.  Once the application runs, the file “EnglishUS.lng” will be created in the application folder.  (Note: Vista may not allow the file to be written in the “Program Files” folder).

Creating a New Language

If you edit the LNG file (using NotePad or something similar), the edited strings will show up in the application. The language file is of the traditional INI format where each “section” is the name of the form and the “key” is the string’s name.  The section and key are extracted from the string variable’s name. Do you remember the ParentForm_StringName format from above? ParentForm becomes the section and StringName becomes the key.

-------- contents of EnglishUS.lng -------- 
Button1Text=Click me for a new dialog/form 
Label1Text=Hello, I'm a text label on the main form 

To create a new language, simply open an existing language file and save it as a new name and change the strings accordingly:

-------- contents of PigLatin.lng -------- 
Button1Text=ickClay emay orfay away ewnay ialog/formday 
Label1Text=elloHay, I'mway away exttay abellay onway ethay ainmay ormfay 

Applying the Language to a Dialog or Sub-Form

If a sub-form (dialog, etc.) needs language access, you can use the same approach that you used in the main form:

Add the sub-form’s strings to the ApplicationStrings class:

/// This is at the bottom of the LanguageLoader.cs file:
public class ApplicationStrings
    public String MainForm_Button1Text = "Click me for a new dialog/form";
    public String MainForm_Label1Text = "Hello, I'm a text label on the main form";
    // these are new strings to be used in the dialog
    public String DialogForm_Label1Text = "I'm the top label";
    public String DialogForm_Label2Text = "I'm the bottom label";

Put the strings on the form by creating and calling a “UpdateLanguageOnControls” method just like the one on the main form: 

// These are in the sub-form’s source file
// inside the DialogForm.cs file
private void UpdateLanguageOnControls()
    // this function places language specific text on all "skin-able" text items.
    label1.Text = LanguageLoader.appStrings.DialogForm_Label1Text;
    label2.Text = LanguageLoader.appStrings.DialogForm_Label2Text;

private void DialogForm_Load(object sender, EventArgs e)


So there it is: a quick (and perhaps dirty) approach to multi-lingual apps that allows users to create their own languages. I'd love your feedback so let the postings fly! Or in other words: oSay erethay itway isway: away uickqay and(ay erhapspay irty)day approachway otay ulti-lingualmay appsway atthay allowway usersway otay eatecray Special thanks to the Pig Latin converter at:


  • 25th September, 2009: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Mark C. Malburg
Software Developer (Senior) Digital Metrology Solutions, Inc.
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralA Good Idea! Pin
Zac Greve19-May-10 14:58
memberZac Greve19-May-10 14:58 
GeneralRe: A Good Idea! Pin
Mark C. Malburg20-May-10 1:41
memberMark C. Malburg20-May-10 1:41 
GeneralRe: A Good Idea! Pin
Zac Greve5-Jun-10 13:43
memberZac Greve5-Jun-10 13:43 
GeneralOK article Pin
Donsw14-Feb-10 11:51
memberDonsw14-Feb-10 11:51 
GeneralRe: OK article Pin
Mark C. Malburg15-Feb-10 4:37
memberMark C. Malburg15-Feb-10 4:37 
GeneralPlease go a little further [modified] Pin
wmjordan22-Nov-09 2:35
memberwmjordan22-Nov-09 2:35 
GeneralRe: Please go a little further Pin
Mark C. Malburg22-Nov-09 3:19
memberMark C. Malburg22-Nov-09 3:19 
GeneralRe-inventing the wheel Pin
justastupidgurl28-Sep-09 23:05
memberjustastupidgurl28-Sep-09 23:05 
You do know that complete fast and effective globalization is already built-in to the framework? It's blindingly fast compared to your approach, which will slow down horribly as the number of strings increases. Culture modules can be separate resource files and it's trivial to generate them from a customer's own translation file (in Excel or whatever). Also, other support (currencies, time date formats, numerical formats, calendars, LTR/RTL, module signing, security, sort-orders, culture-specific graphics, thread culture etc.) is already built-in. There is a lot more to globalization than strings, and it's now VERY easy to do it using the standard Microsoft methods.[^]


GeneralRe: Re-inventing the wheel Pin
Mark C. Malburg29-Sep-09 1:41
memberMark C. Malburg29-Sep-09 1:41 
GeneralRe: Re-inventing the wheel Pin
Hugo González Castro29-Sep-09 3:18
memberHugo González Castro29-Sep-09 3:18 
GeneralMy vote of 1 Pin
justastupidgurl28-Sep-09 22:47
memberjustastupidgurl28-Sep-09 22:47 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171207.1 | Last Updated 25 Sep 2009
Article Copyright 2009 by Mark C. Malburg
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid