Saltar al contenido
Saltar al contenido

Referencia / Configuración

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.

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

verbatra.config.ts
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.

ClaveTipoPor defectoDesdeEfecto
$schemastringninguno0.9.0Apunta un editor al JSON Schema; se ignora en tiempo de ejecución.
sourceLocalecódigo de localeobligatoria0.1.0El locale en el que están escritas tus cadenas de origen.
targetLocalesarray de códigos de localeobligatoria0.1.0Al menos uno; nunca sourceLocale, nunca dos iguales sin distinguir mayúsculas.
formatid de formatoobligatoria0.1.0El formato de tus archivos de locale, o un id custom: para un adaptador externo.
files.patternstringobligatoria0.1.0La ruta de cada archivo de locale, con un token {locale}.
files.localeStyle"literal", "posix", "android""literal"0.7.0Cómo se escribe {locale} en la ruta.
provider.idid de proveedorobligatoria0.1.0El proveedor de traducción, o none para no usar traducción automática.
provider.optionsobjetoobligatoria, salvo con none0.1.0Las opciones propias del proveedor.
glossaryobjeto o ruta de archivoninguno0.1.0Traducciones fijas, traducciones prohibidas y términos que no se traducen.
tone"formal", "informal", "neutral"ninguno0.1.0El registro en el que traducir, aplicado por proveedor.
prunebooleanfalse0.3.0Elimina las claves huérfanas de los archivos de destino y del bloqueo; translate --prune tiene prioridad.
generatePluralsbooleanfalse0.3.0Sintetiza las formas plurales CLDR que necesita un idioma de destino.
fuzzyCache.enabledbooleanobligatoria en el bloque0.11.0Reutiliza la traducción de un origen poco cambiado.
fuzzyCache.thresholdnúmero, de 0.5 a 10.90.11.0Cuánto deben parecerse origen antiguo y nuevo.
humanEdits"protect", "suggest", "overwrite""protect"0.12.0Qué hace una ejecución con una clave obsoleta que escribió una persona.
pinnedKeysarray de stringsninguno0.12.0Patrones de claves (* como comodín) que ninguna escritura automática toca.
network.policy"any", "local-only", "allowlist""any"0.12.0A qué hosts puede conectarse un proveedor.
network.allowedHostsarray de stringsninguno; obligatoria con "allowlist"0.12.0Hosts permitidos adicionales: nombres, comodines *.suffix, IPs o rangos CIDR.
sensitiveData.mode"off", "warn", "block", "redact"obligatorio en el bloque; "off" sin el bloque0.12.0Qué hace una ejecución con el contenido sensible antes de enviarlo.
sensitiveData.detectorsarray de IDs de detectorsecret, email, iban, credit-card0.12.0Detectores activos; phone, ip, private-host son opcionales.
sensitiveData.patternsarray de stringsninguno0.12.0Expresiones regulares para tus propios términos, como nombres en clave.
sensitiveData.allowarray de stringsninguno0.12.0Coincidencias que nunca se informan; * es un comodín y no distingue mayúsculas.
maxBatchSizeentero positivo500.3.0El máximo de entradas por petición al proveedor.
maxLengthmapa de clave a entero positivoninguno0.11.0Presupuestos de longitud por clave, en clústeres de grafemas.
maxTokensentero positivoninguno0.5.0Un presupuesto de tokens para toda la ejecución.
budgetBehavior"warn", "stop""warn"0.5.0Si alcanzar maxTokens avisa o detiene el envío.
rates.asOffecha YYYY-MM-DDobligatoria en el bloque0.11.0La fecha en que leíste las tarifas.
rates.currencytres letras mayúsculasobligatoria en el bloque0.11.0La moneda de todas las tarifas, como USD.
rates.tablemapa de clave de tarifa a tarifaobligatoria en el bloque0.11.0Tarifas por clave de tarifa.
extract.framework"i18next"obligatoria en el bloque0.11.0Qué llamadas busca el análisis del código fuente.
extract.rootsarray de stringsobligatoria en el bloque0.11.0Los directorios que se analizan, al menos uno.
extract.excludearray de stringsninguno0.11.0Nombres de directorio extra que se omiten.
extract.literals.ignorearray de stringsninguno0.11.0Textos exactos que doctor --literals retiene.
extract.unused.ignorearray de stringsninguno0.11.0Claves o patrones * que diff --unused nunca señala.

