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
@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/sdkRequiere 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? }.
dryRunlee, compara e informa sin construir ni llamar al proveedor y sin escribir nada.pruneelimina del archivo escrito y del bloqueo las claves huérfanas (claves de destino ausentes del origen).generatePluralssintetiza 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.concurrencytraduce hasta ese número de locales de destino a la vez (por defecto 1, estrictamente en serie). Un valor menor que 1 lanzaCONCURRENCY_INVALID; en una ejecución real, un valor mayor que 1 conmaxTokensconfigurado lanzaCONCURRENCY_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 quetranslaterechace, así que el rechazo llega después del más lento en vez de al instante.cacheestá activado por defecto y reutiliza la caché de memoria de traducción local (verbatra.cache.json, exportada también comoCACHE_FILE_NAME); ponlo en false para omitir la caché en la ejecución (el--no-cachede la CLI).onProgressse llama a medida que avanza la ejecución (por inicio y fin de cada locale, y por sub-lote del proveedor), yonLockWaitse 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.lockAcquireTimeoutMsanula cuánto tiempo reintenta un bloqueo de escritura en disputa antes de fallar conLOCK_CONTENDED.maxBatchSize,maxTokensybudgetBehaviorson 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_REORDEREDyPROVIDER_DEGRADED. Una señal de revisión es consultiva y nunca retiene una clave, así que una clave nunca aparece a la vez enneedsReviewy enintegrityMismatches. 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_EXCEEDEDyCACHE_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.usagees la suma sobre los locales. - budget aparece solo cuando
maxTokensestá configurado:{ maxTokens, behavior, supported, tokensUsed, exceeded }. Frente a un proveedor sin tokens o una ejecución en seco sigue presente consupported: 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_FAILEDsolo 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 detranslatelos 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ó comonewcomo si se exportó comochanged), una fila del libro que el lector no pudo parsear y una clave duplicada cuya primera aparición ganó. Ellineopcional 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 (csvotsv).
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ódigo | Cuándo |
|---|---|
CONFIG_NOT_FOUND | la búsqueda no encontró ninguna configuración, o un configPath explícito no existe (lanzado por loadConfig) |
CONFIG_INVALID | se encontró una configuración pero no se puede parsear o falla la validación, o su archivo de glosario no se pudo resolver |
UNKNOWN_FORMAT | no hay adaptador registrado para el formato configurado; se lanza antes de leer ningún archivo |
UNKNOWN_LOCALE | un locale solicitado no está entre los locales de destino configurados |
UNKNOWN_KEY | una clave solicitada no está en el recurso de origen (keyValue, editEntry, retranslateEntry) |
PROVIDER_CONSTRUCTION_FAILED | el proveedor no se pudo construir; envuelve el error propio del proveedor, incluida una clave API ausente |
SOURCE_UNREADABLE | el archivo del locale de origen no existe |
SOURCE_INVALID | el archivo del locale de origen no se pudo leer o parsear; envuelve el error de lectura del adaptador |
LOCK_FILE_INVALID | el archivo de bloqueo está presente pero corrupto, sobredimensionado o en una versión no admitida |
LOCK_CONTENDED | el 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_INVALID | files.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_COLLISION | dos locales configurados resuelven al mismo archivo absoluto |
CONCURRENCY_INVALID | se definió concurrency pero no es un entero de al menos 1; se lanza antes de que corra ningún locale |
CONCURRENCY_BUDGET_CONFLICT | una 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_UNWRITABLE | un 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_FAILED | nunca 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.