Saltar al contenido
Saltar al contenido

Referencia / CLI

Página traducida automáticamente

Esta página se tradujo automáticamente, así que puede contener errores o sonar un poco rara. La versión en inglés es la fuente de la verdad. Leer el original en inglés.

verbatra doctor

Comprueba si un proyecto está bien configurado y recibe todos los problemas en un informe, sin llamar a un proveedor ni leer una clave de API.

Comprueba si un proyecto está bien configurado y recibe todos los problemas en un solo informe. doctor no construye ningún proveedor, no escribe ningún archivo y solo lee el valor de una clave de API con --live, que la envía en una petición de la lista de idiomas del proveedor (LibreTranslate no recibe ninguna). Úsalo después de verbatra init o cuando otro comando falle.

Sinopsis

verbatra doctor [flags]

Ejemplos

# report every setup problem at once
verbatra doctor

# validate a project in another directory, with an explicit config
verbatra doctor --cwd apps/web --config verbatra.config.ts

# machine-readable report for a CI preflight step
verbatra doctor --json

# list hardcoded user-facing strings, with no key set
verbatra doctor --literals

# what the provider supports for each target locale
verbatra doctor --locales

# the same, against the provider's current language list
verbatra doctor --live

# a data-flow manifest to attach to a DPA or NDA review
verbatra doctor --data-flow --json

Flags

FlagArgumentoPor defectoEfecto
--literalsningunodesactivadoen lugar de revisar la configuración, busca strings visibles para el usuario escritos a mano en las raíces de código del bloque extract (ver Literales sin traducir)
--localesningunodesactivadotras las comprobaciones, lista por locale de destino el código enviado, el soporte del proveedor, el glosario y la formalidad (ver Soporte de locales)
--liveningunodesactivadoprimero descarga la lista de idiomas actual del proveedor, sin gastar cuota de traducción; implica --locales
--data-flowningunodesactivadoen lugar de revisar la configuración, describe qué se envía a qué host y qué se escribe en local (ver Flujo de datos)

También acepta los flags globales --cwd, --config y --json. --locales y --live no se pueden combinar con --literals (INVALID_OPTION, salida 2), y --data-flow con ninguno de los tres.

Comportamiento

Qué comprueba

Una ejecución de configuración informa de estas comprobaciones, en este orden. Plural rules, Plural completeness, Locale codes, Locale state y Length limits son informativas y nunca fallan: cada una muestra [warn] cuando nombra algo y [ok ] en caso contrario.

ComprobaciónFalla cuando
Configurationno se encuentra ningún archivo de configuración o no pasa la validación
Format adapterel format configurado no se resuelve a ningún adaptador de archivos
Providerel provider.id configurado no se resuelve a ninguna factoría de proveedor
API key environment variablela variable de la que ese proveedor lee su clave no está definida
Network policyla política de red efectiva rechaza el host del proveedor o un proxy que usaría
Source locale fileel archivo de locale de origen falta en su ruta resuelta, no es un archivo normal o no se analiza con el formato configurado
Plural rulesnunca; nombra las versiones de ICU y CLDR en uso y avisa cuando un locale de destino no tiene reglas de plural en ICU
Plural completenessnunca; avisa y nombra cada plural de destino al que le falta una categoría CLDR que usa su idioma, y juzga un plural sin formas en el destino por lo que una ejecución escribiría allí (una forma de origen vacía cuenta como ausente, y la generación de plurales solo donde de verdad se ejecuta), a propósito más estricto que el aviso de translate, solo para i18next (diez como máximo; verbatra check lista los huecos de los plurales que un destino ya tiene); se omite para un formato que no guarda las formas de plural por categoría CLDR
Locale codesnunca; avisa y nombra cada código válido pero no canónico, como en-us o iw, con su forma canónica (ver Códigos de locale)
Locale statenunca; avisa y nombra cada locale con estado en el archivo de bloqueo, la caché o el archivo de procedencia que la configuración no lista, y si translate lo traslada
Length limitsnunca; avisa cuando verbatra.limits.json no se puede usar (una ejecución lo ignora y no se puede fijar un límite hasta arreglarlo), nombra un límite de una clave que la fuente ya no tiene o uno que el maxLength de la configuración sobrescribe, y lo dice si no se pudo leer la fuente para comprobar las claves; pasa cuando el archivo no existe (límites de longitud) nuevo
Locale supportel proveedor no admite el locale de origen o un locale de destino; avisa cuando un locale lleva un aviso (ver Soporte de locales)

