Search code examples
c#windowsformsglobalizationcultureinfo

Switching language (cultureinfo/globalization) does not affect ToolStripMenuItems


I have a Windows Forms application project, and on the main form I have a menu strip. Some place in this menu strip it is possible to select various languages. For example if the user selects "English", everything on this main form (and others in the future) should be turned into English language.

I took this tutorial: click

This works fine with labels and such, but it does not work at all with the tool strip menu items. They just stay with their default text.

I tried to add two more lines to the ChangeLanguage method:

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));
        ComponentResourceManager res2 = new ComponentResourceManager(typeof(ToolStripMenuItem));
        res2.ApplyResources(c, c.Name, new CultureInfo(lang));
    }
}

But it fails and says:

Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "System.Windows.Forms.ToolStripMenuItem.resources" was correctly embedded or linked into assembly "System.Windows.Forms" at compile time, or that all the satellite assemblies required are loadable and fully signed.

Not sure how to proceed - any help appreciated.


Solution

  • You have to remove the last 2 lines in your foreach loop. That lines say that you are looking for the localization information in System.Windows.Forms.ToolStripMenuItem.resx file, but you want to look in your Forms resources file.

    ToolstripMenuItems are added to an ToolStripItems DropDownItems Collection and not to the Controls collection of your Form. This might help you solving your problem.

    private void ChangeLanguage(string lang) {
        ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
        foreach (Control c in this.Controls) {
            resources.ApplyResources(c, c.Name, new CultureInfo(lang));
        }
    
        foreach (ToolStripItem item in toolStrip1.Items) {
            if (item is ToolStripDropDownItem)
                foreach (ToolStripItem dropDownItem in ((ToolStripDropDownItem)item).DropDownItems) {
                    resources.ApplyResources(dropDownItem, dropDownItem.Name, new CultureInfo(lang));
                }
        }
    }
    

    If you have further drop down items you should consider a recursive approach.

    Edit: To my first comment

    private void ChangeLanguage(string lang) {
        ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
        foreach (Control c in this.Controls) {
            resources.ApplyResources(c, c.Name, new CultureInfo(lang));
        }
    

    ChangeLanguage(toolStrip1.Items); }

    private void ChangeLanguage(ToolStripItemCollection collection) {
        foreach (ToolStripItem item in collection) {
            resources.ApplyResources(item, item.Name, new CultureInfo(lang));
            if (item is ToolStripDropDownItem)
                ChangeLanguage(((ToolStripDropDownItem)item).DropDownItems);
        }
    }