Proper way to change language at runtime

I've discovered this kind of approach a few minutes ago. Just quick and simple restart of the main form. Meybe it will help to someone. Event is created inside the form on my own, called when user selects the language from menu but after the selected culture's name is saved into the settings. Culture names are then loaded from that settings. Works exactly as I need and looks like proper solution.

static class Program
{
    private static bool doNotExit = true;
    private static FormMain fm;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {


        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        while(doNotExit)
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(Properties.Settings.Default.language);//
            System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.language);//

            doNotExit = false;
            fm = new FormMain();
            fm.lanugageChangedEvent += new EventHandler(main_LanugageChangedEvent);
            Application.Run(fm);
        }
    }



    static void main_LanugageChangedEvent(object sender, EventArgs e)
    {  
        doNotExit = true;
        fm.Close();   
    }
}

I have found another way:

Move initialization form code in a private method like below:

private void FormInitialize() {/*Your code here*/}

In the form constructor use it like this:

public Form1()
{
    InitializeComponent();
    FormInitialize();
}

And from Button, menuItem or other call method like this:

private void ChangeCultureToFrench_Click(object sender, EventArgs e)
{
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr");
    this.Controls.Clear();
    this.InitializeComponent();
    FormInitialize();
}

I hope this helps ;-)


I believe the solution shown in Hans Passant's comment might be the only (general) solution.

Personally, I use this base class for all forms that need to be localized:

public class LocalizedForm : Form
{
    /// <summary>
    /// Occurs when current UI culture is changed
    /// </summary>
    [Browsable(true)]
    [Description("Occurs when current UI culture is changed")]
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    [Category("Property Changed")]
    public event EventHandler CultureChanged;

    protected CultureInfo culture;
    protected ComponentResourceManager resManager;

    /// <summary>
    /// Current culture of this form
    /// </summary>
    [Browsable(false)]
    [Description("Current culture of this form")]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public CultureInfo Culture
    {
        get { return this.culture; }
        set
        {
            if (this.culture != value)
            {
                this.ApplyResources(this, value);

                this.culture = value;
                this.OnCultureChanged();
            }
        }
    }

    public LocalizedForm()
    {
        this.resManager = new ComponentResourceManager(this.GetType());
        this.culture = CultureInfo.CurrentUICulture;
    }

    private void ApplyResources(Control parent, CultureInfo culture)
    {
        this.resManager.ApplyResources(parent, parent.Name, culture);

        foreach (Control ctl in parent.Controls)
        {
            this.ApplyResources(ctl, culture);
        }
    }

    protected void OnCultureChanged()
    {
        var temp = this.CultureChanged;
        if (temp != null)
            temp(this, EventArgs.Empty);
    }
}

Then instead of directly changing Thread.CurrentThread.CurrentUICulture, I use this property in static manager class to change UI culture:

public static CultureInfo GlobalUICulture
{
    get { return Thread.CurrentThread.CurrentUICulture; }
    set
    {
        if (GlobalUICulture.Equals(value) == false)
        {
            foreach (var form in Application.OpenForms.OfType<LocalizedForm>())
            {
                form.Culture = value;
            }

            Thread.CurrentThread.CurrentUICulture = value;
        }
    }
}