Cada comprobación se ejecuta aunque una anterior haya fallado. La única excepción es la configuración: si no se puede cargar, las comprobaciones que la necesitan aparecen como [skip] ("status": "skipped" en JSON), igual que Plural completeness para un formato sin formas de plural CLDR. Una comprobación que encuentra algo que merece atención sin fallar aparece como [warn] ("status": "warn" en JSON) y nunca cambia el código de salida. Una comprobación fallida lleva además un fix, un siguiente paso en imperativo que se imprime como línea fix: y viaja como "fix" en JSON, para que un agente actúe sin analizar detail.

Una ejecución con dos problemas:

Salida
verbatra doctor
  [ok  ] Configuration: Loaded /app/verbatra.config.ts.
  [ok  ] Format adapter: Format "i18next-json" resolves to an adapter.
  [ok  ] Provider: Provider "anthropic" resolves to a factory.
  [fail] API key environment variable: The ANTHROPIC_API_KEY environment variable is not set.
         fix: Set ANTHROPIC_API_KEY in the environment, or, with the CLI, in a .env file in the project directory.
  [ok  ] Network policy: any host (config: unset; VERBATRA_NETWORK_POLICY: unset). Provider "anthropic" connects to api.anthropic.com: permitted.
  [fail] Source locale file: The source locale file was not found at /app/locales/en.json.
         fix: Create the source locale file, or fix `files.pattern` and `sourceLocale` in the config so they point at it.
  ...
  [warn] Locale codes: "iw" is canonically "he". Consider the canonical form in your config; file names follow the configured code and are never renamed for you.
  [ok  ] Locale support: Provider "anthropic" is an LLM and accepts any locale (well-tested list of 2026-09-28).
2 problems found (run verbatra doctor again after fixing them)

Claves y archivos

  • La clave de API se comprueba solo por nombre: doctor pregunta si la variable está definida, nunca qué contiene. La variable de cada proveedor está en Proveedores.
  • openai-compatible recurre a una clave de relleno, así que solo falla cuando la configuración nombra su propia variable en provider.options.apiKeyEnvVar y esa variable no está definida. libretranslate nunca hace fallar la comprobación, porque su clave es opcional.
  • Con provider: { id: "none" }, las comprobaciones Provider, API key y Network policy pasan, y Locale support se omite.
  • Que falte un archivo de destino no es problema: translate lo crea. El archivo de origen se analiza, así que un directorio, un archivo vacío o un contenido mal formado la hacen fallar.
  • doctor carga primero los archivos de entorno, así que una clave en un archivo dotenv cuenta como definida; con --literals no carga ninguno.

Soporte de locales

La comprobación Locale support pregunta si el proveedor puede traducir cada locale configurado. DeepL y Google Cloud Translation se evalúan contra una tabla de idiomas fechada que verbatra incluye; un proveedor LLM acepta cualquier locale. Falla justo en el locale que verbatra translate rechazaría con LOCALE_UNSUPPORTED_BY_PROVIDER y, si no, muestra [warn] cuando un locale lleva un aviso o --live no pudo obtener la lista. Soporte de idiomas explica los veredictos.

--locales imprime el veredicto por locale después de las comprobaciones:

Salida
  locale support (deepl, language table of 2026-09-28, static)
    en  sent as EN  source, supported
    de  sent as DE  supported  glossary: yes  formality: yes
    sv  sent as SV  supported  glossary: yes  formality: no
      warning [FORMALITY_UNSUPPORTED_BY_PROVIDER] Provider "deepl" has no formality control for "sv", so the configured formal tone is not applied and the provider's default register is used.
    chr  sent as CHR  unsupported  glossary: no  formality: no

Cada línea nombra el locale, el código que recibe el proveedor (tras localeMap, marcado con (localeMap)), el veredicto y si se aplican un glosario y un tono formal o informal. Un aviso es solo orientativo.

--live evalúa en cambio contra la lista actual del proveedor (DeepL /v3/languages, Cloud Translation languages, LibreTranslate /languages). Para LibreTranslate, que no incluye tabla, es la única forma de obtener un veredicto distinto de unverified, así que Locale support muestra [warn] hasta que se ejecute --live. La petición solo se envía si la variable de la clave está definida (LibreTranslate no la necesita) y la política de red permite el host; si no, o si falla, se usa la tabla incluida y una línea live language list explica por qué.

