How to Localize Windows Forms and Change the Language at Runtime

Posted by: Suprotim Agarwal , on 7/15/2008, in Category WinForms & WinRT
Views: 253550
Abstract: Localization is the process of customizing your application to a particular language, culture or locale. Visual Studio provides support for localizing Windows Forms with much ease. In this article, we will see how to localize windows forms and give the user the ability to change to his preferred language at runtime.
How to Localize Windows Forms and Change the Language at Runtime
 
Localization is the process of customizing your application to a particular language, culture or locale. Visual Studio provides support for localizing Windows Forms with much ease. In this article, we will see how to localize windows forms and give the user the ability to change to his preferred language at runtime.
When you run a localized application, the appearance is determined by two culture values. The UICulture property is used to specify which resource files will be loaded for the form. The Culture property, on the other hand, determines how strings such as dates, numerals, and currency amounts are formatted.
Let us see the steps required to create a localized form. You can then expand this example and adopt the same approach for the rest of the forms in your project.
Step 1: Open Visual Studio > File > New > Project. In the Project Types pane, choose the language of your choice (Visual C# or Visual Basic). In the Templates pane, choose Windows Application. Choose a name and location for the project and click OK.
Step 2: With the form opened, set its ‘Localizable’ property to True. Drag a Label control from the Toolbox, and set its Text property to ‘Hello’.
Note: By default, the Language property of the form is set to ‘(Default)’.
Step 3: Now set the form's ‘Language’ property to French (France). Set the label's Text property to ‘bonjour’.
Once again, set the form's Language property, but this time to Spanish (Spain). Set the button's Text property to holà.
Build the Solution. Expand the node in Form1.vb/Form1.cs. As you observe, the resource files appear underneath Form1.vb/Form1.cs. Form1.resx is the resource file for the default culture, Form1.fr-FR.resx is the resource file for French (France) and Form1.es-ES.resx is the resource file for Spanish (Spain). If you cannot see these files for some reason, click the ‘Show All Files’ button in Solution Explorer.
Step 4: Now set the form's ‘Language’ property back to (Default). Drag a ‘ComboBox’ from the Toolbox to the form.
In the Form_Load() add the following code :
C#
        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.Items.Add("English");
            comboBox1.Items.Add("Spanish");
            comboBox1.Items.Add("French");
            comboBox1.SelectedIndex = 0;
        }
 
VB.NET
         Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
                  comboBox1.Items.Add("English")
                  comboBox1.Items.Add("Spanish")
                  comboBox1.Items.Add("French")
                  comboBox1.SelectedIndex = 0
         End Sub
Also add references to the namespaces:
C#
using System.Globalization;
using System.Threading;
VB.NET
Imports System.Globalization
Imports System.Threading
Step 5: Now add a SelectedIndexChanged event handler to the ComboBox. Write the following code:
C#
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox1.SelectedItem.ToString() == "English")
            {
                ChangeLanguage("en");
            }
            else if (comboBox1.SelectedItem.ToString() == "Spanish")
            {
                ChangeLanguage("es-ES");
            }
            else
            {
                ChangeLanguage("fr-FR");
            }
        }
 
        private void ChangeLanguage(string lang)
        {
            foreach (Control c in this.Controls)
            {
                ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
                resources.ApplyResources(c, c.Name, new CultureInfo(lang));
            }
        }
VB.NET
            Private Sub comboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
                  If comboBox1.SelectedItem.ToString() = "English" Then
                        ChangeLanguage("en")
                  ElseIf comboBox1.SelectedItem.ToString() = "Spanish" Then
                        ChangeLanguage("es-ES")
                  Else
                        ChangeLanguage("fr-FR")
                  End If
            End Sub
 
            Private Sub ChangeLanguage(ByVal lang As String)
                  For Each c As Control In Me.Controls
                        Dim resources As ComponentResourceManager = New ComponentResourceManager(GetType(Form1))
                        resources.ApplyResources(c, c.Name, New CultureInfo(lang))
                  Next c
            End Sub
