Skip to main content

Convert XLIFF 2.0 to XLIFF 1.2 | i18n Agent

Free CLI to convert XLIFF 2.0 files into XLIFF 1.2 for translation systems that don't speak 2.0 yet. Preserves source, target, and translation state.

Free CLI — convert xliff2 files to xliff:

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

XLIFF 2.0 is the modern, cleaner successor to XLIFF 1.2, with a saner element hierarchy (<unit> / <segment> instead of <trans-unit>) and explicit state attributes on segments rather than on targets. Almost every modern open-source localization tool produces 2.0 by default. The catch: a depressingly large number of paid translation management systems — including some very expensive ones — still require XLIFF 1.2 on import, and silently ignore or reject 2.0 documents. The downgrade is unavoidable whenever you have to ship a translation round through a TMS that has not caught up to the 2014 spec.

i18n-convert rewrites the document tree from 2.0 into 1.2: the root <xliff> element switches to the 1.2 namespace, every <unit> becomes a <trans-unit> wrapped inside a <file><body> container, and every <segment> is collapsed into the <trans-unit> with its <source> and <target> children promoted directly underneath. Segment-level state attributes ("translated", "initial") are moved onto the <target> element using 1.2's vocabulary ("translated", "new"), so the target's translation status survives the downgrade. The srcLang and trgLang attributes on the 2.0 root are restated as source-language and target-language on <file>. The original attribute carrying the source filename is preserved.

Command

i18n-convert simple.xliff --to xliff -o output.xliff

Input

<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de">
  <file id="f1" original="messages.json">
    <unit id="greeting">
      <segment state="translated">
        <source>Hello</source>
        <target>Hallo</target>
      </segment>
    </unit>
    <unit id="farewell">
      <segment state="translated">
        <source>Goodbye</source>
        <target>Auf Wiedersehen</target>
      </segment>
    </unit>
    <unit id="untranslated">
      <segment state="initial">
        <source>Not yet translated</source>
      </segment>
    </unit>
  </file>
</xliff>

Output

<?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">
    <body>
      <trans-unit id="greeting">
        <source>Hello</source>
        <target state="translated">Hallo</target>
      </trans-unit>
      <trans-unit id="farewell">
        <source>Goodbye</source>
        <target state="translated">Auf Wiedersehen</target>
      </trans-unit>
      <trans-unit id="untranslated">
        <source>Not yet translated</source>
        <target state="new"></target>
      </trans-unit>
    </body>
  </file>
</xliff>

Related conversions