---
title: "verbatra check"
description: "Melde fehlende oder veraltete Keys pro Locale, ohne Dateien zu schreiben oder einen Provider aufzurufen, und lass die CI scheitern, solange etwas abweicht."
type: "reference"
---
# verbatra check

Melde fehlende oder veraltete Keys pro Locale, ohne Dateien zu schreiben oder einen Provider aufzurufen, und lass die CI scheitern, solange etwas abweicht.

Melde pro Ziel-Locale, wie viele Keys fehlen, veraltet oder aktuell sind, und beende den Lauf mit einem Code, auf den ein CI-Schritt verzweigen kann. `check` liest und difft wie [`verbatra translate`](https://verbatra.kreitz-webdev.de/de/docs/cli/translate.md) vor dem Provider-Aufruf und hört dann auf: kein Provider-Aufruf, keine geschriebene Datei, kein API-Key nötig.

## Synopsis [#synopsis]

```bash
verbatra check [flags]
```

## Beispiele [#beispiele]

```bash
# den Build scheitern lassen, wenn Übersetzungen abgedriftet sind
verbatra check

# maschinenlesbarer Status für zwei Locales
verbatra check --locales de,fr --json

# zusätzlich Quelltexte listen, die unterschiedlich übersetzt sind
verbatra check --consistency

# bei kaputten Platzhaltern, Markup und ICU scheitern, und auch bei Warnungen
verbatra check --qa --strict

# scheitern, solange maschinelle Übersetzungen auf Freigabe warten
verbatra check --require-reviewed

# bei E-Mails, API-Keys oder Kartennummern in der Quelle fehlschlagen
verbatra check --sensitive

# nur die eine Datei prüfen, die ein Editor oder Agent gerade geändert hat
verbatra check --file locales/de.json --json
```

## Flags [#flags]

| Flag | Argument | Standard | Wirkung |
| --- | --- | --- | --- |
| `--locales` | `<list>` | alle konfigurierten Ziele | prüft nur diese kommagetrennte Teilmenge; eine nicht konfigurierte Locale scheitert mit `UNKNOWN_LOCALE`, eine leere Liste mit `INVALID_LOCALES`, beide mit Exit `2` |
| `--consistency` | keins | aus | listet zusätzlich Quelltexte, die unterschiedlich übersetzt sind; nur ein Bericht, siehe [Konsistenzbericht](#konsistenzbericht) |
| `--qa` | keins | aus | führt zusätzlich die [Qualitätsprüfung](#qualitätsprüfung) über jede committete Übersetzung aus; Exit `1` bei einem Fehler |
| `--file` | `<path>` | aus | prüft nur diese Locale-Datei, siehe [Eine Datei](#eine-datei); nicht mit `--locales`, `--consistency`, `--require-reviewed` oder `--sensitive` |
| `--severity` | `error` oder `warning` | `warning` | mit `--qa` oder `--file` die niedrigste gemeldete Schwere |
| `--strict` | keins | aus | mit `--qa` oder `--file` auch Exit `1` bei einer Warnung oder [unvollständigen Pluralform](#pluralkategorien); nicht mit `--severity error` |
| `--require-reviewed` | keins | aus | zusätzlich Exit `1`, solange eine maschinell geschriebene Übersetzung [nicht freigegeben](#freigegebene-übersetzungen-verlangen) ist |
| `--sensitive` | keins | aus | durchsucht zusätzlich Quelldatei und Glossar nach [sensiblen Inhalten](#sensible-inhalte); Exit `1` bei jedem Fund |

Nimmt außerdem die [globalen Flags](https://verbatra.kreitz-webdev.de/de/docs/cli.md#globale-flags) `--cwd`, `--config` und `--json`.

Ein Key fehlt, wenn die Quelle ihn hat und das Ziel nicht, und er ist veraltet, wenn sich sein Quelltext seit der letzten Übersetzung geändert hat. Eine Locale ist synchron, wenn sie keins von beidem hat. Die Key-Listen hinter den Zahlen liefert [`verbatra diff`](https://verbatra.kreitz-webdev.de/de/docs/cli/diff.md).

## Verhalten [#verhalten]

### Konsistenzbericht [#konsistenzbericht]

<AvailableFrom version="0.11.0" />

`--consistency` listet pro Ziel-Locale jeden Quelltext, den zwei oder mehr Keys unterschiedlich übersetzen: die Quelle, jede Übersetzung und die Keys, die sie tragen. Er ändert nie den Exit-Code, einen Wert oder die Review-Warteschlange. Die Vergleichsregeln:

- Werte werden nach Unicode-NFC-Normalisierung verglichen, `\r\n` wird zu `\n`, äußere Leerzeichen fallen weg. Leerzeichen im Inneren und Groß- und Kleinschreibung zählen.
- Nur aktuelle Keys werden verglichen, und eine Übersetzung gleich ihrer Quelle bleibt `EQUALS_SOURCE` überlassen.
- Keys mit unterschiedlicher Beschreibung, Bedeutung, Plural-Kennzeichnung oder gettext-`msgctxt` werden nie gruppiert.
- Pluralformen werden pro Form verglichen: Die Formen `one` und `other` eines Keys werden nie miteinander gruppiert.

Bekannte Fehlalarme: i18next-Kontextvarianten (`invite_male`, `invite_female`), gettext-Einträge mit `#, fuzzy`, pluralartige Keys in einem Format ohne Plurale (`yaml`, `ngx-translate-json`, `xliff`, `properties`, `ini`, `resx`) und die Pluralformen eines `custom:`-Formats. Gib solchen Keys eine abweichende Beschreibung oder Bedeutung oder ignoriere den Befund. Mit `--json` trägt jede Locale `inconsistencies: { source, context?, description?, meaning?, isPlural, pluralForm?, translations: [{ value, keys }] }[]`.

### Geschützte Keys [#geschützte-keys]

<AvailableFrom version="0.12.0" />

Ein veralteter Key, den eine Person geschrieben, importiert oder außerhalb von verbatra geändert hat, oder ein Key, der auf `pinnedKeys` passt, bleibt bei `translate` für eine Person liegen (siehe [Menschliche Übersetzungen schützen](https://verbatra.kreitz-webdev.de/de/docs/protecting-human-translations.md)). `check` zählt ihn trotzdem und zeigt den geschützten Anteil, etwa `2 stale (1 protected)`. `--json` liefert ihn als `protected` pro Locale; ist `verbatra.provenance.json` unlesbar, zählen nur gepinnte Keys.

### Pluralkategorien [#pluralkategorien]

<AvailableFrom version="0.12.0" />

Jedes `check` listet die Plurale, denen eine CLDR-Pluralkategorie ihrer Zielsprache fehlt, etwa ein polnisches Android-`<plurals>` mit nur `one` und `other`:

```text output
plural categories (warning: exit 1 only under --qa --strict)
  pl: 2 plurals missing CLDR categories
    cart {count} plural: missing few, many
    files: missing few, many
```

Die Kategorien stammen aus den CLDR-Regeln von Node.js (siehe [Sprachunterstützung](https://verbatra.kreitz-webdev.de/de/docs/language-support.md#plurale)). Geprüfte Formate:

| Format | Gelesene Pluralformen |
| --- | --- |
| `i18next-json` | die Key-Suffixe `_one`, `_few`, ... und `_ordinal_`-Plurale gegen die Ordinalregeln |
| `android-xml` | die `<item quantity>`-Einträge jedes `<plurals>` |
| `apple-strings` | die Pluralregeln in der `.stringsdict` neben der `.strings`-Datei |
| `apple-xcstrings` | die `variations.plural`-Kategorien jeder Locale |
| `next-intl-json`, `arb` | jedes ICU-`plural` und -`selectordinal`, auch verschachtelte |

`other` ist immer Pflicht. Ein exakter Zweig wie `=1` ersetzt nie eine Kategorie, `select`-Zweige werden nie geprüft, und geprüft wird nur ein Plural, von dem das Ziel mindestens eine Form hat. Es ist eine Warnung: Ein einfaches `check` behält seinen Exit-Code, `--qa --strict` schlägt daran fehl. [`verbatra doctor`](https://verbatra.kreitz-webdev.de/de/docs/cli/doctor.md) meldet dieselben Plurale. Mit `--json` trägt jede Locale `incompletePlurals`, nach Key sortiert:

```ts
interface IncompletePlural {
  code: "PLURAL_CATEGORIES_INCOMPLETE";
  key: string;              // Basis-Key oder der Key der ICU-Nachricht
  argument?: string;        // das Argument des ICU-Plurals, etwa count
  ruleType: "cardinal" | "ordinal";
  missing: ("zero" | "one" | "two" | "few" | "many" | "other")[]; // in CLDR-Reihenfolge
}
```

### Qualitätsprüfung [#qualitätsprüfung]

<AvailableFrom version="0.12.0" />

`--qa` wendet die Prüfungen, die ein Übersetzungslauf auf Provider-Ausgaben anwendet, auf die Werte an, die schon in deinen Locale-Dateien stehen, veraltet oder nicht, samt zusätzlicher Pluralformen, die die Zielsprache braucht. Befunde gibt es in zwei Schweregraden:

- **error**: Der Wert fällt durch das [Integritäts-Gate](https://verbatra.kreitz-webdev.de/de/docs/translation-safety.md#das-integritäts-gate), mit `placeholder`, `markup`, `icu`, `degenerate` oder `empty`. Die Details listen entfernte Tokens als `-{{name}}` und hinzugefügte als `+{{nom}}`.
- **warning**: Der Wert trägt einen [Review-Grund](https://verbatra.kreitz-webdev.de/de/docs/translation-safety.md#review-flags), der sich aus dem Wert, seiner Quelle und deiner Konfiguration (Glossar, `maxLength`) ergibt, also keinen, der vom Provider oder vom Cache abhängt; bei `FOREIGN_PLACEHOLDER_CHANGED` nennen die `details` des Befunds jedes verlorene oder veränderte Token, etwa `-{name}`. Ein Wert mit Fehler bekommt keine Warnungen.

```text output
qa: 1 error, 1 warning
  de: 1 error, 1 warning in 42 values checked
    greeting: error placeholder (-{{name}}, +{{nme}})
    title: warning EQUALS_SOURCE
```

Verwaiste und fehlende Keys werden übersprungen, und Quell-Keys, die kein gültiges ICU sind, stehen einmal unter `invalidSourceKeys`. Geschützte, gepinnte und abgelehnte Werte werden wie alle anderen geprüft. Mit `--json` hält `result.qa` die Summen und jede Locale ihr eigenes `qa`:

```ts
interface CheckQaSummary { errors: number; warnings: number; invalidSourceKeys: string[] }
interface LocaleQaReport { checked: number; errors: number; warnings: number; findings: QaFinding[] }
type QaFinding =
  | { key: string; severity: "error"; reason: "placeholder" | "markup" | "icu" | "degenerate" | "empty"; details?: string[] }
  | { key: string; severity: "warning"; reason: string; details?: string[] }; // einer der Review-Gründe oben
```

### Freigegebene Übersetzungen verlangen [#freigegebene-übersetzungen-verlangen]

<AvailableFrom version="0.12.0" />

`--require-reviewed` schlägt mit Exit `1` fehl, solange ein Wert mit [Herkunft](https://verbatra.kreitz-webdev.de/de/docs/the-lock-file.md#herkunft-wer-welchen-wert-geschrieben-hat) `machine`, `memory`, `fuzzy` oder `agent` in der committeten `verbatra.provenance.json` nicht freigegeben ist; dort speichern [Studio](https://verbatra.kreitz-webdev.de/de/docs/review-in-studio.md) und die [MCP-Tools](https://verbatra.kreitz-webdev.de/de/docs/cli/mcp.md) ihre Entscheidungen. Eine Freigabe von vor der Änderung des Quelltexts oder des Werts zählt nicht.

```text output
review: failed [REVIEW_REQUIRED] 2 machine-written translations not approved
  de: 2 unreviewed: checkout.title, checkout.total
```

Mit `--json` ist `result.review` gleich `{ reviewed, unreviewed, code? }`, wobei `code` `REVIEW_REQUIRED` ist oder `REVIEW_STATE_UNREADABLE`, wenn die Provenance-Datei beschädigt ist oder von einem neueren verbatra stammt (das Gate schlägt dann fehl). Jede Locale trägt `review.unreviewed`, die Keys in Quellreihenfolge.

### Sensible Inhalte [#sensible-inhalte]

<AvailableFrom version="0.12.0" />

`--sensitive` führt die Prüfung des [Schutzes für sensible Inhalte](https://verbatra.kreitz-webdev.de/de/docs/data-handling.md#schutz-für-sensible-inhalte) über jeden Quell-Key (Key-Name, Wert, Beschreibung und Bedeutung) und das Glossar jeder geprüften Locale aus, mit den Detektoren, Mustern und der Allow-Liste aus `sensitiveData` (ohne Block den Standard-Detektoren), bei jedem `mode` und Provider, auch `none`: Werte verlassen den Rechner trotzdem über Export-, XLIFF- und TMX-Übergaben. Es meldet Keys und Detektoren, nie gefundenen Text außerhalb eines Key-Namens, und endet bei jedem Fund mit Exit `1`.

Der Detektor `email` überspringt [reservierte Beispiel-Domains](https://verbatra.kreitz-webdev.de/de/docs/data-handling.md#schutz-für-sensible-inhalte), teste also mit einer realistisch wirkenden Adresse.

```text output
sensitive: 1 key and 0 glossary terms hold content that looks sensitive
  support.contact: email in value
```

Mit `--json` ist `result.sensitive` gleich `{ findings, glossaryTerms }`, jeder Fund `{ key, fields, detectors }`; `detectors` kann `pattern-timeout-<n>` enthalten.

### Eine Datei [#eine-datei]

<AvailableFrom version="0.12.0" />

`--file <path>` prüft eine einzelne Locale-Datei, gedacht für Editor- und Agent-Hooks nach einer Änderung. Es liest diese Datei, `verbatra.limits.json` <AvailableFrom version="0.13.0" /> (wenn unbrauchbar, mit einem Hinweis auf stderr ignoriert, wie unter `--qa`; [`doctor`](https://verbatra.kreitz-webdev.de/de/docs/cli/doctor.md) nennt das Problem) und, bei einer Ziel-Locale, die Quelldatei, sonst nichts. Der Pfad wird gegen `--cwd` aufgelöst und über `files.pattern` einer Locale zugeordnet.

- Eine Datei, die sich nicht parsen lässt, ergibt einen `syntax`-Fehler mit dem Code des Adapters (`INVALID_JSON`, `INVALID_YAML`, ...) und Zeile und Spalte, wenn der Parser eine Position meldet.
- Eine Zieldatei wird wie bei [`--qa`](#qualitätsprüfung) geprüft, Pluralkategorien eingeschlossen, eine Quelldatei nur auf Syntax. Ein `apple-xcstrings`-Katalog wird für jede Ziel-Locale geprüft.
- Ein Pfad, der keine konfigurierte Locale-Datei ist, schlägt mit `NOT_A_LOCALE_FILE` und Exit `2` fehl.

Mit `--json` verwendet `result` den Bericht von `--qa` wieder, sodass ein Hook nur eine Form parst:

```ts
interface CheckFileSummary {
  file: string;                          // relativ zur Projektwurzel
  role: "source" | "target" | "catalogue";
  locales: {
    locale: string;
    incompletePlurals: IncompletePlural[];
    qa: { checked: number; errors: number; warnings: number; findings: (QaFinding | QaSyntaxFinding)[] };
  }[];
  qa: CheckQaSummary;
}
interface QaSyntaxFinding {
  severity: "error"; reason: "syntax"; code: string; message: string;
  line?: number; column?: number;       // wenn der Parser eine Position meldet, ab 1 gezählt
}
```

Fehlende und veraltete Keys gehören nicht zur Dateiprüfung.

### JSON-Ausgabe [#json-ausgabe]

Schema: [`check-envelope.json`](https://verbatra.kreitz-webdev.de/schema/v1/check-envelope.json) validiert den ganzen Envelope; [Schemas](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#schemas) listet die übrigen auf.

`--json` gibt einen [Umschlag](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#json-ausgabe) aus, dessen `result` das Statusdokument ist. Ohne `--qa`, `--require-reviewed` und `--sensitive` ist `inSync` genau dann wahr, wenn der Befehl mit `0` endet:

```ts
interface CheckSummary {
  inSync: boolean;
  locales: LocaleCheckSummary[];
  qa?: CheckQaSummary;          // nur mit --qa
  review?: CheckReviewSummary;  // nur mit --require-reviewed
  sensitive?: CheckSensitiveSummary; // nur mit --sensitive
}

interface LocaleCheckSummary {
  locale: string;
  missing: number;              // in der Quelle, fehlt im Ziel
  stale: number;                // Quelle seit der letzten Übersetzung geändert
  upToDate: number;
  inSync: boolean;              // missing === 0 && stale === 0
  emptySource?: number;         // Quellwert leer: nie fehlend oder veraltet
  provenance?: ProvenanceSummary; // Zählungen nach Herkunft und Review-Status
  protected?: number;
  incompletePlurals?: IncompletePlural[];
  inconsistencies?: InconsistencyGroup[]; // nur mit --consistency
  qa?: LocaleQaReport;          // nur mit --qa
  review?: LocaleReviewReport;  // nur mit --require-reviewed
}
```

Ein Quell-Key, dessen Wert leer ist oder nur aus Leerraum besteht, etwa einer, den `extract` ohne Standardwert ergänzt hat, hat noch nichts zu übersetzen: Er wird in `emptySource` statt in `missing` oder `stale` gezählt, bringt eine Locale nie aus dem Takt, und die Terminalausgabe nennt die Zahl.

### Rückmeldung im Terminal [#rückmeldung-im-terminal]

<AvailableFrom version="0.12.0" />

`check` zeigt auf stderr `verbatra: checking the locales... done (0.1s)`, mit `--file` `verbatra: checking locales/de.json...`. `--quiet` lässt die Zeile weg. Siehe [Terminalausgabe](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#terminalausgabe).

## Exit-Codes [#exit-codes]

| Code | Bedeutung |
| --- | --- |
| `0` | synchron, und kein Befund, den die übergebenen Flags zum Fehlschlag machen |
| `1` | eine Locale hat einen fehlenden oder veralteten Key, `--qa` oder `--file` hat einen Fehler gefunden (oder unter `--strict` eine Warnung oder einen unvollständigen Plural), `--require-reviewed` hat eine nicht freigegebene Übersetzung gefunden, oder `--sensitive` hat sensible Inhalte gefunden |
| `2` | konnte nicht laufen: ein Fehler für den ganzen Lauf wie `SOURCE_UNREADABLE` oder `NOT_A_LOCALE_FILE`, oder ein Nutzungsfehler wie `INVALID_QA_OPTION`, `INVALID_SEVERITY` oder `INVALID_OPTION` für ein leeres `--file` oder eines zusammen mit `--locales`, `--consistency`, `--require-reviewed` oder `--sensitive` |

Exit `1` heißt, dass das Ergebnis nicht sauber ist, nicht dass der Lauf gescheitert ist; der Bericht wird trotzdem ausgegeben. Bei einem Projekt, dessen Quelldatei noch fehlt, meldet [`verbatra doctor`](https://verbatra.kreitz-webdev.de/de/docs/cli/doctor.md) weiterhin. Den Vertrag findest du unter [Exit-Codes](https://verbatra.kreitz-webdev.de/de/docs/cli/output.md#exit-codes).

## Siehe auch [#siehe-auch]

- [`verbatra diff`](https://verbatra.kreitz-webdev.de/de/docs/cli/diff.md) listet die genauen Keys hinter diesen Zahlen.
- [CI und Exit-Codes](https://verbatra.kreitz-webdev.de/de/docs/ci-and-exit-codes.md) zeigt `check` als Drift-Gate.
- [Die Lock-Datei](https://verbatra.kreitz-webdev.de/de/docs/the-lock-file.md) erklärt, wie Veraltung erkannt wird.