As you observe, every time the user selects a new language, the ChooseLanguage() method is called. In this method, we loop through each control on the form and use the ComponentResourceManager to enumerate through the resources for an object. We then use the ApplyResources method to apply a resource's value to the corresponding property of the object. One of the overloads of the ApplyResources accepts 3 parameters: the control that contains the property value to be applied; a string that contains the name of the object to look up in the resources and a culture for which to apply resources.
Note: Notice that each culture name(es-ES) consists of two parts. The first part represents the language code and the second part represents the country/region code. If you specify a culture name and do not provide a country/region code—for example, "en" —then that represents a 'neutral culture'. If you provide both a language code and a country/region code—for example, "es-ES", then that represents a 'specific culture'.
Well that’s it. Run the application and choose your preferred language from the combobox. You will see that the label changes values as set by you while creating the resources. I hope you liked the article and I thank you for viewing it.
If you liked the article,  Subscribe to my RSS Feed.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Fifteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Alain Henriot on Tuesday, July 22, 2008 4:33 PM
Very well. Very clearly. But how do you make the obfuscation of this program with dotfuscator CE in Visual Studio ?
Thank
Comment posted by Deepak Dagar on Wednesday, July 23, 2008 6:49 AM
Very good article & Thanks for sharing with all.
I have a question, suppose we have 100 controls(labels/buttons etc.) on the form & we have to localize it in three languages.
Then I feel this approach will be very difficult.
Could you suggest solution for this problem?
Thanks again for good work.
Comment posted by Chathura on Wednesday, July 30, 2008 3:42 AM
Excellent and thanks a lot for sharing knowledge.
Comment posted by lasa on Monday, August 18, 2008 10:44 AM
cool, the idea helped me allot in my C++.net program

private: System::Void LanguageSettings_Load(System::Object^  sender, System::EventArgs^  e) {
          comboBox1->Items->Add("English");
          comboBox1->Items->Add("French");
          comboBox1->Items->Add("Spanish");
       }

   private: System::Void comboBox1_SelectedIndexChanged(System::Object^  sender, System::EventArgs^  e) {
             if(comboBox1->SelectedItem::get()=="English"){
                ChangeLanguage("en");
             }else if(comboBox1->SelectedItem::get()=="French"){
               ChangeLanguage("fr-FR");
             }else if(comboBox1->SelectedItem::get()=="Spanish"){
               ChangeLanguage("es-ES");
             }
          }

      private: void ChangeLanguage(String^ lang)
        {
            for each (Control ^c in this->Controls){
                ComponentResourceManager^ resources = gcnew ComponentResourceManager(this->GetType());
                resources->ApplyResources(c, c->Name, gcnew System::Globalization::CultureInfo(lang));
         }
        }
Comment posted by Suprotim Agarwal on Monday, August 18, 2008 9:10 PM
lasa: Thanks for sharing your C++ solution!!
Comment posted by ChrissDeGrece on Monday, September 22, 2008 1:08 PM
Thanks for sharing this nice information.

Unfortunately it changes only buttons and texts on the form, the toolbar buttons text is not changed. Any suggestions on that?

Thanks

Comment posted by abdoureda on Wednesday, October 8, 2008 12:10 PM
But How Can I return back to (default) language not a specific language like "es-es"
Comment posted by Suprotim Agarwal on Thursday, October 9, 2008 6:04 AM
Isn't the combo box working for you? Selecting Spanish in the combobox should change the culture.
Comment posted by .NET Dev on Monday, November 3, 2008 2:12 AM
This is also good article:
http://urenjoy.blogspot.com/2008/11/windows-form-localization-in-net.html
Comment posted by tagtog on Monday, December 29, 2008 12:46 AM
OK, it's good. but how can i deal with positioning in right to left languages?
Comment posted by samehsenosi on Sunday, January 3, 2010 4:52 AM
you can switch to right to left by the following sample code

'to switch Form Layout:
Me.RightToLeft = Windows.Forms.RightToLeft.Yes
Me.RightToLeftLayout = True
'to switch controls:
            For Each c As Control In Me.Controls
                c.RightToLeft = Windows.Forms.RightToLeft.Yes
            Next
