Translate

Translate .NET .resx resource files

A .resx file mixes text with icons and other typed resources in one XML. KAERIS translates only the strings, leaves the rest byte for byte, and checks the {0} format items.

How a .resx file is built

An XML <root> with <data name="…"><value>…</value></data> entries. An entry with a type or mimetype attribute (an icon, an image) is not text. Names like SaveButton.Text are control properties from WinForms.

Source fileStrings.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
  <resheader name="resmimetype"><value>text/microsoft-resx</value></resheader>
  <data name="WelcomeMessage" xml:space="preserve">
    <value>Welcome back, {0}!</value>
    <comment>{0} is the user's first name</comment>
  </data>
  <data name="ItemsInCart" xml:space="preserve">
    <value>You have {0} items in your cart.</value>
  </data>
  <data name="SaveButton.Text" xml:space="preserve">
    <value>Save and close</value>
  </data>
  <data name="AppIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\app.ico;System.Drawing.Icon, System.Drawing</value>
  </data>
</root>

What to watch for in .resx translations

A real run: translated to German and checked

A real run, 27 October 2026, nothing edited by hand: kaeris translate Strings.resx --langs de with kaeris 0.2.35, 2.6 seconds, model openai/gpt-4.1-mini (the service's fallback model answered this job). Below, the German file it wrote and what kaeris check says about it.

German resultde/Strings.resx
<?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>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="WelcomeMessage" xml:space="preserve">
    <value>Willkommen zurück, {0}!</value>
  </data>
  <data name="ItemsInCart" xml:space="preserve">
    <value>Sie haben {0} Artikel in Ihrem Warenkorb.</value>
  </data>
  <data name="SaveButton.Text" xml:space="preserve">
    <value>Speichern und schließen</value>
  </data>
  <data name="AppIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\app.ico;System.Drawing.Icon, System.Drawing</value>
  </data>
</root>
kaeris checkexit code 0
$ kaeris check --source Strings.resx --langs de
✓ de: complete & placeholder-safe
✓ all locales complete & placeholder-safe

What KAERIS does with it

Run it in three steps

  1. Install the CLI

    Run pip install kaeris.

  2. Translate the resource file

    Run kaeris translate Resources/Strings.resx --langs de,ja.

  3. Check the result

    Upload the source and the translated .resx on the free check page.

pip install kaeris
kaeris translate Resources/Strings.resx --langs de,ja --verify

Questions

Are icons and other typed resources touched?

No. Entries with a type or mimetype attribute are kept verbatim.

Are elements kept?

No: the translated file is written without them. Your source file keeps them.

Is it free?

Yes, without an account: 10,000 characters per file and up to 8 languages per run. A free API key raises the file limit to 50,000 characters. Lifetime is $79 once, on your own OpenRouter key; monthly plans start at $19. Pricing

Can I run it from the terminal or in CI?

Yes. pip install kaeris, then kaeris translate Resources/Strings.resx --langs de,ja. The GitHub Action runs the same translation in a pull request. CLI docs · GitHub Action

Keep going

CLI reference · Check reference · Translate in the browser · Free check · Convert formats · Pseudo-localization

Other formats: JSON · YAML · .po · ARB · XLIFF · .strings · .xcstrings · .properties · CSV · Markdown · Fluent · Android XML