views:

45

answers:

2

I have a winforms application that the users must be able to change the language at runtime.

To generalize the switch and avoid having to hard code control names I tried the following extension:

    internal static void SetLanguage(this Form form, CultureInfo lang)
    {
        ComponentResourceManager resources = new ComponentResourceManager(form.GetType());

        ApplyResourceToControl(resources, form, lang);
        resources.ApplyResources(form, "$this", lang);
    }

    private static void ApplyResourceToControl(ComponentResourceManager resources, Control control, CultureInfo lang)
    {
        foreach (Control c in control.Controls)
        {
            ApplyResourceToControl(resources, c, lang);
            resources.ApplyResources(c, c.Name, lang);
        }
    }

This does change all the strings.

However a side effect of this is that the entire contents of the window is resized to that windows original startup size, no matter what the current size is.

How can I prevent the layout from changing or initiate a new layout calculation?

+2  A: 

Look at the .resx file to see what all is getting reassigned. Properties like Size and Form.AutoScaleDimensions are localizable properties. Reassigning them has the kind of effect you are seeing. Especially undoing the auto-scaling would be quite unpleasant.

No specific advise to fix this problem, this just isn't made to be run in any other place than the form constructor. Reconstruct the form. Pointing out that the actual user of your form never feels a need to change her native language on-the-fly never seems to make an impression.

Hans Passant
A: 

This is the complete code I am using now.

The change is to manually change the Text property only. If I get to localize other properties, the code will have to be expanded afterwards.

    /// <summary>
    /// Change language at runtime in the specified form
    /// </summary>
    internal static void SetLanguage(this Form form, CultureInfo lang)
    {
        //Set the language in the application
        System.Threading.Thread.CurrentThread.CurrentUICulture = lang;

        ComponentResourceManager resources = new ComponentResourceManager(form.GetType());

        ApplyResourceToControl(resources, form.MainMenuStrip, lang);
        ApplyResourceToControl(resources, form, lang);

        //resources.ApplyResources(form, "$this", lang);
        form.Text = resources.GetString("$this.Text", lang);
    }

    private static void ApplyResourceToControl(ComponentResourceManager resources, Control control, CultureInfo lang)
    {
        foreach (Control c in control.Controls)
        {
            ApplyResourceToControl(resources, c, lang);
            //resources.ApplyResources(c, c.Name, lang);
            string text = resources.GetString(c.Name+".Text", lang);
            if (text != null)
                c.Text = text;
        }
    }

    private static void ApplyResourceToControl(ComponentResourceManager resources, MenuStrip menu, CultureInfo lang)
    {
        foreach (ToolStripItem m in menu.Items)
        {
            //resources.ApplyResources(m, m.Name, lang);
            string text = resources.GetString(m.Name + ".Text", lang);
            if (text != null)
                m.Text = text;
        }
    }
phq