How to Use ComponentResourceManager to Localize Forms with Telerik WinForms Controls
Environment
| Product Version | Product | Author |
|---|---|---|
| 2026.3.812 | UI for WinForms | Desislava Yordanova |
Description
In standard Windows Forms development, setting a Form's Localizable property to true instructs Visual Studio to generate culture-specific resource (.resx) files and serialize control properties through System.ComponentModel.ComponentResourceManager.
When working with Telerik UI for WinForms, developers often need to understand the following:
- How
ComponentResourceManagerinteracts with Telerik controls. - How
.resxresource localization differs from TelerikLocalizationProviderclasses. - How to dynamically change languages at runtime by using
ComponentResourceManager.ApplyResources.
ComponentResourceManager vs. LocalizationProvider
It is important to distinguish between two distinct localization layers:
- ComponentResourceManager (.resx files): Localizes form-level and control-level properties configured in the Visual Studio designer (such as
Text,Size,Location, andFont). All Telerik controls inherit fromSystem.Windows.Forms.Control, meaning design-time property values are serialized to.resxfiles and applied when the form is initialized. - Telerik LocalizationProvider: Localizes built-in internal strings that are part of the controls' internal templates and dialogs (such as RadGridView filtering operator menus, the Column Chooser text, conditional formatting dialogs, and RadScheduler dialog labels). These internal strings are not stored in form
.resxfiles and must be localized using Telerik localization providers (for example,RadGridLocalizationProvider).
Solution
Localizing Forms at Design Time
To localize a form at design time using standard .resx resources:
- Open your form in the Visual Studio designer.
- Select the Form and set its Localizable property to
truein the Properties window. - Select the desired language in the Language property (for example, German).
- Update the properties of your Telerik controls (for example, set the
Textof aRadButtonorRadLabelto German text, or adjust column header texts). - Visual Studio creates a dedicated resource file (such as
MyForm.de.resx) and generates code inInitializeComponent()usingComponentResourceManager.ApplyResources()to apply the localized values based onThread.CurrentThread.CurrentUICulture.
Runtime Language Switching
When an application changes culture at runtime without closing and recreating the form, you can re-apply resources by calling resources.ApplyResources() on the form and its controls.
Because Telerik controls host internal visual elements (such as RadMenuItem, GridViewDataColumn, and RadTreeNode) that are components or lightweight elements rather than child System.Windows.Forms.Control instances, a standard recursive control loop must also iterate over these specific Telerik element collections.
The following example demonstrates how to switch culture dynamically and update Telerik controls and columns:
using System;
using System.ComponentModel;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using Telerik.WinControls.UI;
public partial class RadForm1 : RadForm
{
public RadForm1()
{
InitializeComponent();
}
private void ApplyCulture(CultureInfo culture)
{
// 1. Update the UI culture of the current thread
Thread.CurrentThread.CurrentUICulture = culture;
Thread.CurrentThread.CurrentCulture = culture;
// 2. Initialize the ComponentResourceManager for this form
ComponentResourceManager resources = new ComponentResourceManager(this.GetType());
// 3. Suspend layout and apply resources to the form and controls
this.SuspendLayout();
ApplyResourcesToControl(resources, this);
this.ResumeLayout(true);
}
private void ApplyResourcesToControl(ComponentResourceManager resources, Control control)
{
// Apply resources to the control itself
string resourceKey = control is Form ? "$this" : control.Name;
resources.ApplyResources(control, resourceKey);
// Apply resources to Telerik-specific items
if (control is RadGridView grid)
{
foreach (GridViewColumn column in grid.Columns)
{
resources.ApplyResources(column, column.Name);
}
}
else if (control is RadMenu menu)
{
foreach (RadMenuItemBase item in menu.Items)
{
ApplyResourcesToMenuItem(resources, item);
}
}
// Recursively apply to child controls
foreach (Control child in control.Controls)
{
ApplyResourcesToControl(resources, child);
}
}
private void ApplyResourcesToMenuItem(ComponentResourceManager resources, RadMenuItemBase menuItem)
{
resources.ApplyResources(menuItem, menuItem.Name);
if (menuItem is RadMenuItem parentItem)
{
foreach (RadMenuItemBase child in parentItem.Items)
{
ApplyResourcesToMenuItem(resources, child);
}
}
}
}