Skip to main content

Convert XLIFF 1.2 to JSON (i18next) — target side becomes the runtime bundle

Free CLI to convert XLIFF 1.2 translation handoff files into i18next-style JSON. Uses target language values, preserves keys, sorts output deterministically.

Free CLI — convert xliff files to i18next:

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

XLIFF 1.2 is what most translation management systems hand back after a translation round. It is bilingual by design: every <trans-unit> has a <source> element with the original English (or whatever the source language is) and a <target> element with the translation. Your web app, on the other hand, consumes a single-language JSON bundle — typically the i18next-style flat map of keys to translated strings. Going from XLIFF to runtime JSON therefore involves a conscious choice: keep the source strings (for an English bundle) or keep the targets (for a localized bundle). Most ad-hoc scripts get this wrong by emitting whichever side appears first in the XML.

i18n-convert extracts the <target> text from each <trans-unit>, uses the id attribute as the JSON key, and sorts the output alphabetically for stable diffs. Entries whose target is missing — which happens for any unit that has not yet been translated — emit an empty string rather than being dropped, so your runtime keeps the keys and can fall back through your i18n library's resolution chain. Because XLIFF can carry source strings that have no corresponding target, the CLI surfaces a data-loss warning and requires --force to proceed; this acknowledges that the source-side text is being discarded by design.

Command

i18n-convert simple.xliff --to i18next --force -o messages.json

Input

<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en" target-language="de" datatype="plaintext" original="messages.properties">
    <body>
      <trans-unit id="greeting">
        <source>Hello</source>
        <target>Hallo</target>
      </trans-unit>
      <trans-unit id="farewell">
        <source>Goodbye</source>
        <target>Auf Wiedersehen</target>
      </trans-unit>
      <trans-unit id="untranslated">
        <source>Not yet translated</source>
      </trans-unit>
    </body>
  </file>
</xliff>

Output

{
  "farewell": "Auf Wiedersehen",
  "greeting": "Hallo",
  "untranslated": ""
}

Related conversions