Referencia del SDK

Cada punto de entrada de @verbatra/sdk, agrupado por tarea, con el modelo de errores y la anatomía de RunSummary.

Página traducida automáticamente

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

@verbatra/sdk es el motor sobre el que corre el comando verbatra. La CLI es una envoltura fina, así que todo lo que hace la línea de comandos lo puedes hacer en código. Esta página cataloga toda la superficie pública, agrupada por la tarea que hace cada punto de entrada. Para ejemplos de principio a fin, consulta Recetas del SDK.

Instalación

npm install --save-dev @verbatra/sdk
# pnpm
pnpm add -D @verbatra/sdk
# yarn
yarn add -D @verbatra/sdk

Requiere Node.js >=22.14.0.

La línea de pnpm instala bien, pero sale con 1 y ERR_PNPM_IGNORED_BUILDS: pnpm bloquea los scripts de instalación del SDK de Gemini incluido y de su protobufjs, y deja un pnpm-workspace.yaml sin responder con el que cualquier comando pnpm posterior del proyecto falla igual. Ejecuta pnpm approve-builds una vez y no apruebes ninguna de las dos entradas, o consulta la Solución de problemas para la solución no interactiva. Aquí no hay atajo con npx como en la CLI, porque estás importando una biblioteca, no ejecutando un binario.

Las claves API y el entorno

El SDK nunca lee, guarda ni acepta una clave API. El proveedor lee su clave del entorno (por ejemplo ANTHROPIC_API_KEY) cuando se construye. A diferencia de la CLI, el SDK no carga archivos .env: en tu propio script, define tú la variable, por ejemplo con node --env-file=.env script.js.

Cada punto de entrada toma un objeto de entrada cuyo primer campo es la config validada (de loadConfig), salvo donde se indica. La mayoría también acepta un segundo argumento opcional deps que inyecta un registro, un constructor de proveedor o un sistema de archivos para pruebas; puedes ignorarlo en el uso normal.

Ejecuta traducciones

translate

El flujo de una sola pasada: leer el origen, comparar cada locale de destino con la línea base del bloqueo, enviar al proveedor las claves faltantes y modificadas, ejecutar las comprobaciones de integridad, escribir los archivos de locale y actualizar el bloqueo. Úsalo para scripts, pasos de build y jobs de CI.

Entrada: { config, cwd?, dryRun?, prune?, generatePlurals?, concurrency?, cache?, onProgress?, onLockWait?, lockAcquireTimeoutMs? }.

  • dryRun lee, compara e informa sin construir ni llamar al proveedor y sin escribir nada.
  • prune elimina del archivo escrito y del bloqueo las claves huérfanas (claves de destino ausentes del origen). generatePlurals sintetiza las formas de plural CLDR que faltan (solo i18next-JSON con un proveedor LLM). Ambos están desactivados por defecto; cuando se definen, cada uno anula la opción de configuración correspondiente para esa ejecución.
  • concurrency traduce hasta ese número de locales de destino a la vez (por defecto 1, estrictamente en serie). Un valor menor que 1 lanza CONCURRENCY_INVALID; en una ejecución real, un valor mayor que 1 con maxTokens configurado lanza CONCURRENCY_BUDGET_CONFLICT (un dry-run queda exento). Un error de toda la ejecución que se levanta cuando ya hay locales en marcha impide que se arranque ningún locale más, y los locales en vuelo terminan y liberan sus bloqueos de escritura antes de que translate rechace, así que el rechazo llega después del más lento en vez de al instante.
  • cache está activado por defecto y reutiliza la caché de memoria de traducción local (verbatra.cache.json, exportada también como CACHE_FILE_NAME); ponlo en false para omitir la caché en la ejecución (el --no-cache de la CLI).
  • onProgress se llama a medida que avanza la ejecución (por inicio y fin de cada locale, y por sub-lote del proveedor), y onLockWait se dispara mientras el bloqueo de escritura de un locale está en disputa. Ambos son callbacks de notificación; el SDK no escribe nada por sí mismo. lockAcquireTimeoutMs anula cuánto tiempo reintenta un bloqueo de escritura en disputa antes de fallar con LOCK_CONTENDED.
  • maxBatchSize, maxTokens y budgetBehavior son solo de configuración; no hay anulación por ejecución.