Comment posted by marko on Thursday, March 25, 2010 6:52 AM
Hi, i have a problem with localization. I have about 300 forms in my project, and i cannot set localizable property to true (i have to do this to generate resource files for 2 additional languages) for all of them manualy, it would take forever. I want to do this from code. Is it even possible?

Thanks
Comment posted by marko on Thursday, March 25, 2010 7:08 AM
Hi, i have a problem with localization. I have about 300 forms in my project, and i cannot set localizable property to true (i have to do this to generate resource files for 2 additional languages) for all of them manualy, it would take forever. I want to do this from code. Is it even possible?

Thanks
Comment posted by faraz on Friday, May 28, 2010 8:17 AM
Very good article & Thanks for sharing with all.
I have problem with type of ComponentResourceManager in VB 2010 .
" Error   1   Type 'ComponentResourceManager' is not defined "
code :
  Private Sub comboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
        If ComboBox1.SelectedItem.ToString() = "English" Then
            ChangeLanguage("en")
        ElseIf ComboBox1.SelectedItem.ToString() = "Spanish" Then
            ChangeLanguage("es-ES")
        ElseIf ComboBox1.SelectedItem.ToString() = "French" Then
            ChangeLanguage("fr-FR")
        Else
            ChangeLanguage("ar")
        End If
    End Sub

    Private Sub Login_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
        ComboBox1.Items.Add("English")
        ComboBox1.Items.Add("Spanish")
        ComboBox1.Items.Add("French")
        ComboBox1.Items.Add("Arabic")
        ComboBox1.SelectedIndex = 0
    End Sub

    Private Sub ChangeLanguage(ByVal lang As String)
        For Each c As Control In Me.Controls
            Dim resources As ComponentResourceManager = New ComponentResourceManager(GetType(Login))
            resources.ApplyResources(c, c.Name, New CultureInfo(lang))
        Next c
    End Sub
Comment posted by Chris on Monday, July 5, 2010 2:12 PM
Thank you very much for this very clear explanation!

@ Faraz, you need to put on the top : Imports System.ComponentModel
Comment posted by KommradHomer on Monday, July 26, 2010 11:53 AM
im doing all these and the applyresource method is being called too as i check with breaks on debug.but nothing changes at all. some people suggest to initializeComponent method but its doubling all the items so it doesnt work either. whats the problem ?
Comment posted by Abdulz on Friday, September 17, 2010 1:40 PM
hi,
This topic should be helpful but I got no change. I follow all these steps but no change of language happen. When I change language of "Form" from the properties this also make no change. Is there any prerequisite for this change?
I am using VS2008 professional edition.
Comment posted by yanosi on Friday, October 15, 2010 3:28 PM
hi,
I am a beginner in vb.net, but i think, the handles method is missing...

Try this (it works in vb.net 2008):


Imports System.Globalization
Imports System.Threading
Imports System.ComponentModel

Public Class Form1

    Private Sub ChangeLanguage(ByVal lang As String)
        For Each c As Control In Me.Controls
            Dim resources As ComponentResourceManager = New ComponentResourceManager(GetType(Form1))
            resources.ApplyResources(c, c.Name, New CultureInfo(lang))
        Next c
    End Sub

    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        If ComboBox1.SelectedItem.ToString() = "English" Then
            ChangeLanguage("en")
        ElseIf ComboBox1.SelectedItem.ToString() = "Spanish" Then
            ChangeLanguage("es-ES")
        ElseIf ComboBox1.SelectedItem.ToString() = "French" Then
            ChangeLanguage("fr-FR")
        Else
            ChangeLanguage("ar")
        End If

        'MsgBox(ComboBox1.SelectedItem)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox1.Items.Add("English")
        ComboBox1.Items.Add("Spanish")
        ComboBox1.Items.Add("French")
        ComboBox1.Items.Add("Arabic")
        ComboBox1.SelectedIndex = 0
    End Sub
End Class