Locales y archivos

  • files.pattern debe contener {locale}, su único token, y se resuelve contra la raíz del proyecto: locales/{locale}.json pasa a locales/de.json. Es una ruta literal, nunca un glob, así que una configuración direcciona un archivo por locale (Diseños con namespaces); apple-xcstrings resuelve todos los locales al mismo catálogo (Xcode String Catalogs).

  • files.localeStyle decide en qué se expande el token:

    • literal escribe la etiqueta tal como está configurada, como necesitan la mayoría de diseños.
    • posix reemplaza - por _ para gettext y el diseño Java messages_{locale}.properties (pt-BR pasa a pt_BR); una variante como de-1996 no tiene escritura posix. gettext-po escribe los scripts a la manera de gettext (siguiente sección).
    • android se expande a un directorio de recursos, escrito como res/{locale}/strings.xml: values para el origen, y luego values-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_REGION@modifier) mientras la configuración conserva códigos BCP 47:

Código en la configuraciónNombre de archivo
pt-BRpt_BR
es-419es_419
sr-Latnsr@latin
sr-Latn-RSsr_RS@latin
uz-Cyrluz@cyrillic
ks-Deva-INks_IN@devanagari
zh-Hant-TWzh_TW
sr-Cyrl-RSsr_RS

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_PATH_COLLISION; un script sin modificador de gettext, como zh-Hant solo, falla con LOCALE_LAYOUT_INVALID. verbatra init lee estos nombres de vuelta. Los demás formatos mantienen la escritura de ICU (sr_Latn).

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_INVALID: pt_BR (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_INVALID.

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:

verbatra.config.ts
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_INVALID, nombrando la ruta y, en la versión 2, el campo. Pon un término __proto__ 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:

glossary.json
{
  "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 }]
}
CampoSignificado
versionSiempre 2; cualquier otro número falla.
terms[].sourceEl término de origen; cada término aparece una vez.
terms[].targetLa traducción para cada locale que no tenga entrada propia en targets.
terms[].targetsTraducciones 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[].forbiddenTraducciones que un locale nunca debe usar; un locale regional también se rige por la lista de su idioma base.
terms[].caseSensitiveComparar el término, las traducciones y las traducciones prohibidas distinguiendo mayúsculas. Por defecto false.
terms[].note, terms[].partOfSpeechContexto en texto libre, que un proveedor LLM recibe como datos.
doNotTranslateTé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>_ordinal_<category>) 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_CACHE_REUSE (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.

verbatra.config.ts
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:

verbatra.config.ts
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. setKeyLengthLimit solo 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 y setKeyLengthLimit lo 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 translate produce para la clave, reutilizaciones de caché incluidas; una clave al día solo se mide cuando cambia su origen, o con export --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ía maxTokens. 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 (el budget del 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 maxTokens por debajo de la proyección de un lote lo rechaza en cada ejecución; el aviso indica que bajes maxBatchSize o subas maxTokens.
  • Un locale con claves retenidas es partial, o failed si no llegó ninguna clave, y ambos salen con 1. 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.

verbatra.config.ts
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.

verbatra.config.ts
extract: {
  framework: "i18next",
  roots: ["src", "app"],
  exclude: ["generated"],
  literals: { ignore: ["Acme Inc."] },
  unused: { ignore: ["emails.*"] },
}
  • framework debe nombrar uno con extractor (formas de llamada); cualquier otro se rechaza.
  • roots se resuelven contra la raíz del proyecto; exclude añade nombres de directorio (no rutas), que coinciden en cualquier punto bajo una raíz, al conjunto que siempre se omite.
  • literals.ignore coincide con el texto completo de un literal, con espacios reducidos y referencias decodificadas (Literales sin traducir).
  • unused.ignore se 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:

  1. package.json (una propiedad "verbatra")
  2. .verbatrarc
  3. .verbatrarc.json
  4. .verbatrarc.yaml
  5. .verbatrarc.yml
  6. .verbatrarc.js
  7. .verbatrarc.cjs
  8. .verbatrarc.ts
  9. verbatra.config.js
  10. verbatra.config.cjs
  11. verbatra.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.json

Sin conexión, o para fijar la versión instalada, usa la copia del paquete, ./node_modules/@verbatra/sdk/dist/config-schema.json (todos los esquemas).

.verbatrarc.json y .verbatrarc llevan una clave $schema para VS Code:

.verbatrarc.json
{
  "$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:

.vscode/settings.json
{
  "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:

.verbatrarc.yaml
# 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: 4096

package.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_NOT_FOUND: no hay configuración en ningún sitio buscado, o la ruta de --config no existe.
  • CONFIG_INVALID: 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.

La CLI sale con 2 en ambos casos.

Editar en GitHub

En esta página