Devuelve un RunSummary (consulta su anatomía más abajo). Los problemas de toda la ejecución lanzan un SdkError; que falle un solo locale nunca lanza y queda como status: "failed" en la entrada de ese locale mientras la ejecución continúa.

watch

Vigila el archivo del locale de origen y vuelve a ejecutar translate en cada cambio asentado por el anti-rebote. Dispara una ejecución inicial inmediatamente al arrancar, y luego una ejecución por cambio asentado. Las ejecuciones se serializan: los cambios durante una ejecución se colapsan en un único seguimiento.

Entrada: { config, cwd?, debounceMs?, onRun, concurrency?, cache?, onProgress?, onLockWait?, lockAcquireTimeoutMs? }. debounceMs es 300 por defecto. onRun se llama una vez por ejecución con un WatchRunResult: { status: "succeeded", summary } o { status: "failed", error: { code, message } }. El SDK no registra nada; onRun es la única salida. concurrency, cache, onProgress, onLockWait y lockAcquireTimeoutMs se pasan a cada ejecución y se comportan igual que en translate.

Devuelve un WatchController con un solo método, stop(), que cierra el watcher y espera la ejecución en curso. Tres problemas se rechazan al arrancar, antes de que el watcher exista, así que watch mismo rechaza en lugar de devolver un controlador: un concurrency que no es un entero de al menos 1 lanza CONCURRENCY_INVALID, un concurrency mayor que 1 contra una configuración que fija maxTokens lanza CONCURRENCY_BUDGET_CONFLICT (no hay watch en seco, así que el conflicto de presupuesto siempre aplica), y un archivo de origen ausente lanza SOURCE_UNREADABLE. Todo fallo posterior al arranque se comunica a través de onRun y la vigilancia continúa.

Inspecciona el estado sin escribir

Ninguna de estas llama a un proveedor, escribe un archivo ni muta el bloqueo.

check

Informa del desfase por locale como contadores: missing (en el origen, ausente del destino), stale (el origen cambió desde la última traducción) y upToDate. Úsalo como puerta de CI.

Entrada: { config, cwd?, locales? }. Devuelve un CheckSummary cuyo inSync es true exactamente cuando cada locale comprobado no tiene nada faltante ni obsoleto.

diff

El hermano detallado de check: el mismo cálculo, pero devuelve las listas de claves por locale (missing, changed, orphaned) en lugar de contadores. Las claves huérfanas son solo informativas y nunca activan hasPendingChanges, porque una ejecución por defecto no elimina claves.

Entrada: { config, cwd?, locales? }. Devuelve un DiffSummary.

keyIntegrity

Informa, para las claves modificadas de cada locale, de si el valor de destino actual sigue coincidiendo con los marcadores de posición del origen y de si es ICU válido. Cada entrada lleva key, hasPlaceholders, matches, los tokens de marcador missing y extra en una discrepancia, e icuValid. Las entradas nunca llevan un valor de cadena de origen o destino. Este es el informe de integridad por clave que muestra Studio.

Entrada: { config, cwd?, locales?, keys? }. keys acota la comprobación; solo se comprueban las claves que están "modificadas" para un locale. Devuelve un LocaleKeyIntegrity por locale comprobado.

lockState

Informa de la existencia del archivo de bloqueo, su versión y el desfase por locale (número de claves de la línea base más contadores de faltantes, obsoletas y al día). exists viene de una sonda explícita, así que "todavía no hay archivo de bloqueo" y "un archivo de bloqueo vacío pero presente" siguen siendo distinguibles. Cuando el archivo está ausente el resultado es { exists: false } y no se lee nada más.

Entrada: { config, cwd?, locales? }. Devuelve un LockStateResult.

loadLockFile

