Engineering

ResX Files and Resource File Editors: The Complete .NET Localization Guide

Eray Gündoğmuş
Eray Gündoğmuş
·13 min read
Share
ResX Files and Resource File Editors: The Complete .NET Localization Guide

ResX Files and Resource File Editors: The Complete .NET Localization Guide

If you've ever added a second language to a .NET application, you've encountered .resx files. They're the backbone of .NET localization — and they've been around since .NET Framework 1.0. This guide explains how .resx files work, how to structure a localization setup correctly in both ASP.NET Core and WinForms/WPF, which editors make the job manageable, and when it is worth looking at alternatives.


TL;DR / Key Takeaways

  • A .resx file is an XML-based resource file used by .NET to store localized strings, images, and other data. The runtime loads the correct file based on the current thread culture.
  • The satellite assembly model compiles locale-specific .resx files into separate .dll files, so your main application ships without embedding every translation.
  • Visual Studio has a built-in .resx editor, but it becomes painful beyond a handful of languages. Third-party tools like ResXManager or Zeta Resource Editor significantly improve the multi-language editing experience.
  • .resx localization is the right default for offline desktop applications (WPF, WinForms, MAUI) where all assets must be bundled.
  • For web applications, CDN-based delivery platforms can complement or replace .resx workflows, reducing rebuild-and-redeploy cycles for translation updates.

What Are ResX Files?

A .resx file is an XML resource file that .NET uses to store named key-value pairs — typically strings — for a specific language or culture. When your application runs, the ResourceManager class loads the correct .resx file based on the current thread's CultureInfo, falling back to the default (neutral) resource file if a locale-specific file does not exist.

The XML Structure

<?xml version="1.0" encoding="utf-8"?>
<root>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <data name="WelcomeMessage" xml:space="preserve">
    <value>Welcome to our application!</value>
    <comment>Displayed on the home page hero section</comment>
  </data>
  <data name="SubmitButton" xml:space="preserve">
    <value>Submit</value>
  </data>
</root>

For a French translation, create Strings.fr.resx alongside Strings.resx. The runtime walks the culture hierarchy from most specific (fr-CA) to neutral (fr) to default (Strings.resx).

Satellite Assemblies

The .NET compiler compiles locale-specific .resx files into satellite assemblies — separate .dll files in culture-code subdirectories. According to Microsoft's documentation, this lets teams update languages independently.


How to Set Up ResX-Based Localization

Step 1: Create Resource Files

Resources/
  Strings.resx         ← default (English)
  Strings.fr.resx      ← French
  Strings.de.resx      ← German
  Strings.ja.resx      ← Japanese

Step 2: Access Resources in C#

using MyApp.Resources;
string message = Strings.WelcomeMessage;

Step 3: Set the Culture

Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr");

In ASP.NET Core, use RequestLocalizationMiddleware.

Step 4: Use IStringLocalizer

public class HomeController : Controller
{
    private readonly IStringLocalizer<HomeController> _localizer;
    public HomeController(IStringLocalizer<HomeController> localizer) => _localizer = localizer;
    public IActionResult Index()
    {
        ViewData["Message"] = _localizer["WelcomeMessage"];
        return View();
    }
}

See the ASP.NET Core localization docs.

Step 5: WPF and WinForms

<TextBlock Text="{x:Static props:Strings.WelcomeMessage}" />

Best Resource File Editors

EditorPlatformMulti-languageAuto-translateBest for
Visual StudioWindowsNoNoQuick edits
ResXManagerWindowsYesGoogle Translate.NET teams
Zeta Resource EditorWindowsYesNoSmall teams
POEditorWebYesMTNon-dev translators
CrowdinWebYesMTEnterprise
Better i18nWeb + CLIYesAI-poweredWeb + .NET hybrid

ResXManager is the most widely used — open-source, side-by-side editing, missing translation highlighting.


Common Issues

Translations not showing? Check file naming case sensitivity (Linux/macOS), satellite assembly presence, and ResourcesPath in AddLocalization().

Culture fallback: fr-CAfr → default. Missing keys fall back silently.

Thousands of keys? Split by functional area: Strings.Common.resx, Strings.Checkout.resx, etc.

Keeping files in sync? Use ResXManager's missing-translation view or a build-time check.


Modern Alternatives

JSON-Based: IStringLocalizer<T> works with JSON providers. More readable in PRs, but no strongly-typed wrapper.

CDN-Based: Better i18n delivers translations from Cloudflare's edge. Update strings without a redeploy.

When .resx is still right: Desktop apps (WPF, WinForms, MAUI) that must work offline. Satellite assemblies are the correct model.


Conclusion

Start with .resx and Visual Studio for any .NET project. Add ResXManager at 3+ languages. Consider JSON or CDN for web-first projects. Keep .resx for desktop apps.


References

Last updated: March 2026