Referencia / Configuración
Página traducida automáticamente
Archivo de configuración
Cada clave de configuración con su tipo, su valor por defecto y la versión que la añadió, más dónde puede vivir el archivo y cómo falla una configuración mala.
verbatra lee un único objeto de configuración sin secretos y lo valida antes de cualquier trabajo. Ninguna clave de API se lee jamás de él (Proveedores), así que la configuración se puede confirmar sin riesgo.
Una configuración mínima
import { defineConfig } from "@verbatra/cli";
export default defineConfig({
// Locales and files: required
sourceLocale: "en",
targetLocales: ["de", "fr"],
format: "i18next-json",
files: {
// {locale} is the only token
pattern: "locales/{locale}.json",
},
// Provider: required; the API key comes from the environment, never from here
provider: {
id: "gemini",
options: {
// example model id; use your provider's current one
model: "gemini-2.5-flash",
maxOutputTokens: 4096,
},
},
// Optional groups, each off or at its default until you add it:
// tone: "informal",
// glossary: "glossary.json",
// network: { policy: "local-only" },
// sensitiveData: { mode: "warn" },
// maxTokens: 200000,
// budgetBehavior: "stop",
});Mira locales y archivos, provider, glossary, network, contenido sensible, presupuesto, rates y extract.
defineConfig solo da tipos a su argumento: options.model autocompleta con los IDs de modelo del proveedor, aunque en tiempo de ejecución vale cualquier cadena no vacía.
Cada clave
Las claves desconocidas se rechazan en todos los niveles salvo $schema y los mapas cuyas claves nombras tú, como maxLength, rates.table, localeMap y un glossary en línea, así que una clave de API no puede vivir en la configuración.
| Clave | Tipo | Por defecto | Desde | Efecto |
|---|---|---|---|---|
$schema | string | ninguno | 0.9.0 | Apunta un editor al JSON Schema; se ignora en tiempo de ejecución. |
sourceLocale | código de locale | obligatoria | 0.1.0 | El locale en el que están escritas tus cadenas de origen. |
targetLocales | array de códigos de locale | obligatoria | 0.1.0 | Al menos uno; nunca sourceLocale, nunca dos iguales sin distinguir mayúsculas. |
format | id de formato | obligatoria | 0.1.0 | El formato de tus archivos de locale, o un id custom: para un adaptador externo. |
files.pattern | string | obligatoria | 0.1.0 | La ruta de cada archivo de locale, con un token {locale}. |
files.localeStyle | "literal", "posix", "android" | "literal" | 0.7.0 | Cómo se escribe {locale} en la ruta. |
provider.id | id de proveedor | obligatoria | 0.1.0 | El proveedor de traducción, o none para no usar traducción automática. |
provider.options | objeto | obligatoria, salvo con none | 0.1.0 | Las opciones propias del proveedor. |
glossary | objeto o ruta de archivo | ninguno | 0.1.0 | Traducciones fijas, traducciones prohibidas y términos que no se traducen. |
tone | "formal", "informal", "neutral" | ninguno | 0.1.0 | El registro en el que traducir, aplicado por proveedor. |
prune | boolean | false | 0.3.0 | Elimina las claves huérfanas de los archivos de destino y del bloqueo; translate --prune tiene prioridad. |
generatePlurals | boolean | false | 0.3.0 | Sintetiza las formas plurales CLDR que necesita un idioma de destino. |
fuzzyCache.enabled | boolean | obligatoria en el bloque | 0.11.0 | Reutiliza la traducción de un origen poco cambiado. |
fuzzyCache.threshold | número, de 0.5 a 1 | 0.9 | 0.11.0 | Cuánto deben parecerse origen antiguo y nuevo. |
humanEdits | "protect", "suggest", "overwrite" | "protect" | 0.12.0 | Qué hace una ejecución con una clave obsoleta que escribió una persona. |
pinnedKeys | array de strings | ninguno | 0.12.0 | Patrones de claves (* como comodín) que ninguna escritura automática toca. |
network.policy | "any", "local-only", "allowlist" | "any" | 0.12.0 | A qué hosts puede conectarse un proveedor. |
network.allowedHosts | array de strings | ninguno; obligatoria con "allowlist" | 0.12.0 | Hosts permitidos adicionales: nombres, comodines *.suffix, IPs o rangos CIDR. |
sensitiveData.mode | "off", "warn", "block", "redact" | obligatorio en el bloque; "off" sin el bloque | 0.12.0 | Qué hace una ejecución con el contenido sensible antes de enviarlo. |
sensitiveData.detectors | array de IDs de detector | secret, email, iban, credit-card | 0.12.0 | Detectores activos; phone, ip, private-host son opcionales. |
sensitiveData.patterns | array de strings | ninguno | 0.12.0 | Expresiones regulares para tus propios términos, como nombres en clave. |
sensitiveData.allow | array de strings | ninguno | 0.12.0 | Coincidencias que nunca se informan; * es un comodín y no distingue mayúsculas. |
maxBatchSize | entero positivo | 50 | 0.3.0 | El máximo de entradas por petición al proveedor. |
maxLength | mapa de clave a entero positivo | ninguno | 0.11.0 | Presupuestos de longitud por clave, en clústeres de grafemas. |
maxTokens | entero positivo | ninguno | 0.5.0 | Un presupuesto de tokens para toda la ejecución. |
budgetBehavior | "warn", "stop" | "warn" | 0.5.0 | Si alcanzar maxTokens avisa o detiene el envío. |
rates.asOf | fecha YYYY-MM-DD | obligatoria en el bloque | 0.11.0 | La fecha en que leíste las tarifas. |
rates.currency | tres letras mayúsculas | obligatoria en el bloque | 0.11.0 | La moneda de todas las tarifas, como USD. |
rates.table | mapa de clave de tarifa a tarifa | obligatoria en el bloque | 0.11.0 | Tarifas por clave de tarifa. |
extract.framework | "i18next" | obligatoria en el bloque | 0.11.0 | Qué llamadas busca el análisis del código fuente. |
extract.roots | array de strings | obligatoria en el bloque | 0.11.0 | Los directorios que se analizan, al menos uno. |
extract.exclude | array de strings | ninguno | 0.11.0 | Nombres de directorio extra que se omiten. |
extract.literals.ignore | array de strings | ninguno | 0.11.0 | Textos exactos que doctor --literals retiene. |
extract.unused.ignore | array de strings | ninguno | 0.11.0 | Claves o patrones * que diff --unused nunca señala. |
Locales y archivos
-
files.patterndebe contener{locale}, su único token, y se resuelve contra la raíz del proyecto:locales/{locale}.jsonpasa alocales/de.json. Es una ruta literal, nunca un glob, así que una configuración direcciona un archivo por locale (Diseños con namespaces);apple-xcstringsresuelve todos los locales al mismo catálogo (Xcode String Catalogs). -
files.localeStyledecide en qué se expande el token:literalescribe la etiqueta tal como está configurada, como necesitan la mayoría de diseños.posixreemplaza-por_para gettext y el diseño Javamessages_({locale}.properties pt-BRpasa apt_); una variante comoBR de-1996no tiene escritura posix.gettext-poescribe los scripts a la manera de gettext (siguiente sección).androidse expande a un directorio de recursos, escrito comores/{locale}/strings.xml:valuespara el origen, y luegovalues-de,values-pt-rBR,values-b+zh+Hans.
Un estilo rechaza un locale que no puede escribir.
Nombres de locale de gettext
Con format: "gettext-po" y localeStyle: "posix", los archivos llevan nombres de gettext (language_) mientras la configuración conserva códigos BCP 47:
| Código en la configuración | Nombre de archivo |
|---|---|
pt-BR | pt_ |
es-419 | es_ |
sr-Latn | sr@latin |
sr-Latn-RS | sr_ |
uz-Cyrl | uz@cyrillic |
ks-Deva-IN | ks_ |
zh-Hant-TW | zh_ |
sr-Cyrl-RS | sr_ |
Un script que el idioma y la región ya implican se omite, así que zh-TW y zh-Hant-TW juntos fallan con LOCALE_; un script sin modificador de gettext, como zh-Hant solo, falla con LOCALE_. verbatra init lee estos nombres de vuelta. Los demás formatos mantienen la escritura de ICU (sr_).
Códigos de locale
Cada código de locale debe ser una etiqueta que Intl.getCanonicalLocales acepte, con una subetiqueta de idioma de dos o tres letras, o la carga falla con CONFIG_: pt_ (escribe pt-BR con localeStyle: "posix") y german se rechazan. Un código válido no canónico, como zh-hant-tw o el obsoleto iw, funciona tal como está escrito.
provider
provider.id selecciona uno de los proveedores o none, cuyo options puede omitirse y, si se indica, debe ser {} (Trabajar sin traducción automática). Los demás proveedores aceptan options.localeMap y options.requestTimeoutMs (Proveedores); desde 0.12.0 una clave mal colocada bajo provider, como localeMap, falla con CONFIG_.
glossary
Términos que se traducen de una forma fija, en línea o como ruta a un archivo JSON con la misma forma (nunca fusionadas). La versión 1 asigna a cada término de origen una traducción para todos los locales:
export default defineConfig({
// ...
glossary: {
"Sign in": "Anmelden",
},
// or: glossary: "glossary.json",
});Una ruta relativa se resuelve contra el directorio del archivo de configuración; el archivo debe estar en UTF-8 y no superar 1 MiB, y se lee una vez al cargar. Un archivo ausente, JSON inválido o una forma inválida fallan con CONFIG_, nombrando la ruta y, en la versión 2, el campo. Pon un término _ en un archivo; un literal de JavaScript lo convierte en el prototipo.
Glosario por locale (versión 2)
La versión 2 añade traducciones por locale, traducciones prohibidas y términos que se quedan tal como están escritos:
{
"version": 2,
"terms": [
{
"source": "Dashboard",
"targets": { "de": "Übersicht", "fr": "Tableau de bord" },
"forbidden": { "de": ["Instrumententafel"] },
"note": "The start page after sign-in",
"partOfSpeech": "noun"
},
{ "source": "Sign in", "target": "Anmelden", "caseSensitive": true }
],
"doNotTranslate": ["verbatra", { "term": "Acme", "caseSensitive": false }]
}| Campo | Significado |
|---|---|
version | Siempre 2; cualquier otro número falla. |
terms[].source | El término de origen; cada término aparece una vez. |
terms[].target | La traducción para cada locale que no tenga entrada propia en targets. |
terms[].targets | Traducciones por locale. Un locale usa su propia entrada, luego la de su idioma base (de cubre de-AT) y luego target, comparando códigos canónicos sin distinguir mayúsculas. |
terms[].forbidden | Traducciones que un locale nunca debe usar; un locale regional también se rige por la lista de su idioma base. |
terms[].caseSensitive | Comparar el término, las traducciones y las traducciones prohibidas distinguiendo mayúsculas. Por defecto false. |
terms[].note, terms[].partOfSpeech | Contexto en texto libre, que un proveedor LLM recibe como datos. |
doNotTranslate | Términos que se copian sin traducir. Un string simple conserva sus mayúsculas; { "term", "caseSensitive": false } puede cambiarlas. |
Cada término necesita un target, una entrada en targets o una lista forbidden; no puede prohibir su propia traducción, nombrar un locale dos veces ni aparecer en doNotTranslate. Ningún texto puede estar en blanco; un término admite como máximo 200 caracteres, una traducción o una forma prohibida 2000, una note 500 y una partOfSpeech 50. La huella de caché de un locale solo cubre sus propios términos. Un archivo de la versión 1 conserva su huella; updateGlossaryTerm lo reescribe como versión 2 solo para una edición que la versión 1 no puede expresar.
Studio solo edita la forma de archivo, término a término. Qué proveedores aplican el glosario está en Proveedores; cada salida se comprueba después.
generatePlurals
Cuando es true, verbatra sintetiza las formas plurales CLDR que un destino necesita y el origen no tiene, como few y many en polaco, y las claves ordinales (<key>_) según las reglas ordinales CLDR. Solo lo admite i18next-json con un proveedor LLM; todo lo demás, y un locale sin reglas CLDR, recibe el aviso de plurales (los ordinales suponen other). No hay opción de CLI; translate() del SDK acepta un override por ejecución.
fuzzyCache
fuzzyCache: { enabled: true } permite que un origen cambiado reutilice la traducción de su forma anterior cuando ambas se parecen al menos threshold, siempre marcada como FUZZY_ (Reutilización difusa); --no-cache lo omite.
humanEdits y pinnedKeys
humanEdits cubre una clave obsoleta cuyo valor escribió una persona (procedencia human, import o external); una clave que coincide con pinnedKeys (como ["legal.*", "brand.name"]) nunca se escribe de forma automática, diga lo que diga humanEdits. * coincide con cualquier secuencia de caracteres, puntos incluidos, y la comparación distingue mayúsculas. Qué hace cada modo está en Conserva las traducciones humanas.
network
Consulta Restringe el acceso a la red.
network: { policy: "local-only", allowedHosts: ["gpu.lan"] }maxBatchSize
Las entradas faltantes y modificadas se envían en sublotes secuenciales que no superan este tamaño. Ninguna opción de CLI lo sobrescribe.
maxLength
Límites de longitud por clave, para cadenas sujetas a una restricción de maquetación:
maxLength: {
"nav.dashboard": 18,
"cta.submit": 12,
}- Aquí o en
verbatra.limits.json. nuevo Las claves se comparan literalmente, nunca como globs; una clave que no fija ninguno de los dos nunca se mide.setKeyLengthLimitsolo admite claves del origen, así que Studio no puede fijar un límite a una forma plural generada; una entrada escrita a mano para su propia clave sí se aplica. El archivo versionado junto al archivo de bloqueo admite{ "version": 1, "maxLength": { ... } }, la configuración gana por clave ysetKeyLengthLimitlo escribe. - Clústeres de grafemas. La longitud cuenta caracteres percibidos, espacios incluidos: un emoji, una letra acentuada o un carácter CJK cuentan como uno. El límite es inclusivo.
- Cuándo. Cada valor que
translateproduce para la clave, reutilizaciones de caché incluidas; una clave al día solo se mide cuando cambia su origen, o conexport --include-unchanged. - Informativo. Un exceso se sigue escribiendo y bloqueando, y se marca para revisión como
MAX_.LENGTH_ EXCEEDED
maxTokens y budgetBehavior
maxTokens es un presupuesto para toda la ejecución: tokens de entrada más de salida en cada llamada al proveedor (traducción y generación de plurales) y en cada locale de destino. translate --max-tokens puede endurecerlo para una ejecución, nunca relajarlo, y siempre como un "stop" estricto.
budgetBehavior decide qué pasa entonces:
"warn", el valor por defecto, cuenta el gasto y señala el exceso, pero continúa."stop"lo convierte en un techo para todos los proveedores. Antes de cada petición, la ejecución proyecta su coste como la estimación previa y rechaza una que superaríamaxTokens. Las claves de esa petición y cada clave aún no intentada (el resto del locale y cada locale posterior, cuyo diff e informe de huérfanas siguen ejecutándose) se retienen, conservan su hash anterior en el bloqueo y se reintentan en la siguiente ejecución.
Con "stop":
- Después de cada petición el total se reconcilia con el uso que informó el proveedor, así que una ejecución puede terminar algo por encima de
maxTokens(elbudgetdel resumen de ejecución). Los proveedores de traducción automática no informan de tokens y se presupuestan a partir de la proyección. - Una petición fallida o truncada se carga por completo.
- La proyección suma una asignación fija para el prompt del LLM, también para los proveedores de traducción automática, y abarca un lote entero, así que un
maxTokenspor debajo de la proyección de un lote lo rechaza en cada ejecución; el aviso indica que bajesmaxBatchSizeo subasmaxTokens. - Un locale con claves retenidas es
partial, ofailedsi no llegó ninguna clave, y ambos salen con1. Con"warn"el código de salida nunca cambia.
El presupuesto acota una ejecución de translate, nunca la retraducción de una sola entrada; watch arranca uno nuevo por ejecución. Un presupuesto excluye --concurrency por encima de 1 en una ejecución real; un dry run queda exento. budgetBehavior sin maxTokens no tiene efecto.
Dos maxTokens distintos
El maxTokens de nivel superior es este presupuesto de toda la ejecución; el provider.options.maxTokens de Anthropic, sin relación con él, limita una respuesta (Proveedores).
rates
Solo lo lee translate --estimate, que convierte las tarifas en dinero; una ejecución real lo ignora.
rates: {
asOf: "2026-01-15",
currency: "USD",
table: {
// placeholders: copy the current rates from each provider's pricing page
"gemini/gemini-2.5-flash": { inputPerMillionTokens: 1, outputPerMillionTokens: 2 },
deepl: { perMillionCharacters: 1 },
},
}Una clave de table es provider/model, o el id a secas para un proveedor sin modelo (deepl, google-translate). Una entrada se factura por tokens (inputPerMillionTokens, outputPerMillionTokens) o por caracteres (perMillionCharacters), nunca ambas cosas, y se rechaza una tarifa negativa, una tarifa por encima de 1.000.000.000 por millón o la unidad equivocada. openai-compatible y libretranslate no emiten factura, así que su cantidad se informa sin tarifa.
extract
Solo lo leen extract, doctor --literals y diff --unused.
extract: {
framework: "i18next",
roots: ["src", "app"],
exclude: ["generated"],
literals: { ignore: ["Acme Inc."] },
unused: { ignore: ["emails.*"] },
}frameworkdebe nombrar uno con extractor (formas de llamada); cualquier otro se rechaza.rootsse resuelven contra la raíz del proyecto;excludeañade nombres de directorio (no rutas), que coinciden en cualquier punto bajo una raíz, al conjunto que siempre se omite.literals.ignorecoincide con el texto completo de un literal, con espacios reducidos y referencias decodificadas (Literales sin traducir).unused.ignorese compara con la clave decodificada (diff --unused).
Orden de descubrimiento
verbatra busca hacia arriba desde el directorio de trabajo y toma la primera coincidencia, deteniéndose en el directorio más cercano que contenga .git, si no en tu directorio personal (o en el de trabajo cuando el personal no está por encima), así que nunca recoge una configuración por encima de tu repositorio:
package.json(una propiedad"verbatra").verbatrarc.verbatrarc.json.verbatrarc.yaml.verbatrarc.yml.verbatrarc.js.verbatrarc.cjs.verbatrarc.tsverbatra.config.jsverbatra.config.cjsverbatra.config.ts
--config <path> carga un solo archivo en su lugar, relativo al directorio de trabajo; la prioridad en el SDK está en loadConfig.
Validación en el editor
@verbatra/sdk publica un JSON Schema generado a partir de su esquema zod, servido también en una URL estable para cualquier instalación, npx, un monorepo con hoisting o un agente remoto:
https://verbatra.kreitz-webdev.de/schema/v1/config.jsonSin conexión, o para fijar la versión instalada, usa la copia del paquete, ./node_ (todos los esquemas).
.verbatrarc.json y .verbatrarc llevan una clave $schema para VS Code:
{
"$schema": "https://verbatra.kreitz-webdev.de/schema/v1/config.json",
"sourceLocale": "en",
"targetLocales": ["de", "fr"],
"format": "i18next-json",
"files": { "pattern": "locales/{locale}.json" },
"provider": { "id": "gemini", "options": { "model": "gemini-2.5-flash", "maxOutputTokens": 4096 } }
}El .verbatrarc sin extensión necesita además una asociación de archivos del espacio de trabajo:
{
"json.schemas": [
{
"fileMatch": [".verbatrarc", ".verbatrarc.json"],
"url": "https://verbatra.kreitz-webdev.de/schema/v1/config.json"
}
]
}Una configuración YAML lleva un comentario del YAML Language Server:
# yaml-language-server: $schema=https://verbatra.kreitz-webdev.de/schema/v1/config.json
sourceLocale: en
targetLocales: [de, fr]
format: i18next-json
files:
pattern: "locales/{locale}.json"
provider:
id: gemini
options:
model: gemini-2.5-flash
maxOutputTokens: 4096package.json no admite esquema; las formas ejecutables las tipa defineConfig.
Lo que el documento no puede comprobar
Solo la carga de la configuración comprueba estas reglas: las reglas de targetLocales y de los códigos de locale, las claves de localeMap y las reglas de baseUrl y apiKeyEnvVar de openai-compatible, direcciones y rangos válidos en network.allowedHosts, sensitiveData.patterns dentro de las reglas de seguridad de patrones y las reglas de términos de un glosario en línea de la versión 2.
El directorio de trabajo y .env
El directorio de trabajo (donde ejecutas verbatra, o --cwd) inicia la búsqueda de configuración y contiene los archivos de entorno. Las rutas de locale, verbatra.lock.json, la caché, el archivo de procedencia y .verbatra-local/ se resuelven contra la raíz del proyecto, el directorio de la configuración encontrada, así que una ejecución desde un subdirectorio usa los mismos archivos. Con --config, el directorio de trabajo es la raíz, y una configuración en otro lugar recibe un aviso en stderr, porque la ruta de su glosario se resuelve contra su propio directorio. Una ruta que pasas tú, como --out o check --file, se resuelve contra el directorio de trabajo.
Cuando la carga falla
CONFIG_: no hay configuración en ningún sitio buscado, o la ruta deNOT_ FOUND --configno existe.CONFIG_: se encontró una configuración pero no se puede usar. El mensaje lista cada problema con la ruta de su clave; una clave desconocida añade la pista de que las claves de API vienen del entorno. Un fallo de parseo nombra el archivo (con línea y columna en YAML) pero nunca cita su contenido, y cada mensaje pasa por la redacción de claves.INVALID
La CLI sale con 2 en ambos casos.