Lee el propio archivo de bloqueo (verbatra.lock.json, exportado también como LOCK_FILE_NAME) y devuelve su forma parseada: { version, locales }, donde cada locale asigna claves al hash del contenido de origen desde el que se tradujeron por última vez. Un archivo ausente degrada a un bloqueo vacío, el mismo comportamiento de primera ejecución en el que se apoya translate; usa lockState cuando necesites distinguir la ausencia.

Entrada: { cwd? }. No necesita configuración. Devuelve un LockFile.

runStatus

Lee la instantánea de señales de revisión y uso de tokens que la ejecución más reciente de translate o watch (no en seco) persistió en .verbatra-local/run-status.json. Nunca lanza: un archivo ausente, corrupto o no reconocido degrada a { available: false }. Este archivo es telemetría de mejor esfuerzo, no una línea base de corrección.

Entrada: { cwd? }. No necesita configuración. Devuelve { available: false } o { available: true, version, generatedAt, usage?, budget?, locales }.

Operaciones de una sola clave

Estos son los puntos de integración que usa Verbatra Studio; úsalos para construir tu propia herramienta de revisión. Los tres resuelven locale y key de nuevo en cada llamada y lanzan UNKNOWN_LOCALE o UNKNOWN_KEY cuando alguno no existe.

keyValue

Lee el valor de origen actual de una clave y, cuando existe, su valor de destino actual para un locale. Solo lectura.

Entrada: { config, cwd?, locale, key }. Devuelve { source, target? }; target está ausente exactamente cuando la clave todavía no existe en ese locale.

editEntry

Escribe una corrección tecleada por un humano para una clave y un locale. El valor candidato pasa por la misma puerta de integridad que una traducción del proveedor antes de que nada llegue al disco; al aceptarse, el archivo de locale y la entrada del bloqueo de esa clave se actualizan dentro del bloqueo de escritura del locale. Nunca llama a un proveedor.

Entrada: { config, cwd?, locale, key, value }. Devuelve un resultado de dos ramas: { accepted: true, value }, o { accepted: false, reason: "placeholder" | "icu" | "degenerate" | "empty", value } sin escribir nada. "empty" cubre un valor vacío o solo con espacios para un origen que sí tiene texto: una edición no puede expresar el vaciado de una clave, así que usa para eso el centinela [[CLEAR]] del libro.

retranslateEntry

Vuelve a ejecutar el proveedor para exactamente una clave y un locale: una llamada de una sola entrada a través de la misma ruta de proveedor que usa translate, protegida por las mismas comprobaciones de integridad. Al aceptarse escribe el archivo de locale y la entrada del bloqueo solo para esa clave.

Entrada: { config, cwd?, locale, key }. Devuelve { accepted: true, value, reviewReasons } (los códigos de motivo de revisión, si los hay, que aplican al nuevo valor) o { accepted: false, reason: "placeholder" | "icu" | "degenerate" | "empty", value }. A diferencia de translate, aquí un fallo del proveedor lanza: un ProviderError de @verbatra/ai-providers con un código estable como RATE_LIMITED o AUTH_FAILED.

Instantáneas de archivos de locale

Los bloques con los que se construye un vigilante de actualización en vivo como el de Studio: captura el estado de un archivo de locale y luego cuenta qué cambió desde entonces.

readLocaleFileSnapshot

Lee un archivo de locale (el locale de origen o cualquier locale de destino) y lo reduce a un hash de contenido por clave. Un archivo que todavía no existe se lee como una instantánea vacía en lugar de lanzar.

Entrada: { config, locale, cwd? }. Devuelve { locale, hashes }.

diffLocaleSnapshots

Compara dos instantáneas del mismo archivo, tomadas en momentos distintos, y cuenta las claves añadidas, modificadas y eliminadas entre ambas. Una función síncrona normal: diffLocaleSnapshots(previous, current) devuelve { added, changed, removed }. Solo contadores, nunca nombres de claves.

Rutas de locale

createLocalePathResolver

Resuelve la correspondencia entre locales y rutas del proyecto en ambos sentidos, a partir de files.pattern, los locales configurados y files.localeStyle. createLocalePathResolver(cwd, config) devuelve { pathFor, localeFor }: pathFor(locale) es la ruta absoluta del archivo de un locale, y localeFor(path) es el locale al que pertenece una ruta, o undefined para una ruta que este proyecto no posee. Todos los puntos de entrada del SDK resuelven rutas a través de él, así que un watcher o un panel construido sobre el SDK ve exactamente las rutas que escribe una ejecución.