Literales sin traducir

--literals encuentra strings visibles para el usuario que nunca llegaron a un catálogo. Recorre las raíces de código de tu bloque extract, lee tu código sin escribirlo nunca, no construye proveedor, no lee ninguna clave y no carga ningún .env. Solo se ejecutan dos comprobaciones: Configuration y Untranslated literals. Cada hallazgo nombra archivo, línea y columna, con los espacios colapsados, las referencias de caracteres de JSX decodificadas y 80 caracteres como máximo:

Salida
  [fail] Untranslated literals: Scanned 42 source files: 2 untranslated literals found (1 suppressed).
    src/components/Header.tsx:12:9  "Welcome back"
    src/pages/settings.tsx:40:22  "Save changes"
    suppressed (directive) src/pages/legal.tsx:8:5  "Acme Inc."

Se informa de: texto JSX en archivos .tsx, .jsx y .js, atributos JSX visibles para el usuario (alt, title, placeholder, label, aria-label y los demás aria-* con texto) y cualquier otro string de dos o más palabras.

Nunca se informa de:

  • un string pasado a t(...), $t(...), i18n.t(...) o a un t renombrado de useTranslation, o renderizado dentro de <Trans> o <Translation>;
  • claves de objeto, especificadores de import, nombres de clase, valores CSS, ids de test, data-* y atributos de id o palabra clave (aria-describedby, aria-labelledby, aria-controls, rel, sandbox, allow, autoComplete, referrerPolicy, crossOrigin), URLs y strings sin letras;
  • literales en posición de tipo (el valor antes de as o satisfies sí se comprueba), mensajes de log, mensajes de error (new ValidationError(...), throw Error(...)), operandos de comparación y template literals con una expresión;
  • argumentos directos de describe (zod), query, execute, prepare, format, parse, z.enum, setItem, getItem y removeItem, y el primer argumento de on, off, once, emit, addEventListener y de un get o set sobre un objeto; el texto más anidado y los mensajes pasados a funciones como setError sí se informan;
  • todo lo que esté en archivos de test, story, declaración o configuración.

Para retener un literal, pon // verbatra-ignore-next-line encima (en JSX, {/* verbatra-ignore-next-line */}) o // verbatra-ignore-line al final de su línea. Una directiva de siguiente línea apunta a la siguiente línea con código y, en una etiqueta JSX de apertura, a todos sus atributos. Un string que vale en todas partes lo añades a extract.literals.ignore con las referencias decodificadas (Tom & Jerry). Los literales suprimidos se siguen listando con su motivo.

La comprobación falla con un hallazgo y con un archivo que no pudo abrir, leer hasta el final o que consideró demasiado grande (el escaneo continúa). Un proyecto sin bloque extract la hace fallar.

Flujo de datos

--data-flow describe adónde van los datos de este proyecto en lugar de revisar la configuración, como evidencia para una revisión de DPA o NDA; Tratamiento de datos explica cada categoría. No lee ninguna clave de API ni hace ninguna petición de red. Solo se ejecutan dos comprobaciones: Configuration y Data flow. Data flow nunca falla: muestra [warn] cuando la política de red rechaza un host o tiene un valor no válido, o cuando no se puede leer el archivo de origen para los recuentos.

Salida
  [ok  ] Data flow: Provider "deepl" sends source-text, placeholder-markers, language-codes to api.deepl.com (permitted), api-free.deepl.com (permitted).
  data flow (manifest version 1)
    provider     deepl (machine-translation)
    network      any host (no policy set)
    destination  api.deepl.com  default  paid-key  before-construction  permitted
    destination  api-free.deepl.com  default  free-key  before-construction  permitted
    sent         source-text, placeholder-markers, language-codes
    api key      required
    placeholders masked
    sensitive    off
    counts       3 source keys, 0 with a description or meaning, 1 with placeholders it cannot mask (withheld)
    locale       de  sent as DE  glossary terms: 0
    local        lock  verbatra.lock.json  (no source text, translations or personal data)
    local        provenance  verbatra.provenance.json  (reviewer names)
    local        cache  verbatra.cache.json  (source text, translations, gitignored by init)
    local        local-state  .verbatra-local  (source text, host name and process ID of a run holding a write lock, gitignored by init)
    request      language-list  verbatra doctor --live  sends the API key
    request      dns-lookup  each connection to a destination host
    agent        mcp  verbatra mcp  redactable
    agent        studio-agent-tools  verbatra studio --expose-agent-tools

