Skip to main content

Convert .NET .resx to JSON (i18next) — bring Microsoft resource files to a JavaScript client

Free CLI to convert .NET RESX resource files to i18next-style JSON bundles. Strips the resheader scaffolding, keeps values, sorts deterministically for clean diffs.

Free CLI — convert resx files to i18next:

npm install -g @i18n-agent/i18n-convert
Need to translate, not just convert? Try i18nagent.ai MCP →

.resx is Microsoft's XML resource format, the canonical way to store user-facing strings in .NET desktop, Xamarin, and many legacy ASP.NET projects. Modern web frontends, by contrast, want a flat i18next-style JSON object that can be served as a static asset and consumed directly by react-i18next, next-intl, or any other JavaScript i18n library. Teams that have a long .NET history and a new web client repeatedly write the same conversion — typically as a one-off PowerShell or Python script that gets the schema mostly right and the escaping mostly wrong.

i18n-convert parses the RESX XML, skips the boilerplate <resheader> blocks that every RESX file is required to start with, and emits a JSON object whose keys are the name attributes of the <data> elements and whose values are the inner text of the <value> children. The xml:space="preserve" attribute is respected — meaningful whitespace inside <value> is kept, while unrelated XML formatting whitespace between elements is discarded. Empty <value> elements become empty strings in the JSON (""), not null, so downstream code can rely on values being strings without runtime checks. The output is sorted alphabetically by key for deterministic diffs across translation rounds. <comment> siblings are dropped because i18next JSON has no slot for them.

Command

i18n-convert simple.resx --to i18next -o messages.json

Input

<?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="greeting" xml:space="preserve">
    <value>Hello, World!</value>
  </data>
  <data name="farewell" xml:space="preserve">
    <value>Goodbye!</value>
  </data>
  <data name="empty_value" xml:space="preserve">
    <value></value>
  </data>
</root>

Output

{
  "empty_value": "",
  "farewell": "Goodbye!",
  "greeting": "Hello, World!"
}

Related conversions