Quality checks

Updated

Translatize checks every translation against its source text as soon as it is saved: lost placeholders, broken tags, invalid ICU, text over its character limit, glossary terms and more. Findings appear next to the translation in the editor, the merge gate decides whether errors may reach main, and AI review reads for meaning and tone. The rule checks and the merge gate are included on every plan, Free too.

When checks run and where findings show

Every change is checked automatically, whichever way it arrives: typed in the label editor, imported from a file, pushed with the CLI or the API, written by AI translation, or brought in by a merge. Each finding belongs to one key in one target language and has a severity:

  • Error – the translation is broken, for example a placeholder is missing. Only errors can block a merge.
  • Warning – probably wrong, worth a look.
  • Info – a hint, such as a different final punctuation mark.

You see findings in three places:

  • the Quality checks panel in the label editor, per language;
  • a badge on each affected cell of the labels table, with errors, warnings and info;
  • error and warning counts per branch on the Branches page.

The checks compare a translation with its source, so they skip empty translations (to fail a build on missing ones, use translatize status --fail-on-missing), the source language itself, and labels marked "Do not translate", whose copied source text is the right value in every language.

The 10 rule checks

The severity column is what the app shows next to each check in Project Settings → Quality checks.

CheckSeverityWhat it flags, for example
PlaceholdersErrorYou have {count} items translated as Sie haben Artikel – {count} is missing. A renamed {{name}} → {{nom}} is reported as one missing and one extra placeholder.
ICU syntaxErrorThe source is {count, plural, one {# item} other {# items}} and the translation lost its last closing brace. Only checked when the source is an ICU message.
Plural formsWarningA Russian translation with only one and other – Russian also needs few and many. Also flags a plural flattened into plain text and a select that lost one of the source's options.
HTML tagsErrorRead the <a>terms</a>. translated as Lies die <a>Bedingungen. – the <a> is never closed. Tags that differ from the source's are flagged too.
Character limitErrorA key with a limit of 18 characters whose German value, Jetzt kostenpflichtig bestellen, has 31. Set the limit in the label editor under Context & Info.
WhitespaceWarningThe source "Total: " ends with a space and the translation "Gesamt:" doesn't. Leading spaces and line breaks count the same way, and a double space the source doesn't have is flagged.
UntranslatedWarningSave changes left as Save changes in French. Texts under 4 letters, URLs, e-mail addresses, glossary terms whose translation is the term itself, and variants of the same language (en → en-GB) are fine.
GlossaryErrorThe glossary says "workspace" is "Arbeitsbereich" in German, and the translation says Neuen Workspace anlegen. A term marked prohibited that appears in a translation is flagged too.
NumbersWarningFree shipping over 50 € translated as Kostenloser Versand ab 30 €. Separators may follow the language, so 1,000 and 1.000 count as the same number.
End punctuationInfoDelete this project? translated as Supprimer ce projet – the question mark is gone. Not checked for Chinese, Japanese, Korean and Thai.

Placeholder styles

The placeholder, HTML tag and ICU checks only look for the syntaxes you tell them about, under Project Settings → Quality checks → Placeholder styles:

StyleLooks likeDefault
ICU{count}on
Double braces (i18next, Handlebars, Mustache){{name}}on
printf%s %1$d %@on
HTML and XML tags, numbered ones too<b>…</b> <0>…</0>on
Colon names (Laravel):nameoff – ordinary text can look the same

Switching checks off

Every check can be switched off per project in Project Settings → Quality checks → Checks. Turning one off hides its findings at once and stops it counting for the merge gate. Admins and owners change these settings; developers see them read-only.

Placeholder style changes apply the next time a text is checked. To refresh existing findings right away, open AI review on the labels page and click Re-run checks – it works on every plan and re-checks the whole branch, or just the rows you selected.

Ignoring a finding

Some findings are right to leave alone: "Download" really is the German word for a download, and a marketing headline may drop its full stop on purpose. Developers, admins and owners can ignore a finding:

  1. Open the label in the editor.
  2. In the Quality checks panel, click Ignore next to the finding.
  3. Add a reason (optional, up to 500 characters) and click Ignore finding.

The finding stays hidden until the source or the translation changes, so a new mistake in the same string comes back. Ignored findings never count for the merge gate. A branch starts with the ignores of the branch it was created from, and a merge brings the merged keys' ignores along. Show ignored findings lists them with their reasons, and Show again undoes one. Ignoring and un-ignoring are recorded in the audit log.

The merge gate

The merge gate decides what QA errors do to a branch merge. Set it per project in Project Settings → Quality checks → Merge gate:

ModeWhat happens
OffMerges are never checked.
Warn (default)The merge screen shows the QA errors and warnings, and the merge always goes through.
BlockA merge whose translations have QA errors is refused. Admins and owners can override with a written reason; API tokens never can.

Gate merges into chooses the targets: main only (the default) or every branch. The gate checks only the translations the merge would change, runs the rule checks on them at merge time, and leaves out ignored findings and checks you switched off. Warnings, info and AI review findings never block a merge.

What a blocked merge looks like

Before you merge, the merge screen shows a QA gate panel with the mode and a line like "48 translations checked – errors: 2, warnings: 1.", the findings themselves, and a link that opens the source branch in the editor. In Block mode with errors it says "Errors block this merge. Fix them on the source branch first." Fix the translations, and the next check lets the merge through.

Over the API the same merge answers 409 with the gate (shortened here):

POST …/branches/feature-checkout/merge
HTTP/1.1 409 Conflict

{
  "error": "qa_gate_blocked",
  "gate": {
    "mode": "block",
    "applies": true,
    "blocked": true,
    "errors": 2,
    "warnings": 1,
    "pairsChecked": 48,
    "issues": [
      {
        "key": "cart.summary",
        "lang": "de",
        "checkId": "placeholders",
        "severity": "error",
        "code": "placeholder_missing",
        "params": { "placeholders": ["{count}"], "list": "{count}", "count": 1 }
      }
    ]
  }
}

Overriding the gate

Sometimes a finding is a known false positive and the release can't wait. An admin or owner can merge anyway:

  1. On the merge screen, click Override gate… in the QA gate panel.
  2. Write the reason – at least 10 characters, up to 500. For example: "known false positive, the placeholder is added in code".
  3. Click Allow this merge, then merge.

The override goes into the audit log as "Merge approved despite quality gate", with your name, the reason and the number of errors and warnings. Developers and translators can't override; the app tells them to fix the errors or ask an admin or owner.

API tokens can never override
A merge through an API token – a script in your pipeline, an AI agent over MCP – is refused with qa_gate_blocked while the gate blocks, whatever the token's role, and the GitHub App can't override it either. A token merge into main also needs a token with the admin role (403 admin_token_required_for_main). Only a person can wave errors through.

AI review

The rule checks find broken syntax. They can't tell whether a translation says what the source says. AI review reads the source and the translation together, scores each translation from 0 to 100 and points out problems:

  • the meaning may differ from the source;
  • the translation may not read naturally;
  • terminology may not match the glossary or the project;
  • the style may not match the project's style guide;
  • the translation may be too long, or its placeholders may be wrong.

It judges against the style guide, per-language guidance and glossary you set up for AI translation. Findings appear in the label editor's Quality checks panel marked "AI review", with a suggested fix when it has one, and a translation without findings shows its score. AI findings are warnings at most and never block a merge. A finding goes away when the source or the translation changes, or when a new review replaces it.

Running a review

  1. On the labels page, click AI review (next to Auto-Translate). Developers, admins and owners see it.
  2. Under What to review, choose every translation on the branch or the keys you selected in the table, then pick the languages.
  3. Check this month's usage in the dialog and click Start review.

You can close the dialog: the review keeps running, findings appear in the editor as they come in, and you get a notification when it finishes. A project runs one review at a time.

Automatic review after AI translation

In Project Settings → Quality checks, tick AI review after AI translation. From then on, when an AI translation finishes, Translatize reviews the translations it just wrote. It is off by default, admins and owners switch it on, and it uses the same monthly allowance, stopping when the allowance runs out.

Plans and allowance

AI review is part of the Professional and Agency plans, with an allowance of its own, separate from AI translation: 1,000,000 characters a month on Professional and 5,000,000 on Agency. A review uses as many characters as the translations it reviews are long, and translations that could not be reviewed are not counted. A review you start has to fit in what is left of the month; if it doesn't, choose fewer keys or languages. The plan that counts is the one of the account that pays for the project – the project owner, or the workspace owner for a project in a workspace.

CI and agents

CLI: translatize qa

translatize qa runs the rule checks on the token's branch (or the one given with --branch), prints the counts per severity and the first 20 findings, and exits 1 on findings at the --fail-on severity or above. It needs no config file.

shell
export TRANSLATIZE_API_TOKEN=mcni_xxx

# Fail on errors (the default)
npx @translatize/cli qa

# Fail on warnings too
npx @translatize/cli qa --fail-on warning

# Check a branch the token created, preview its merge gate, print JSON
npx @translatize/cli qa --branch feature-checkout --json
  • --fail-on error (default) fails on errors; --fail-on warning fails on errors and warnings. Info never fails. AI review can report warnings too, and they count under warning.
  • On a branch other than the token's base branch, it also previews the merge gate into the base and fails whenever the gate would block, whatever --fail-on says. That needs a token with the Agent workflow scope, which may work on branches it created.
  • --json prints the whole report for scripts.

Every flag is on the CLI page.

GitHub Action

The GitHub Action runs the same command with command: qa. fail-on takes error (default) or warning, and a blocked merge gate always fails the step. Store the token as a repository secret named TRANSLATIZE_TOKEN (see setting up the token secret).

.github/workflows/translation-qa.yml
name: Translation QA

on:
  pull_request:
    branches: [main]

jobs:
  qa:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Fail on QA errors
        uses: translatize/sync-action@v1
        with:
          command: qa
          token: ${{ secrets.TRANSLATIZE_TOKEN }}
          fail-on: error

GitLab CI

With the GitLab component, set command: qa and fail_on. The CLI reads the token from a masked CI/CD variable TRANSLATIZE_API_TOKEN; keep it unprotected if merge-request pipelines should see it.

.gitlab-ci.yml
include:
  - component: gitlab.com/translatize/gitlab/translatize@0.2.0
    inputs:
      command: qa
      fail_on: error

Or without the component:

.gitlab-ci.yml
translatize-qa:
  stage: test
  image: node:24-alpine
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  script:
    - npx --yes @translatize/cli@latest qa --fail-on error

GitHub App

On Professional and Agency, the GitHub App runs the checks and the merge gate preview on every pull request and shows the results on its "Translatize" check, which fails while the gate would block the merge.

MCP tools

An AI agent connected through the MCP server gets five tools for quality:

ToolWhat it does
run_qaRuns the rule checks on a branch and returns the counts and the findings. Optional keys to re-check only some.
get_qa_issuesLists stored findings page by page, filtered by severity, key, language or source (rule or ai).
check_merge_gatePreviews the merge gate for merging a branch into the token's base branch, with the strategy you will merge with.
start_ai_reviewStarts an AI review of a branch, optionally for some keys or languages. Needs the developer role and a Professional or Agency plan.
ai_review_statusReports the latest AI review: its status, progress and the characters it used.

A typical agent loop is translate, run_qa, fix the errors, check_merge_gate, and only then ask you to approve the merge. Like every token, an agent can't override the gate.

Integration API

The same features are on the token API, under /v1/integrations/projects/:projectId:

RouteRoleWhat it does
POST /qa/runtranslatorRun the rule checks on a branch (optional keys).
GET /qa/issuestranslatorList findings with counts; filters and cursor paging.
GET /branches/:branchName/merge-gatetranslatorPreview the gate for a merge into the token's base branch.
POST /qa/ai-reviewdeveloperStart an AI review (optional keys and langs).
GET /qa/ai-review/statustranslatorThe latest AI review and this month's allowance.
shell
curl -X POST "https://api.translatize.com/v1/integrations/projects/$PROJECT_ID/qa/run" \
  -H "Authorization: Bearer $TRANSLATIZE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"branch": "feature-checkout"}'

A merge the gate refuses answers 409 qa_gate_blocked. In Block mode, if the checks can't run at that moment, the merge answers 503 qa_gate_unavailable without writing anything – try again. Full details are in the API reference.

Plans

FreeStarterProfessionalAgency
10 rule checks✓✓✓✓
Merge gate and override✓✓✓✓
QA in CI (CLI, Action, GitLab, MCP)✓✓✓✓
AI review, characters a month––1,000,0005,000,000