---
title: "verbatra diff"
description: "Muestra qué claves añadiría o retraduciría una ejecución por locale y cuáles quedan huérfanas, sin escribir archivos ni llamar a un proveedor."
type: "reference"
---
# verbatra diff

Muestra qué claves añadiría o retraduciría una ejecución por locale y cuáles quedan huérfanas, sin escribir archivos ni llamar a un proveedor.

Lista, por locale de destino, las claves pendientes exactas: las que una ejecución añadiría, las que retraduciría y las que ahora están huérfanas. `diff` hace la misma lectura y el mismo diff que [`verbatra translate`](https://verbatra.kreitz-webdev.de/es/docs/cli/translate.md) y luego se detiene: sin llamada al proveedor, sin archivos escritos, sin actualizar el [archivo de bloqueo](https://verbatra.kreitz-webdev.de/es/docs/the-lock-file.md) y sin clave de API.

## Sinopsis [#sinopsis]

```bash
verbatra diff [flags]
```

## Ejemplos [#ejemplos]

```bash
# lista las claves pendientes por locale (sale con 1 si hay alguna)
verbatra diff

# solo los locales alemán y francés
verbatra diff --locales de,fr

# listas de claves legibles por máquina para herramientas o un comentario en el PR
verbatra diff --json

# lista también las claves de origen que tu código ya no nombra
verbatra diff --unused
```

## Flags [#flags]

| Flag | Argumento | Por defecto | Efecto |
| --- | --- | --- | --- |
| `--locales` | `<list>` | todos los destinos configurados | compara solo este subconjunto separado por comas; un locale no configurado falla con `UNKNOWN_LOCALE` y una lista vacía con `INVALID_LOCALES`, ambos con salida `2` |
| `--unused` | ninguno | desactivado | lista también las claves del locale de origen que ninguna llamada bajo las [raíces de `extract`](https://verbatra.kreitz-webdev.de/es/docs/config-file.md#extract) nombra; consulta [Claves de origen sin uso](#claves-de-origen-sin-uso) |

También acepta los [flags globales](https://verbatra.kreitz-webdev.de/es/docs/cli.md#flags-globales) `--cwd`, `--config` y `--json`.

## Comportamiento [#comportamiento]

### Claves pendientes y huérfanas [#claves-pendientes-y-huérfanas]

Cada locale lista cuatro tipos de clave:

| Lista | Significado |
| --- | --- |
| `missing` (se muestra como `add`) | está en el origen y falta en el destino: una ejecución la añadiría |
| `changed` (se muestra como `re-translate`) | el texto de origen cambió desde la última traducción: una ejecución la retraduciría |
| `orphaned` | está en el destino y ya no en el origen: solo se informa |
| `emptySource` (se muestra como `empty source`) | el valor de origen está vacío o solo tiene espacios: nada que traducir hasta que lo escribas, nunca pendiente |

Un locale tiene cambios pendientes cuando tiene al menos una clave faltante o cambiada. Las claves huérfanas nunca cuentan como pendientes, porque una ejecución por defecto las deja donde están; solo [`verbatra translate --prune`](https://verbatra.kreitz-webdev.de/es/docs/cli/translate.md) las elimina. [`verbatra check`](https://verbatra.kreitz-webdev.de/es/docs/cli/check.md) da los contadores, `diff` da las listas de claves.

### Claves de origen sin uso [#claves-de-origen-sin-uso]

<AvailableFrom version="0.11.0" />

`--unused` responde otra pregunta que `orphaned`: ¿qué claves de tu archivo de locale de origen ya no nombra tu aplicación? Analiza las `roots` del [bloque `extract`](https://verbatra.kreitz-webdev.de/es/docs/config-file.md#extract) con el lector que usa [`verbatra extract`](https://verbatra.kreitz-webdev.de/es/docs/cli/extract.md) y lista cada clave de origen que ninguna referencia estática nombra. Las dos listas nunca se fusionan. El análisis solo lee: no se elimina nada y no se lee ninguna clave de API. Borrar una clave es decisión tuya.

El análisis modela el runtime de i18next. Esto cuenta como referencia:

- una llamada `t(...)`, `$t(...)` o `<object>.t(...)` en cualquier lugar bajo las raíces, también a través de un alias como `const { t: translate } = useTranslation()`, `const tr = i18n.t`, `t.bind(i18n)` o `i18n.getFixedT(...)`;
- un `keyPrefix` estático o un tercer argumento estático de `getFixedT`, que cubre también la forma con prefijo de cada clave estática de ese archivo, y un `i18nKey` estático en `Trans` o en un objeto;
- una clave con namespace (`common:nav.home` cubre también `nav.home`), una clave en lenguaje natural y cada entrada de un array estático de claves;
- una variante de plural o de contexto de una clave referenciada (`t("items", { count })` cubre `items_one` e `items_other`) y cada clave bajo un padre referenciado.

Las claves se comparan en la codificación propia del formato del catálogo, así que una clave JSON plana con puntos, un plural o una entrada `msgctxt` de gettext y una entrada `<plurals>` de Android coinciden con la clave que nombra tu código. Un template literal con cabeza estática, como `` t(`nav.${page}`) ``, lista las claves bajo `nav.` como `possiblyDynamic`, aparte de `unused`, y nunca hace fallar la ejecución.

El informe lleva un `status`: `complete` (se acotaron todas las claves alcanzables, así que `unused` es fiable), `unreliable` (una clave listada puede seguir en uso; `unreliableBecause` nombra cada motivo con su recuento y sus ubicaciones) o `not-run` (no se lista nada; `reason` dice por qué):

| Motivo | `status` | Cuándo |
| --- | --- | --- |
| `dynamic-keys` | `unreliable` | una clave sin parte estática: `t(key)`, un template literal sin cabeza estática o una concatenación |
| `dynamic-key-prefix` | `unreliable` | un prefijo de `keyPrefix` o `getFixedT` que no es un string estático |
| `trans-without-key` | `unreliable` | un elemento `Trans` sin `i18nKey` estático |
| `aliased-translate-function` | `unreliable` | `t` asignada a algo que no es una variable simple, como `this.tr = t` |
| `translate-function-escapes` | `unreliable` | una función de traducción usada fuera de una llamada directa, su propio binding, un alias local, `t={t}` en `Trans` o `Translation` o un array de dependencias de un hook: `renderRow(t)`, `{ t }`, `return t`, `export default t` |
| `unrecognised-translate-source` | `unreliable` | un `t` o `$t` de una fuente que el análisis no modela, como un hook envoltorio que devuelve `useTranslation(...)`, opciones del hook con spread o un resultado de `getFixedT` exportado |
| `template-files-not-scanned` | `unreliable` | archivos `.vue`, `.svelte`, `.html`, `.htm`, `.astro`, `.hbs`, `.handlebars`, `.ejs`, `.pug`, `.njk`, `.liquid` o `.mdx` bajo las raíces (se listan los 20 primeros y se cuentan todos) |
| `incomplete-scan` | `unreliable` | un archivo demasiado grande, ilegible o que no se puede leer hasta el final (también un elemento JSX sin cerrar o un string que llega al final de su línea), o un directorio que no se puede listar |
| `EXTRACT_NOT_CONFIGURED` | `not-run` | no hay bloque `extract` |
| `EXTRACT_FS_UNSUPPORTED` | `not-run` | el sistema de archivos de quien llama al SDK no puede listar directorios |
| `FRAMEWORK_NOT_MODELED` | `not-run` | el formato es `next-intl-json`, `vue-i18n-json` o `ngx-translate-json`, cuyos runtimes el análisis no modela |
| `NO_SOURCE_FILES` | `not-run` | no hay ningún archivo de código bajo las raíces |
| `NO_REFERENCES_FOUND` | `not-run` | los archivos analizados no nombran ninguna clave ni tienen sitios de clave dinámica aunque el catálogo no esté vacío; normalmente significa que las raíces no cubren tu código |

Las fuentes de funciones de traducción reconocidas son: `useTranslation(...)` desestructurado en un binding local, no exportado, con argumentos estáticos; un `i18n.getFixedT(...)` local con argumentos estáticos; una llamada directa a un miembro `t` (`i18n.t("key")`, `this.props.t("key")`) y su alias local; `<Translation>{(t) => ...}</Translation>`; `withTranslation("ns")(Component)` con `props.t(...)`; e `import { t } from "i18next"`. Se evalúa cualquier variable o miembro llamado `t` o `$t`, así que un `frame.t + 1` ajeno puede volver el informe poco fiable. En archivos `.tsx`, `.jsx` y `.js`, el texto JSX y los valores de atributo entre comillas se leen como marcado, nunca como código.

Cada clave listada muestra su forma decodificada (una entrada `msgctxt` de gettext como `menu|Open`); `--json` lleva además la `catalogKey` tal como la escribe el adaptador. Una clave usada solo fuera del código analizado (una plantilla de servidor, un CMS) va en [`extract.unused.ignore`](https://verbatra.kreitz-webdev.de/es/docs/config-file.md#extract): un patrón coincide con la clave decodificada, y una clave que coincide se lista bajo `ignored`, nunca desaparece sin aviso.

### Claves protegidas [#claves-protegidas]

<AvailableFrom version="0.12.0" />

Las claves faltantes y cambiadas que `translate` dejaría para una persona (una persona escribió, importó o cambió el valor fuera de verbatra, o la clave coincide con `pinnedKeys`) se listan además bajo `protected`; consulta [Proteger traducciones humanas](https://verbatra.kreitz-webdev.de/es/docs/protecting-human-translations.md). Siguen en `add` y `re-translate`, porque siguen pendientes. Si `verbatra.provenance.json` está dañado o es de un verbatra más nuevo, solo se listan las claves fijadas.

### Salida JSON [#salida-json]

Esquema: [`diff-envelope.json`](https://verbatra.kreitz-webdev.de/schema/v1/diff-envelope.json) valida el envoltorio completo; [Esquemas](https://verbatra.kreitz-webdev.de/es/docs/cli/output.md#esquemas) enumera los demás.

`--json` imprime un [envoltorio](https://verbatra.kreitz-webdev.de/es/docs/cli/output.md#salida-json) cuyo `result` es un `DiffSummary`. `hasPendingChanges` es verdadero exactamente cuando el comando sale con `1` por claves pendientes:

```ts
interface DiffSummary {
  hasPendingChanges: boolean;
  locales: LocaleDiff[];
  unused?: UnusedKeysReport;   // solo con --unused
}

interface LocaleDiff {
  locale: string;
  missing: string[];           // se añadiría
  changed: string[];           // se retraduciría
  orphaned: string[];          // solo se informa
  emptySource?: string[];      // valor de origen vacío: nunca pendiente
  hasPendingChanges: boolean;  // missing.length > 0 || changed.length > 0
  changedOrigins?: Record<string, KeyOrigin>; // ausente si el archivo de procedencia no se puede leer
  protected?: string[];        // claves pendientes que translate deja como están
}
```

### Información en el terminal [#información-en-el-terminal]

<AvailableFrom version="0.12.0" />

`diff` muestra una línea mientras trabaja (con un recuento de archivos en curso cuando `--unused` analiza el código) y sugiere el siguiente comando:

```text output
verbatra: diffing and scanning the source... done (0.8s)
next: verbatra translate (send the pending keys to your provider)
```

Si todas las claves pendientes están protegidas, sugiere `verbatra studio`; con `provider: { id: "none" }`, sugiere `verbatra export`. Estas líneas van a stderr, y `--quiet` las omite. Consulta [Salida en el terminal](https://verbatra.kreitz-webdev.de/es/docs/cli/output.md#salida-en-el-terminal).

## Códigos de salida [#códigos-de-salida]

| Código | Significado |
| --- | --- |
| `0` | ningún locale tiene una clave que añadir o retraducir, y ningún análisis completo con `--unused` encontró una clave sin uso |
| `1` | al menos un locale tiene una clave faltante o cambiada, o un análisis `complete` con `--unused` encontró una clave sin uso |
| `2` | no se pudo ejecutar: un error de toda la ejecución, un valor `--locales` no configurado (`UNKNOWN_LOCALE`) o un error de uso, como una lista `--locales` vacía (`INVALID_LOCALES`) |

Las claves huérfanas, posiblemente dinámicas e ignoradas, y un informe `unreliable` o `not-run`, nunca producen `1` por sí solos. Consulta [el contrato de códigos de salida](https://verbatra.kreitz-webdev.de/es/docs/cli/output.md#códigos-de-salida).

## Relacionado [#relacionado]

- [`verbatra check`](https://verbatra.kreitz-webdev.de/es/docs/cli/check.md) da los contadores por locale detrás de estas listas.
- [`verbatra translate`](https://verbatra.kreitz-webdev.de/es/docs/cli/translate.md) aplica los cambios pendientes; `--prune` elimina las claves huérfanas.
- [El archivo de configuración](https://verbatra.kreitz-webdev.de/es/docs/config-file.md#extract) documenta el bloque `extract` y `unused.ignore`.
- [CI y códigos de salida](https://verbatra.kreitz-webdev.de/es/docs/ci-and-exit-codes.md) muestra `diff` en una canalización.