El manifiesto nombra el proveedor; cada host de destino, de dónde sale (integrado, provider.options.baseUrl o una variable *_BASE_URL) y el veredicto de la política (permitted, deferred, refused o invalid-policy); los tipos de datos enviados, con el número de claves de origen, de claves con descripción o significado y de claves cuyos placeholders el proveedor no puede enmascarar (una estimación sobre las claves de origen: una ejecución solo envía claves que faltan o cambiaron y puede retener más con sensitiveData: redact); el código y el número de términos del glosario por locale de destino; los archivos locales con sus rutas relativas al proyecto y si contienen texto de origen, traducciones o datos personales; y las demás peticiones y superficies de agentes. DeepL aparece con sus dos hosts, porque la clave que elige uno nunca se lee. Un proxy en uso aparece con su variable y su host, nunca con sus credenciales, y los campos solo nombran lo que esta config puede enviar. Con provider: { id: "none" } indica que no se envía nada. Nombra hosts, categorías de datos y condiciones, nunca el valor de una clave ni el contenido de un archivo.

Con --json el manifiesto está en result.dataFlow. Su campo version solo cambia cuando se renombra o elimina un campo; pueden aparecer campos nuevos sin cambiarla, así que ignora los que no conozcas. dataFlowManifestSchema del SDK lo valida.

Salida JSON

Esquema: doctor-envelope.json valida el envoltorio completo; Esquemas enumera los demás.

Con --json, el envoltorio lleva el informe en result. ok es verdadero exactamente cuando el comando termina con 0:

interface DoctorResult {
  ok: boolean;                 // true exactly when the command exits 0
  checks: DoctorCheck[];       // one per check, always in the same order
  literals?: LiteralScan;      // only with --literals: findings, suppressed, diagnostics
  dataFlow?: DataFlowManifest; // only with --data-flow: what goes where, version 1
  locales?: LocaleCapabilityReport; // per-locale provider support, with or without --locales
}

interface DoctorCheck {
  id:
    | "config"
    | "format-adapter"
    | "provider"
    | "api-key"
    | "network-policy"
    | "source-file"
    | "plural-rules"
    | "plural-completeness"
    | "locale-codes"
    | "locale-state"
    | "limits" // 0.13.0
    | "locales"
    | "untranslated-literals"
    | "data-flow";
  title: string;               // stable, human-readable name
  status: "pass" | "warn" | "fail" | "skipped";  // only "fail" makes ok false
  detail: string;              // why it reached that verdict; never an API key value
  fix?: string;                // the next step, only on a failed check
}

interface LocaleCapabilityReport {
  provider: string;
  coverage: "listed" | "open";       // "open" for an LLM provider
  tableVersion: string;              // the table's date (YYYY-MM-DD)
  tableOrigin: "static" | "live";    // "live" only when --live fetched the list
  live?: { status: "refreshed" | "skipped" | "failed"; detail: string }; // only with --live
  source: {
    locale: string;
    providerCode: string;
    mapped: boolean;
    support: "supported" | "unverified" | "unsupported";
    warnings: { code: string; message: string }[];
  };
  locales: {
    locale: string;
    providerCode: string;            // the code the provider receives
    mapped: boolean;                 // true when localeMap set providerCode
    support: "supported" | "unverified" | "unsupported";
    glossary: boolean;
    formality: boolean;
    warnings: { code: string; message: string }[];
  }[];
}

result.locales no aparece cuando no se pudo cargar la configuración, con un proveedor desconocido ni con provider: { id: "none" }.

Información en el terminal

Mientras se ejecuta, doctor muestra una línea en stderr, que --quiet omite: checking the setup, checking the setup and fetching the provider's language list con --live, describing the data flow con --data-flow o scanning the source for literals con un recuento de archivos con --literals. El informe se queda en stdout. Consulta Salida en el terminal.

Códigos de salida

CódigoSignificado
0ninguna comprobación falló (un warn también sale con 0)
1al menos una comprobación falló, incluido un locale no admitido; con --literals, se encontró un literal o no se pudo escanear un archivo
2no pudo ejecutarse: un error de uso o una ruta --config explícita que no existe

Una configuración que la búsqueda no encuentra, o que no pasa la validación, es una comprobación fallida (salida 1), porque informar de ello es justo la tarea del comando. Consulta el contrato de códigos de salida.

Relacionado

Editar en GitHub

En esta página