Search code examples
c#formswinforms

how switch between form languages in c#?


Hi I have C# windows form with 11 forms. I use language Properties of All forms to design them in 2 language (default and English united state). In my setting form I have 2 radio button and I want when user click on them the languages of all form change. I find 2 example for this but none of them work how to do this?

this is my first try: (not working and Messing up the placement of controls on the form)

 private void radioButtonDefault_Click(object sender, EventArgs e)
        {
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture;
            // Reload the form or the controls to apply the new language
            this.Controls.Clear();
            InitializeComponent();
        }

        private void radioButtonEnglish_Click(object sender, EventArgs e)
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            // Reload the form or the controls to apply the new language
            this.Controls.Clear();
            InitializeComponent();
        }

this is my Second try: (not run get too many error)

private void radioButtonDefault_Click(object sender, EventArgs e)

{
    SwitchToDefaultLanguage();
}

private void radioButtonEnglish_Click(object sender, EventArgs e)
{
    SwitchToEnglish();
}

private static void ApplyResources(Control control, string name, CultureInfo culture)
{
    System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(control.GetType(), name, culture);
    control.Text = resources.GetString("$this.Text");
    foreach (Control child in control.Controls)
    {
        ApplyResources(child, child.Name, culture);
    }
}

private void SwitchToDefaultLanguage()
{
    this.SuspendLayout();
    this.Localizable = true;
    this.components = new System.ComponentModel.Container();
    // Load the resources for the default language
    System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingForm));
    resources.ApplyResources(this, "$this");
    // Apply the resources to all the controls of the form
    ApplyResources(this, this.Name, CultureInfo.CurrentUICulture);
    this.ResumeLayout(false);
}

private void SwitchToEnglish()
{
    this.SuspendLayout();
    this.Localizable = true;
    this.components = new System.ComponentModel.Container();
    // Load the resources for the English language
    System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingForm));
    resources.ApplyResources(this, "$this");
    // Apply the resources to all the controls of the form
    ApplyResources(this, this.Name, CultureInfo.GetCultureInfo("en-US"));
    this.ResumeLayout(false);
}

how can solve my problem? please help?


Solution

  • Change language at run-time

    The proper way of setting the language is before showing main. So for the main form, it's best to do it in startup, otherwise you need to carefully write a logic which considers the differences between controls. It's not as easy as it's shown in the linked posts. For example ComboBox, ListBox, ListView, TreeView, DataGridView, ToolStrip, ContextMenuStrip, MenuStrip, StatusStrip or maybe a few other controls need different logic than other controls.

    If for any reason you'd like to continue your attempt to reload resources at runtime, take a look at my example How to change language of a menu at run-time, but I'd not use it in production and I'd rely on restarting the application.

    Change language with restart

    If you'd like to know how to do it with restarting the application, this is how I'll handle it:

    • I'll use application settings to store the selected language.
    • I'll set the language at startup
    • I'll define a list of supported languages and using code, I'll show those under a menu in the main form.
    • In the click event handler of the menu items, I save the selected language in the setting, and restart the app with user's permission.

    enter image description here

    1. I'll add a Settings.settings file to the project. Then I'll add a Culture setting having string as type with a value equal to the culture that I'd like to use as default culture, let's say "fa-IR".

      enter image description here

    2. At the program.cs, I'll define list of supported cultures, and I'll set the current culture and current UI culture of the current thread, based on the value that I have in the settings:

      using System.Globalization;
      namespace WinFormsSample
      {
          internal static class Program
          {
              public static string[] SupportedCultures = new[] {
                  "fa-IR",
                  "en-US",
              };
              [STAThread]
              static void Main()
              {
                  ApplicationConfiguration.Initialize();
                  var culture = Settings.Default.Culture;
                  if(SupportedCultures.Contains(culture))
                  {
                      Thread.CurrentThread.CurrentUICulture =
                          Thread.CurrentThread.CurrentCulture =
                          CultureInfo.GetCultureInfo(Settings.Default.Culture);
                  }
                  Application.Run(new Form1());
              }
          }
      }
      
    3. Then in the main form, I'll add a menu item for language, let's say languageToolStripMenuItem. Then at the startup of the form, I'll add the supported languages as menu items and set the selected one based on the settings, and also add a click event handler to save the settings when a new language is selected and then asking to restart the app:

      public Form1()
      {
          InitializeComponent();
          foreach (var culture in Program.SupportedCultures)
          {
              var cultureItem = new ToolStripMenuItem();
              cultureItem.Text = CultureInfo.GetCultureInfo(culture).NativeName;
              cultureItem.Tag = culture;
              cultureItem.Click += (sender, args) =>
              {
                  var selected = (ToolStripMenuItem)sender;
                  selected.Checked = true;
                  selected.Owner.Items.OfType<ToolStripMenuItem>()
                      .Except(new[] { selected })
                      .ToList().ForEach(x => x.Checked = false);
                  Settings.Default.Culture = (string)selected.Tag;
                  Settings.Default.Save();
                  if (MessageBox.Show("To apply the selected language you " +
                      "need to restart the application.\n" +
                      "Do you want to restart now?\n" +
                      "If you choose no or cancel, the language " +
                      "applies the next time you open the application.",
                      "Restart application?",
                      MessageBoxButtons.YesNoCancel,
                      MessageBoxIcon.Question,
                      MessageBoxDefaultButton.Button3) == DialogResult.Yes)
                  {
                      Application.Restart();
                  }
              };
              languageToolStripMenuItem.DropDownItems.Add(cultureItem);
          }
          var item = languageToolStripMenuItem.DropDown.Items
              .OfType<ToolStripMenuItem>().Where(x => $"{x.Tag}" == Settings.Default.Culture)
              .FirstOrDefault();
          if (item != null)
              item.Checked = true;
      }