They are two different XML vocabularies that share a name. XLIFF 1.2 became an OASIS Standard in February 2008; XLIFF 2.0 followed in August 2014 and was revised as 2.1 in February 2018. The 2.x specification states that its documents cannot be conformant to 1.2 and that 2.x applications are not required to read 1.2. Editing version="1.2" to version="2.0" therefore produces a file that is valid in neither: the namespace, the element names and the structure all differ.
The main differences:
<xliff>, <file>, <body>, <trans-unit> with <source> and <target>; 2.x nests <xliff>, <file>, <unit>, <segment> with <source> and <target>, and a unit may be split into several segments.source-language and target-language on each <file>; 2.x puts srcLang and trgLang once on the root.urn:oasis:names:tc:xliff:document:1.2 versus urn:oasis:names:tc:xliff:document:2.0 (2.1 keeps the 2.0 namespace with version="2.1").<g>, <x/>, <bpt>/<ept>, <ph> in 1.2; <pc>, <ph>, <sc>/<ec> with the original markup in <originalData> in 2.x.state values on <target> (new, translated, signed-off, final and others) plus approved on <trans-unit>; 2.x has four on <segment>: initial, translated, reviewed, final.<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file original="app" source-language="en" target-language="de" datatype="plaintext">
<body>
<trans-unit id="greeting">
<source>Hello</source>
<target state="translated">Hallo</target>
</trans-unit>
</body>
</file>
</xliff>
<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0" srcLang="en" trgLang="de">
<file id="f1">
<unit id="greeting">
<segment state="translated">
<source>Hello</source>
<target>Hallo</target>
</segment>
</unit>
</file>
</xliff>
Which one you get is decided by the exporter. Xcode writes 1.2 (its XLIFF uses <trans-unit>), Angular's ng extract-i18n writes 1.2 by default and 2.0 with --format=xlf2, and Symfony's translation:extract defaults to xlf12 with xlf20 as the alternative. Poedit and OmegaT open both; parts of Okapi's XLIFF 2 support are still documented as experimental, so 1.2 is the safer choice when the receiving tool is unknown.
Converting an existing file: prefer re-exporting from the source tool in the version the consumer accepts, because the exporter knows the original ids and placeholders. If you only have the file, the Okapi Framework reads both versions through its XLIFF and XLIFF-2 filters and writes either: Rainbow's Translation Kit Creation step offers a Generic XLIFF (1.2) and an XLIFF 2.0 package format, and Tikal's tikal -x extracts any supported input, including an XLIFF 2 document, into a 1.2 file that tikal -m merges back after translation. Check ids, notes and inline codes afterwards; Okapi's own docs list comments and original formatting as things the XLIFF 2 round trip loses. If a tool only accepts 1.2, export 1.2 at the source and skip the conversion.
Published Oct 9, 2026 · Markdown version