Todas las comprobaciones se ejecutan al crear el resolver, antes de leer ningún archivo: un patrón y un estilo que no se pueden combinar, o un locale para el que el estilo no tiene una escritura correcta, lanzan LOCALE_LAYOUT_INVALID, y dos locales que resuelven a la misma ruta lanzan LOCALE_PATH_COLLISION.

El par de libro

La entrega para traductores humanos, como libro de Excel o como texto delimitado; consulta Traducción humana.

exportWorkbook

Escribe las cadenas que todavía necesitan traducción (claves faltantes y modificadas por locale; añade las sin cambios con includeUnchanged) en un libro .xlsx con estilos. Las filas llevan la misma señal de revisión que calcula una ejecución de translate. Sin llamada al proveedor, sin escritura del bloqueo.

Entrada: { config, cwd?, out?, locales?, includeUnchanged?, format? }. format es xlsx por defecto; csv y tsv escriben en su lugar un <locale>.csv o <locale>.tsv por locale, así que out nombra un directorio para ellos (creado si falta) y una ruta de archivo para xlsx. out es por defecto DEFAULT_WORKBOOK_PATH (verbatra-translations.xlsx) o DEFAULT_DELIMITED_PATH (verbatra-translations), ambos exportados como constantes. Los valores aceptados se exportan como EXCHANGE_FORMATS y el valor por defecto como DEFAULT_EXCHANGE_FORMAT, para que una herramienta que envuelve el SDK pueda validar un argumento de formato sin fijar la lista en el código. Devuelve { path, locales }: la ruta absoluta escrita y un número de filas por locale.

importWorkbook

Lee un libro rellenado de vuelta a los archivos de locale, ejecutando las mismas comprobaciones de desfase del origen e integridad que translate. Solo las filas aceptadas avanzan su línea base del bloqueo; una fila en blanco o rechazada se sigue exportando hasta que se resuelve de verdad.

Entrada: { config, workbook, cwd?, dryRun?, format? }. Con csv o tsv, workbook es un solo archivo de entrega o el directorio que contiene uno por locale, y la locale viene del nombre del archivo. Devuelve la misma forma RunSummary que translate (con needsReview siempre vacío, ya que no interviene ningún proveedor). Una hoja de un locale que no es un destino configurado hace fallar ese locale con CONFIG_INVALID como dato en el resumen, no como excepción.

Configuración

loadConfig

Encuentra, carga y valida la configuración del proyecto, devolviendo una VerbatraConfig. Opciones: { cwd?, configPath?, configOverride? }, con precedencia de configOverride (validar un objeto en memoria) sobre configPath (cargar un archivo explícito) sobre la búsqueda. La búsqueda empieza en cwd y cubre verbatra.config.ts (también .js/.cjs), la familia .verbatrarc (.json, .yaml, .yml, .js, .cjs, .ts) y una propiedad "verbatra" en package.json. Un glossary dado como ruta de archivo se lee y valida aquí, así que el código posterior siempre ve un registro plano.

Lanza CONFIG_NOT_FOUND cuando no se encuentra nada, CONFIG_INVALID cuando se encuentra una configuración pero es inválida. Consulta Archivo de configuración para el esquema.

loadConfigWithMeta

La misma carga, más la procedencia: devuelve { config, source, glossary }, donde source dice si la configuración vino de un acierto de búsqueda, de una ruta explícita o de una anulación en memoria (con el filepath absoluto cuando lo hay), y glossary registra si el glosario estaba ausente, en línea o resuelto desde un archivo. Úsalo cuando necesites mostrar de dónde salió la configuración.

defineConfig

Un ayudante identidad para escribir un verbatra.config.ts tipado: devuelve su argumento sin cambios y existe puramente para la inferencia de tipos y el autocompletado del editor, incluido el completado de los IDs de modelo conocidos del proveedor seleccionado. La restricción de modelos es solo al escribir; en tiempo de ejecución cualquier cadena no vacía pasa la validación.

