Skip to main content

Convert XLIFF 2.0 to XLIFF 1.2 — downgrade for legacy TMS compatibility

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