Comment posted by webmaster777 on Tuesday, October 26, 2010 7:48 PM
You shouldn't forget to call the refreshResources recursively, otherwise sub-controls won't be translated! Also my title wouldn't convert and bounds changed so I used this code for my application.


        private void RefreshResources(Control ctrl, ComponentResourceManager res)
        {
            ctrl.SuspendLayout();
            res.ApplyResources(ctrl, ctrl.Name, CurrentLocale);
            foreach (Control control in ctrl.Controls)
                RefreshResources(control, res); // recursion
            ctrl.ResumeLayout(false);
        }

// calling
            ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
            resources.ApplyResources(this, "$this"); // Stolen from a designer generated code. This is to ensure the form itself reloads resources.
            RefreshResources(this,resources);

This will force a reload of all Controls and the form itself.

Hope this helps some folks.
Comment posted by mahmoud_ElHaddad on Monday, January 3, 2011 4:39 AM
C# Programmer
Comment posted by Jan on Sunday, April 10, 2011 5:07 AM
What id there is more than one form in my application. (VB2010)
Comment posted by Jan on Monday, April 11, 2011 12:45 PM
I also want to know about thew switching of languages using multiple forms in VB 2010.
Comment posted by Senthil on Thursday, June 16, 2011 12:31 PM
Unfortunately it changes only buttons and texts on the form, the toolbar buttons text is not changed. Any suggestions on that?
I have a scenario like a winform with a textbox and button - After entering text and click submit the value gets stored in the databse. we need to localize this. what happens is the string we enter to text box appears according to the font applied, but when we catch that string like textbox.text its in english, so the value stored in db is also in english.

So how do i localize a textbox, so that it displays the text entered in the specific language and its stored to DB in the same language.
Comment posted by DarkSupremo on Thursday, July 21, 2011 7:00 AM
Thank you!!
Exactly what i was looking :)

Very good...
Comment posted by Alex on Friday, September 2, 2011 1:59 AM
Nice article!

But MenuStrip, ContextMenu and ToolStrip are left unchanged. How those three can be changed with the new resources implementation?
Comment posted by Will on Tuesday, September 13, 2011 4:22 AM
Good Article!!
I want to do at same but with MenuStrip... I tried to do like you but I Can´t... Any ideas??
Comment posted by Dev on Tuesday, November 15, 2011 7:12 PM
thank you it's good example
Comment posted by Tegshee on Monday, December 5, 2011 1:23 AM
How to form caption language changing...???
help me. (This code)
Comment posted by lilian87 on Wednesday, December 7, 2011 7:34 AM
Really good article!! Thanks for sharing !!
Comment posted by Jarosław Polański on Tuesday, February 28, 2012 8:03 AM
Hello everybody,
I have a problem with my application localization. I use Windows Forms .NET Framework 4.0 and System.Windows.Forms.DataVisualisation ver 4.0.

When I try to create new localization everything works fine except of charts. I created new UserControl then put some labels, textbox and chart. I cant localize chart variables like title , legends, axis titles and so on. The .resx file does not contain strings for chart localization. Is there any way around ?
Comment posted by Heitor on Friday, April 6, 2012 1:13 PM
So, how someone actually localize a form. Just try some "messagebox.show("Alert", Messageboxbuttons.yesno)" and you all see that CONTINUES in ENGLISH, for god sake!!! This is not localization...
Comment posted by H G on Saturday, April 21, 2012 2:06 PM
Very helpful indeed. Good posts are timeless (well, almost).
Comment posted by ZooZ on Tuesday, May 22, 2012 1:00 AM
Great article! Thank you :)
Comment posted by Yared Tadele on Tuesday, May 22, 2012 5:00 AM
this is helpful thank sir!
Comment posted by subrahmanyam on Wednesday, September 12, 2012 7:48 AM
Its very good article, thanks for the article. its helps alot. How to change the fonts for the different languages.
Comment posted by virtualworld on Tuesday, November 6, 2012 4:09 AM
I tried but no error no changes in my project.I using Visual Studio 2010.
Comment posted by FirstPerson on Wednesday, March 20, 2013 7:21 AM
"I tried but no error no changes in my project.I using Visual Studio 2010."

Same here.
Comment posted by Craig on Tuesday, April 9, 2013 12:12 PM
I find this works best:

If Not Me.Created Then Exit Sub

        Dim ci As String = "en-US"

        If LanguageCombo.Text = "English" Then ci = ("en-US")
        If LanguageCombo.Text = "Spanish" Then ci = ("es-ES")

        newLanguage = LanguageCombo.text 'GlobalString
        Dim culture_info As New CultureInfo(ci)
        Thread.CurrentThread.CurrentUICulture = culture_info
        Thread.CurrentThread.CurrentCulture = culture_info
        Thread.CurrentThread.CurrentUICulture = New Globalization.CultureInfo(ci)


        If Me.components IsNot Nothing Then Me.components.Dispose()
        Me.Controls.Clear()
        Me.InitializeComponent()

        FrmMain_Load(Me, New System.EventArgs)
Comment posted by RAIN on Saturday, June 15, 2013 4:27 AM
Thanks you very much!
Suprotim Agarwal & Lasa
Comment posted by Kevin Coulombe on Tuesday, June 25, 2013 9:46 PM
As Craig said, setting the culture on the thread before showing the form again is a better solution. It will localize any dialog, toolbars, etc. correctly.
Comment posted by Kalid Kelil on Tuesday, August 20, 2013 2:08 PM
HelpFUl!!!!!!!!!!!
Comment posted by Sofiane on Saturday, August 24, 2013 8:16 AM
thanks for the solution
i have a qestion;*
how can we change the name of the form with this approch?
Comment posted by Sofiane on Saturday, August 24, 2013 8:51 AM
thanks for the solution
i have a qestion;*
how can we change the name of the form with this approch?
Comment posted by Efrain Pinto on Thursday, January 9, 2014 10:52 AM
The solution posted by Suprotim Agarwal is correct if you only want to update language settings on controls added directly into the form (ChangeLanguage).
But if you have controls inside controls, recursivity is a must.
The following approach seems to work very well

private void ChangeLanguage(Control control, CultureInfo cultureInfo, ComponentResourceManager resources)
        {
            foreach (Control innerControl in control.Controls)
            {
                resources.ApplyResources(innerControl, innerControl.Name, cultureInfo);
                ChangeLanguage(innerControl, cultureInfo, resources);
            }
        }

You need to find "cultureInfo" and "resources" before calling ChangeLanguage, then ChangeLanguage(MyForm) will do the trick.
Comment posted by Axel on Friday, February 28, 2014 9:05 PM
Hmm, that's all for me "new", but I add a very simple fallback, I changed following in my code (that's my example in C#):

// BEGIN EXAMPLE //
        private void comboBoxLanguage_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBoxLanguage.SelectedItem.ToString() == "English")
            {
                ChangeLanguage("en");
            }
            else if (comboBoxLanguage.SelectedItem.ToString() == "Deutsch")
            {
                ChangeLanguage("de-DE");
            }
            else if (comboBoxLanguage.SelectedItem.ToString() == "Français")
            {
                ChangeLanguage("fr-FR");
            }
            else //Fallback
            {
                ChangeLanguage("en");
            }
        }
// END EXAMPLE //

Is there a solution to save the setting in a file or similar?

Comment posted by Robert on Monday, April 28, 2014 3:56 AM
I tried and it worked fine for normal controls like labels etc.

But with e.g. a ToolStrip, it didn't

:/
Comment posted by codehelp87 on Thursday, May 22, 2014 3:13 AM
I tried similar in my winforms app it didn't work .

So to test I created another project and tried yours , it still does not work ;( ....
Comment posted by Ank on Sunday, October 5, 2014 1:35 AM
I tried the above example with steps mentioned, its working, but I want to try the same at runtime when the user enters the data on the form.
Comment posted by Axel on Tuesday, December 9, 2014 5:22 PM
Is it possible to load the available resource files and to add to the ComboBox or better, MenuStrip dynamically?

Is it possible to save the selected language in the settings file that the user can restart the application that load all items and similar in the current language? (Like SmartDVB and similar)
Comment posted by Jay on Wednesday, December 10, 2014 12:45 AM
hi, i copy this code as it is, but it display no output as language change