verbatraConfigSchema

El esquema zod con el que valida loadConfig, exportado para que tu propia herramienta pueda validar un objeto de configuración igual que lo hace el SDK. Las claves desconocidas de nivel superior se rechazan, así que un secreto extraviado no puede esconderse en la configuración.

scaffoldingMetadata

Metadatos de solo lectura de los que el comando init de la CLI deriva sus preguntas: providerEnv (de id de proveedor a la variable de entorno de la que se lee su clave), scaffoldModels (un modelo de scaffold por defecto por proveedor LLM) y supportedFormats (el conjunto cerrado de ids de formato). El tipo ScaffoldableProviderId cubre los cuatro proveedores alojados; openai-compatible queda excluido porque no tiene una única variable de entorno obligatoria.

La anatomía de RunSummary

translate, importWorkbook y cada ejecución exitosa de watch resuelven a un RunSummary:

interface RunSummary {
  dryRun: boolean;          // true when nothing was written and no provider was called
  locales: LocaleSummary[]; // one entry per target locale, in config order
  succeeded: string[];      // locales whose run succeeded
  partial: string[];        // locales written with keys still missing; the CLI exits 1 on these
  failed: string[];         // locales whose run failed
  usage?: UsageSummary;     // summed input/output tokens; absent when no call reported usage
  budget?: RunBudget;       // present only when maxTokens is configured
}

interface LocaleSummary {
  locale: string;
  status: "succeeded" | "partial" | "failed";
  translated: string[];          // keys translated this run (in dry-run, keys that would be)
  cacheHits: string[];           // keys served from the translation-memory cache this run
  unchanged: string[];           // keys already up to date
  orphaned: string[];            // target keys with no matching source key (always reported)
  pruned: string[];              // orphaned keys removed this run; empty unless pruning is on
  invalidIcuSource: string[];    // source keys skipped for invalid ICU
  integrityMismatches: string[]; // translations withheld for a placeholder mismatch
  providerFailures: string[];    // keys withheld because nothing was translated for them
  budgetWithheld: string[];      // keys never sent because a "stop" budget already tripped
  generated: string[];           // CLDR plural forms synthesized this run
  unfilled: string[];            // import only: blank rows whose key still needs a translation
  malformedRows: { row: number; line?: number; column: string }[]; // import only: rows the reader could not parse
  duplicateKeys: { key: string; row: number; line?: number }[];    // import only: later rows for a duplicated key
  notices: LocaleNotice[];       // provider notices and SDK notices for this locale
  needsReview: { key: string; reasons: string[] }[]; // accepted keys flagged for a second look
  usage?: UsageSummary;          // this locale's summed tokens; absent if nothing reported usage
  error?: { code: string; message: string }; // present only when status is "failed"
}

Las partes que conviene conocer:

  • needsReview lista claves aceptadas y escritas que las heurísticas de revisión marcaron, cada una con sus códigos de motivo: LENGTH_RATIO_OUTLIER, EQUALS_SOURCE, GLOSSARY_TERM_MISSED, INTEGRITY_REORDERED y PROVIDER_DEGRADED. Una señal de revisión es consultiva y nunca retiene una clave, así que una clave nunca aparece a la vez en needsReview y en integrityMismatches. Consulta Seguridad de la traducción para saber qué significa cada código y Revisión en Studio para trabajar la cola.
  • notices vive por locale, nunca en el nivel superior. Cubre avisos del proveedor (por ejemplo, una degradación de DeepL) y avisos del SDK con los códigos PLURAL_CATEGORIES_INCOMPLETE, SUB_BATCH_FAILED, BLANK_ROW_BASELINE_RETAINED, BUDGET_TOKENS_EXCEEDED y CACHE_VERSION_UNRECOGNIZED. El aviso de caché es de toda la ejecución (un solo archivo, compartido por cada locale), así que se adjunta a cada locale de la ejecución.
  • usage es undefined, nunca un cero inventado, siempre que nada en ese ámbito informara de uso: una ejecución en seco nunca llama a un proveedor, y DeepL nunca informa de tokens. RunSummary.usage es la suma sobre los locales.
  • budget aparece solo cuando maxTokens está configurado: { maxTokens, behavior, supported, tokensUsed, exceeded }. Frente a un proveedor sin tokens o una ejecución en seco sigue presente con supported: false, así que la barrera es visiblemente inerte en lugar de dispararse en falso.
  • error.code en un locale fallido es una cadena preservada (el código subyacente del proveedor o del adaptador, con LOCALE_FAILED solo como reserva), así que no lo trates como un conjunto cerrado.
  • cacheHits lista las claves servidas desde la caché de memoria de traducción en lugar del proveedor. unfilled, malformedRows y duplicateKeys solo los rellena importWorkbook (una ejecución de translate los deja vacíos): una fila en blanco cuya clave todavía necesita traducción en el momento de la importación (tanto si se exportó como new como si se exportó como changed), una fila del libro que el lector no pudo parsear y una clave duplicada cuya primera aparición ganó. El line opcional de las dos últimas es la línea del archivo en la que empieza el registro, y solo está presente en una importación delimitada (csv o tsv).

