MQXLIFF files

The bilingual export from memoQ. Like SDLXLIFF it is XLIFF 1.2 with a vendor namespace on top, but it solves the same problems in a noticeably lighter way: the confirmation level, the match rate and the change log all sit as attributes on the trans-unit itself.

The mq namespace

The first surprise is the namespace URI. It is not a URL, not a URN, just the bare string MQXliff:

<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:mq="MQXliff" version="1.2">
  <file original="AdminGuide.docx" source-language="en" target-language="hu"
        datatype="x-mq-doc" mq:filename="AdminGuide.docx" mq:package="AdminGuide-hu.mqout">
    <header>
      <phase-group>
        <phase phase-name="translation" process-name="translation" tool-id="memoQ"
               date="2026-05-12T09:14:22Z" contact-name="translator1"/>
      </phase-group>
      <tool tool-id="memoQ" tool-name="memoQ translator pro" tool-version="11.2.9"/>
    </header>

That is legal — a namespace name only has to be a URI reference, and a bare relative reference qualifies — but strict validators complain about it and some libraries normalize it away. It is worth knowing before you spend an afternoon deciding your file is broken.

The prefix is conventionally mq, but the prefix is not the contract; the namespace is. xliff.ai reads the actual xmlns: declaration off the root and follows whatever prefix that document bound, so a re-prefixed export still round-trips.

The header carries a <phase-group> listing the workflow steps the file has been through, each with a contact name and a date, plus a <tool> element naming the version that produced it. The file element adds mq:filename and mq:package, which is how a delivered bilingual finds its way back into the right document in the right package.

Status is on the trans-unit

The XLIFF 1.2 state attribute on <target> is usually absent from these files, and it is not where the confirmation level lives. mq:status on <trans-unit> is.

<trans-unit id="3" mq:status="ManuallyTranslated" mq:percent="100"
            mq:lastchangeduser="translator1" mq:lastchangeddate="2026-05-12T10:05:18Z"
            mq:firstlastchangeduser="translator1">
  <source>Export the project before you archive it.</source>
  <target>Exportálja a projektet, mielőtt archiválná.</target>
</trans-unit>

<trans-unit id="6" mq:status="Reviewer1" mq:lastchangeduser="reviewer1"
            mq:lastchangeddate="2026-05-18T12:03:31Z">
  <source>Welcome back. You have unread notifications.</source>
  <target>Üdvözöljük újra. Olvasatlan értesítése van.</target>
  <mq:comment mq:author="reviewer1" mq:timestamp="2026-05-18T12:03:31Z"
              mq:type="Comment" mq:deleted="false">Kept the formal register here.</mq:comment>
</trans-unit>
mq:status What it means
NotStarted Nobody has confirmed the row. Normally an empty target, but a pre-translated hit that was never confirmed sits here too.
PartiallyEdited Someone typed in the row and moved on without confirming it.
ManuallyTranslated Confirmed by the translator. The ordinary result of confirming a row.
Edited A translation memory, fragment or machine hit that a human then edited and confirmed. Counted as translated.
Proofread Confirmed in the proofreading step.
Reviewer1 Confirmed by the first reviewer role.
Reviewer2 Confirmed by the second reviewer role — the end of the default workflow.
Locked Not a confirmation level. It appears alongside mq:locked="true" and means the row is read-only.

The two reviewer levels are the part that trips people up. They are not seniority grades; they are the two review roles in the default workflow, and a row confirmed by the second reviewer is as finished as the format gets. xliff.ai reads Proofread and Reviewer1 as reviewed and Reviewer2 as final. A status string that is not in the list above — the vendor adds levels over time — is kept exactly as written and the row's state is inferred from whether the target holds text.

Match rate and change log

mq:percent is the match rate the row was populated with: 85 for a fuzzy hit, 100 for an exact one, and values above 100 for matches whose surrounding context also matched — a 101 is a context match, not a rounding error. A row with no percent was typed from scratch.

mq:lastchangeduser and mq:lastchangeddate record who last touched the row and when, in UTC. mq:firstlastchangeduser keeps the name of the first person who worked on it, which is what survives a row passing through translation and then two review steps.

These are audit data, and xliff.ai does not forge them. Editing a row here changes the target text and, if you change the status, the mq:status attribute — nothing else. Your name does not appear in the file, and the previous contributor's name is not overwritten with it. If your workflow needs the change log updated, confirm the rows in the tool that owns the workflow after you deliver.

Comments and locked rows

Comments are simpler here than in the other vendor dialect: a <mq:comment> element sits directly inside the trans-unit it belongs to, with mq:author, mq:timestamp, mq:type and an mq:deleted flag — deleted comments stay in the file, marked. There is no separate definitions block and no anchor into the middle of the target, so nothing breaks when the target text changes.

A locked row carries mq:locked="true", and frequently mq:status="Locked" as well. Project managers lock repeated content, product names and anything already approved. xliff.ai shows locked rows in the grid, greyed and read-only: you can read them, search them and copy from them, and an export leaves their bytes exactly as they arrived.

UTF-16 files

Some of these exports are UTF-16, usually little-endian with a byte-order mark, while others are UTF-8. Both are valid and both turn up in the same project. The practical symptoms of UTF-16 are familiar: the file is roughly twice the size you expected, and a text editor that assumes UTF-8 shows a null byte between every character.

xliff.ai detects the encoding from the byte-order mark, falls back to sniffing the XML declaration when there is none, and decodes strictly — a file whose bytes do not match its detected encoding fails when you open it rather than silently producing damaged output hours later. Replacement text is encoded back into the file's own encoding, and the byte-order mark stays where it was. A UTF-16 file exports as a UTF-16 file, the same length in bytes as the one you opened if you changed nothing.

Inline tags

Inline codes use ordinary XLIFF 1.2 elements — bpt, ept, ph, x — with the native markup escaped inside them, plus occasional mq attributes such as mq:nomap on a placeholder that has no counterpart in the source document's tag map. The XLIFF 1.2 inline tag reference applies without changes. Vendor attributes on those tags survive an export for the same reason everything else does: they are never written.

What an export changes

The rule for this format is short. Never rewrite an mq: attribute you did not change. xliff.ai keeps the original bytes, splices the target content of the segments you edited, and edits the mq:status attribute in place on the trans-unit tags whose status you changed. Percent, both user attributes, the timestamp, comments, the phase group, the tool element and every attribute nobody has documented come back byte for byte.

Open a file, change nothing, export it, compare the bytes: identical, including the byte-order mark and the line endings. Change three rows and three target ranges differ, plus three attribute edits. That comparison is an automated test in this project, run against real exports in both encodings.

Related formats

XLIFF 1.2 describes the structure underneath. SDLXLIFF is the equivalent dialect from Trados Studio, which keeps its confirmation levels in a separate block rather than on the unit. XLIFF 2.0 is the standard both dialects would have needed less of.

Reusing a finished bilingual: convert it to TMX.