.NET · WinForms · WPF
Change the language at runtime in WinForms and WPF.
Setting CurrentUICulture changes nothing on the screen: forms and windows read their resources once, when they are created. There are three ways to switch, and they differ in what you have to write and what can break.
On this page
Three ways to switch, from safest to most work.
All three use the same satellite assemblies. The difference is only in your code.
| Way | What you write | What can break | Fits |
|---|---|---|---|
| Restart | Save the choice, read it in Main, restart | Nothing in the UI; the user loses unsaved state unless you keep it | Most desktop applications; WinForms and WPF |
| Recreate the windows | Set the culture, open new forms or windows, close the old ones | State held in the old windows; dialogs that are open | Applications with one main window and little state in it |
| Reapply resources | Walk every control and apply its resources again | Layout, text the user typed, menus, user controls, strings set in code | WinForms only, when a restart is not acceptable |
WPF windows built from BAML cannot reload their XAML in place: there the choice is between restarting and recreating. Libraries that bind every text to a .resx through a markup extension switch in place, but only for the text bound that way.
1. Restart with the new language.
Set the culture in Main before the first form or window, as the WinForms and WPF guides show, and restart when the user picks another language. The WPF sample in Localizer does exactly this from its Language menu.
WinForms
void SwitchLanguage(string culture) // "de-DE"
{
Settings.Default.Language = culture;
Settings.Default.Save();
Application.Restart();
}WPF
void SwitchLanguage(string culture)
{
Settings.Default.Language = culture;
Settings.Default.Save();
Process.Start(Environment.ProcessPath!); // .NET 6 and later
Application.Current.Shutdown();
}2. Recreate the windows.
A new form or window reads its resources in InitializeComponent, in the culture current at that moment. Set the culture for this thread and for new ones, open a new main window, and close the old one.
// WPF; in WinForms the same with a new MainForm and an ApplicationContext
void SwitchLanguage(CultureInfo culture)
{
CultureInfo.DefaultThreadCurrentUICulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
var old = Application.Current.MainWindow;
var fresh = new MainWindow();
Application.Current.MainWindow = fresh; // before closing the old one
fresh.Show();
old.Close();
}
- Carry the state over yourself: the open document, the selection, window position.
- Close or reopen dialogs that are open: they keep the old language.
3. Reapply resources to open forms (WinForms).
ComponentResourceManager.ApplyResources sets every localizable property of a control from the form's resources in the current UI culture. That is also why layouts break: the stored Location and Size come back too, and so does the original Text of a text box.
static void ApplyCulture(Form form, CultureInfo culture)
{
Thread.CurrentThread.CurrentUICulture = culture;
var resources = new ComponentResourceManager(form.GetType());
resources.ApplyResources(form, "$this");
ApplyTo(form.Controls, resources);
}
static void ApplyTo(Control.ControlCollection controls, ComponentResourceManager resources)
{
foreach (Control c in controls)
{
resources.ApplyResources(c, c.Name);
ApplyTo(c.Controls, resources);
}
}
- Menus and toolbars are not in
Controls: walk theItemsof eachMenuStrip,ToolStrip, andStatusStripas well. - User controls have their own resources: apply them with a resource manager for the user control's type.
- Text set in code after
InitializeComponent, such as a status message, has to be set again. - Keep what the user changed: save sizes, splitter positions, and typed text before you apply, and restore them after.
Only part of the UI changed language?
| Symptom | Cause | What to do |
|---|---|---|
| Text set in code stays in the old language | It was read once from Strings.Something and stored | Read it again after the switch, or restart |
| Work on background threads uses the old language | CurrentUICulture is per thread | Set CultureInfo.DefaultThreadCurrentUICulture too |
| Dates and numbers keep the old format | CurrentCulture (formats) and CurrentUICulture (resources) are separate | Set both, if the formats should follow the language |
| WPF bindings format dates in US English | Bindings use FrameworkElement.Language, which is en-US unless set | Override its default at startup, or set Language on the window (FAQ below) |
| MessageBox buttons and file dialogs stay in English | They are Windows dialogs and follow the Windows display language | Nothing in your satellites changes them |
| One language shows English text everywhere | Its satellite is not found | See Satellite assembly not loading |
Satellites from Lingobit Localizer.
The switching code stays yours; Lingobit makes what it switches to. It translates the forms, windows, and strings of your compiled WinForms or WPF application, or your .resx files, and writes the satellite assembly of each language. Run Localized Application starts the application in the language you are checking.
Questions about switching the language
Why does setting CurrentUICulture not change the open form?
The form read its resources in InitializeComponent when it was created. The new culture applies to resources read from then on: new forms, new windows, and strings you read again.
Why do WPF bindings show dates in US format?
WPF formats bound values with FrameworkElement.Language, which defaults to en-US, not with CurrentCulture. Override the default once, at startup, before the first window is created:
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(
XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));The default can be overridden only once per process. For a later switch, set Language on each new window; its elements inherit it.
Can WPF switch the language without restarting?
Windows from BAML cannot reload their XAML, so recreate them. Text bound to .resx resources through a markup extension that listens for the culture change switches in place; text from {x:Static} is read once.
Do I need different satellites for switching at runtime?
No. The same de\MyApp.resources.dll serves a start in German and a switch to German. Only the code that picks the culture differs.
Related paths
- WinForms — Translate the compiled build in the form editor.
- WPF / BAML — Windows and resources from compiled assemblies.
- .NET satellite assemblies — Folder layout, names, and fallback.
- Satellite assembly not loading — A checklist when one language stays English.