El modelo de errores

Los fallos de toda la ejecución lanzan un SdkError: una sola clase, un code estable y un message sin secretos. Ramifica sobre el código, no sobre el mensaje. Los fallos por locale, los avisos del proveedor y los hallazgos de integridad se comunican como datos en el RunSummary, nunca se lanzan.

CódigoCuándo
CONFIG_NOT_FOUNDla búsqueda no encontró ninguna configuración, o un configPath explícito no existe (lanzado por loadConfig)
CONFIG_INVALIDse encontró una configuración pero no se puede parsear o falla la validación, o su archivo de glosario no se pudo resolver
UNKNOWN_FORMATno hay adaptador registrado para el formato configurado; se lanza antes de leer ningún archivo
UNKNOWN_LOCALEun locale solicitado no está entre los locales de destino configurados
UNKNOWN_KEYuna clave solicitada no está en el recurso de origen (keyValue, editEntry, retranslateEntry)
PROVIDER_CONSTRUCTION_FAILEDel proveedor no se pudo construir; envuelve el error propio del proveedor, incluida una clave API ausente
SOURCE_UNREADABLEel archivo del locale de origen no existe
SOURCE_INVALIDel archivo del locale de origen no se pudo leer o parsear; envuelve el error de lectura del adaptador
LOCK_FILE_INVALIDel archivo de bloqueo está presente pero corrupto, sobredimensionado o en una versión no admitida
LOCK_CONTENDEDel bloqueo de escritura de un locale no se pudo adquirir antes de su tiempo límite; el mensaje nombra la ruta del archivo de bloqueo
LOCALE_LAYOUT_INVALIDfiles.pattern y files.localeStyle no se pueden combinar, o el estilo no tiene una escritura de ruta válida para un locale configurado
LOCALE_PATH_COLLISIONdos locales configurados resuelven al mismo archivo absoluto
CONCURRENCY_INVALIDse definió concurrency pero no es un entero de al menos 1; se lanza antes de que corra ningún locale
CONCURRENCY_BUDGET_CONFLICTuna ejecución real fijó concurrency por encima de 1 con maxTokens configurado; se lanza antes de cualquier llamada al proveedor (un dry-run queda exento)
TARGET_UNWRITABLEun archivo de locale de destino no se pudo escribir (su directorio no es escribible, no existe, es de solo lectura o se quedó sin espacio); el mensaje nombra el archivo de destino y el código del sistema de archivos, nunca el archivo temporal interno que usa la escritura atómica
LOCALE_FAILEDnunca se lanza: el code de reserva registrado en el error de un locale fallido

Dos excepciones a la regla de una sola clase de error: retranslateEntry relanza el ProviderError propio del proveedor cuando la llamada única falla, y runStatus no lanza nunca. Para cómo estos códigos se corresponden con los códigos de salida de la CLI, consulta CI y códigos de salida; para ayuda a partir del síntoma, consulta Solución de problemas.

Edit on GitHub