---
title: "Proveedores"
description: "Todos los proveedores de IA y de traducción automática que admite verbatra, con sus opciones y la variable de su clave de API, más el comportamiento común."
type: "reference"
---
# Proveedores

Todos los proveedores de IA y de traducción automática que admite verbatra, con sus opciones y la variable de su clave de API, más el comportamiento común.

Selecciona un proveedor por `id` en el bloque `provider` de tu [configuración](https://verbatra.kreitz-webdev.de/es/docs/config-file.md). Anthropic, OpenAI, Gemini, OpenCode y openai-compatible son modelos de lenguaje; DeepL, Google Cloud Translation y LibreTranslate son servicios de traducción automática; `none` desactiva la traducción automática. La cobertura de idiomas está en [Idiomas y locales](https://verbatra.kreitz-webdev.de/es/docs/language-support.md), y qué recibe cada proveedor en [Tratamiento de datos y privacidad](https://verbatra.kreitz-webdev.de/es/docs/data-handling.md).

## ¿Cuál elijo? [#cuál-elijo]

Cualquier proveedor funciona con cualquier formato y comando, y cambiar más tarde significa editar un solo `id`.

| Si quieres | Usa |
| --- | --- |
| Gratis, para un proyecto pequeño con cadenas no confidenciales | **Gemini**: un nivel de API gratuito, cuyas peticiones Google puede hacer que revisen personas fuera del EEE, Suiza y el Reino Unido ([condiciones](https://verbatra.kreitz-webdev.de/es/docs/data-handling.md#retención-y-tratamiento-de-datos-del-proveedor)). |
| La mejor calidad para una app de producción | **Anthropic** u **OpenAI**, ambos de pago. |
| Alto volumen, un glosario nativo, sin LLM | **DeepL**, nivel gratuito o de pago. |
| La cobertura más amplia con una clave de API en Google Cloud | **Google Cloud Translation** (Basic, v2). |
| Sin conexión, sin coste, sin que nada salga de tu red | **openai-compatible** con LM Studio, Ollama o vLLM. |
| Sin modelo de lenguaje, pero autoalojado | **LibreTranslate** en tu propio servidor. |
| Nada de traducción automática | **none**: solo memoria y personas. |

## Las claves vienen del entorno [#las-claves-vienen-del-entorno]

verbatra nunca lee una clave de la configuración. Cada proveedor alojado lee una variable:

| Id de proveedor | Variable de entorno |
| --- | --- |
| `anthropic` | `ANTHROPIC_API_KEY` |
| `openai` | `OPENAI_API_KEY` |
| `gemini` | `GEMINI_API_KEY` |
| `deepl` | `DEEPL_API_KEY` |
| `google-translate` | `GOOGLE_TRANSLATE_API_KEY` |
| `opencode` | `OPENCODE_API_KEY` |

Defínela en `.env` (que `verbatra init` añade a `.gitignore`), en tu shell o en el almacén de secretos de tu CI, y nunca la confirmes. Una variable no definida o vacía falla con [`MISSING_API_KEY`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#missing_api_key), nombrando la variable pero nunca un valor. `openai-compatible` y `libretranslate` normalmente no necesitan clave.

## Anthropic [#anthropic]

```ts title="verbatra.config.ts"
provider: {
  id: "anthropic",
  options: {
    model: "claude-sonnet-4-6", // example model id
    maxTokens: 4096,
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `model` | string | obligatoria | El id del modelo. |
| `maxTokens` | entero positivo | obligatoria | Limita los tokens de salida de una respuesta ([límites](#límites-de-tokens-de-salida)); sin relación con el presupuesto de nivel superior. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota cada intento de petición ([Tiempo de espera de petición](#tiempo-de-espera-de-petición)). |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale ([Códigos de locale](#códigos-de-locale-enviados-al-proveedor)). |

Lee `ANTHROPIC_API_KEY`.

## OpenAI [#openai]

```ts title="verbatra.config.ts"
provider: {
  id: "openai",
  options: {
    model: "gpt-5.4-mini", // example model id
    maxOutputTokens: 4096,
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `model` | string | obligatoria | El id del modelo. |
| `maxOutputTokens` | entero positivo | obligatoria | Limita los tokens de salida de una respuesta. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota cada intento de petición. |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Lee `OPENAI_API_KEY`.

## Gemini [#gemini]

```ts title="verbatra.config.ts"
provider: {
  id: "gemini",
  options: {
    model: "gemini-2.5-flash", // example model id
    maxOutputTokens: 4096,
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `model` | string | obligatoria | El id del modelo. |
| `maxOutputTokens` | entero positivo | obligatoria | Limita los tokens de salida de una respuesta. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota cada intento de petición. |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Lee `GEMINI_API_KEY`.

<Callout title="El nivel gratuito y sus límites">
Una clave de [Google AI Studio](https://aistudio.google.com/apikey) no necesita facturación, pero sus topes por minuto y por día pueden frenar una primera ejecución sobre muchos locales: traduce un locale cada vez o baja `maxBatchSize`, y vuelve a ejecutar para recoger el resto.
</Callout>

## DeepL [#deepl]

```ts title="verbatra.config.ts"
provider: {
  id: "deepl",
  options: {
    glossaryId: "<your-glossary-id>",
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `glossaryId` | string | ninguno | Un glosario que creaste en DeepL, aplicado de forma nativa. |
| `requestTimeoutMs` | entero positivo | `120000` | La espera mínima por intento, hasta seis intentos. |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Lee `DEEPL_API_KEY`; `options` puede ser `{}`. DeepL no tiene modelo ni límite de tokens de salida, y se degrada con un aviso en lugar de fallar:

- **Los placeholders** viajan como marcadores numerados en una etiqueta ignorada (`Hello {{name}}` como `Hello <x>{0}</x>`) y se restauran. `PLACEHOLDER_UNSUPPORTED` retiene un valor con un placeholder no literal o con `<`, `>`, `{` o `}` en el resto del texto, y un resultado con un marcador perdido, repetido, cambiado o sin etiqueta, una entidad desconocida o una etiqueta ajena. El marcado sin placeholders va como texto plano. <AvailableFrom version="0.12.0" />
- **El tono** se asigna a la formalidad (`formal` más, `informal` menos, `neutral` se omite). Una clave del nivel gratuito no envía ninguna formalidad e informa `FORMALITY_DOWNGRADED`. Una clave de pago la pide con `prefer_more` o `prefer_less`, así que un idioma sin formalidad, como el sueco, vuelve al registro predeterminado con el mismo aviso en lugar de fallar. El [glosario](#tono-y-glosario-entre-proveedores) no se aplica.

<AvailableFrom version="0.12.0" />

verbatra incluye la [tabla de idiomas](https://developers.deepl.com/docs/getting-started/supported-languages) fechada de DeepL y rechaza un idioma que no está en ella con `LOCALE_UNSUPPORTED_BY_PROVIDER` antes de gastar nada. Un `glossaryId` solo funciona cuando los dos idiomas están en la lista de glosarios de DeepL (como `DE`, `EN`, `FR`, `JA`, `ZH`).

## Google Cloud Translation [#google-cloud-translation]

<AvailableFrom version="0.10.0" />

```ts title="verbatra.config.ts"
provider: {
  id: "google-translate",
  options: {},
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `requestTimeoutMs` | entero positivo | `120000` | Acota la llamada completa (sin reintentos). |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Lee `GOOGLE_TRANSLATE_API_KEY`, una clave de API de un proyecto de Google Cloud con la Cloud Translation API activada. Solo funciona Basic (v2): Advanced (v3) necesita una cuenta de servicio.

- **Los placeholders** se enmascaran como en DeepL, dentro de `<span translate="no">`; los saltos de línea, tabuladores y dobles espacios también se retienen. <AvailableFrom version="0.12.0" />
- **Códigos.** Cada código enviado se comprueba como BCP 47 bien formado antes de cualquier llamada (`en_US` falla con `INVALID_REQUEST`). Se permiten códigos regionales; un par que Google rechaza falla con `INVALID_REQUEST` desde la API.

<AvailableFrom version="0.12.0" />

verbatra incluye la [tabla de idiomas](https://docs.cloud.google.com/translate/docs/languages) fechada de Google y rechaza un idioma que no está en ella antes de gastar nada. Un código regional cuyo idioma solo aparece en la lista como un todo, como `de-AT`, se envía tal como está escrito con un aviso.

## OpenCode [#opencode]

<AvailableFrom version="0.12.0" />

Aquí solo funcionan los modelos de [OpenCode Zen](https://opencode.ai/docs/zen/) que se sirven por `/chat/completions` (la tabla de modelos indica el endpoint de cada uno). OpenCode reserva Go y los modelos gratuitos de Zen para sus propios clientes.

```ts title="verbatra.config.ts"
provider: {
  id: "opencode",
  options: {
    model: "glm-5.3", // example: a Zen model served over Chat Completions
    maxOutputTokens: 4096,
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `model` | string | obligatorio | El id del modelo. |
| `maxOutputTokens` | entero positivo | obligatorio | Limita los tokens de salida de una respuesta. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota cada intento de petición. |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Endpoint fijo, sin `baseUrl`. Lee `OPENCODE_API_KEY`.

## openai-compatible [#openai-compatible]

Cualquier servidor que hable la API Chat Completions de OpenAI: LM Studio, Ollama, vLLM o una API alojada.

El servidor debe servir Chat Completions en `<baseUrl>/chat/completions` con salida de JSON schema estricto. Las pasarelas que solo atienden a sus propias apps cliente no funcionan.

```ts title="verbatra.config.ts"
provider: {
  id: "openai-compatible",
  options: {
    baseUrl: "http://192.168.178.74:1234/v1",
    model: "qwen2.5-14b-instruct", // example: whatever your server exposes
    maxOutputTokens: 1024,
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `baseUrl` | URL `http` o `https` | obligatoria | La raíz de la API, que suele terminar en `/v1`. Una URL que termina en `/chat/completions` o `/completions` se rechaza; una sin `/v1` pasa la validación y falla al hacer la petición. |
| `model` | string | obligatoria | El modelo que exponga tu servidor. |
| `maxOutputTokens` | entero positivo | obligatoria | Limita los tokens de salida de una respuesta. |
| `apiKeyEnvVar` | nombre de variable | ninguno | La variable que contiene la clave de este servidor. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota cada intento de petición. |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Para una API alojada como Mistral:

```ts title="verbatra.config.ts"
provider: {
  id: "openai-compatible",
  options: {
    baseUrl: "https://api.mistral.ai/v1",
    model: "mistral-large-latest", // example: check Mistral's current model list
    maxOutputTokens: 4096,
    apiKeyEnvVar: "MISTRAL_API_KEY",
  },
}
```

La respuesta usa el mismo esquema estricto que `openai`; el primer objeto JSON balanceado se toma de cualquier prosa o bloque de código que lo rodee y se valida. `verbatra init --provider openai-compatible --base-url <url> --model <name>` escribe este bloque ([init](https://verbatra.kreitz-webdev.de/es/docs/cli/init.md#proveedores)), y `--api-key-env-var <NAME>` añade el nombre de la variable.

### Las claves son opcionales [#las-claves-son-opcionales]

La clave se resuelve en orden:

1. **`apiKeyEnvVar`**: si está definido, su variable debe contener una clave, o la ejecución falla con `MISSING_API_KEY`.
2. **`OPENAI_COMPATIBLE_API_KEY`**: se usa si está definida y no vacía.
3. **`"local"`**: un placeholder fijo y no secreto, que es lo que hace funcionar un servidor sin clave.

`apiKeyEnvVar` no puede nombrar la variable de un proveedor alojado, y el cliente nunca lee `OPENAI_API_KEY`, así que una clave alojada nunca llega a un `baseUrl` personalizado.

<Callout type="warn" title="Una clave real sobre http en claro viaja sin cifrar">
Con una clave y una URL `http://` que no es loopback, la clave cruza tu red sin cifrar y sin aviso, así que usa `https://` para un servidor que necesite clave.
</Callout>

### Elegir un modelo local [#elegir-un-modelo-local]

Prefiere un modelo multilingüe ajustado por instrucciones y sin razonamiento, tan grande como tu hardware ejecute bien, como `qwen2.5-14b-instruct`. Los modelos de razonamiento y las compilaciones muy cuantizadas tienden a envolver o truncar la respuesta, lo que falla como `INVALID_RESPONSE` u `OUTPUT_TRUNCATED`.

## LibreTranslate [#libretranslate]

<AvailableFrom version="0.12.0" />

Un servidor [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) autoalojado (Argos Translate, sin modelo de lenguaje). verbatra solo llama a su API HTTP, así que la licencia AGPL-3.0 del servidor no se extiende a tu proyecto.

```ts title="verbatra.config.ts"
provider: {
  id: "libretranslate",
  options: {
    baseUrl: "http://localhost:5000",
  },
}
```

| Opción | Tipo | Por defecto | Efecto |
| --- | --- | --- | --- |
| `baseUrl` | URL `http` o `https` | obligatoria | La raíz de la API, sin `/translate`. |
| `requestTimeoutMs` | entero positivo | `120000` | Acota la llamada completa (sin reintentos). |
| `localeMap` | mapa de locale a código | ninguno | Sustituye el código enviado por locale. |

Sus idiomas son los modelos instalados en tu servidor:

```bash
docker run -p 5000:5000 libretranslate/libretranslate --load-only en,de,fr
```

- **Clave.** `LIBRETRANSLATE_API_KEY` se envía como `api_key` solo cuando está definida. Un servidor arrancado con `--api-keys` hace fallar la ejecución con `MISSING_API_KEY` cuando no está definida, y con `AUTH_FAILED` cuando la rechaza.
- **Los placeholders** se enmascaran como en DeepL, como marcadores `{0}` sin etiqueta; el marcado se conserva, así que solo cuentan las llaves junto a un placeholder.
- **Marcado.** Un valor con etiquetas de estilo HTML se envía en formato `html`: el texto dentro de las etiquetas se traduce, las etiquetas se quedan (una frase que cruza una etiqueta puede resentirse) y las etiquetas cambiadas se rechazan.
- **Comprobación de idiomas.** Cada destino avisa `LOCALE_UNVERIFIED_BY_PROVIDER` en cada ejecución; `verbatra doctor --locales --live` los comprueba contra el servidor.

`verbatra init --provider libretranslate --base-url <url>` escribe este bloque.

## none [#none]

<AvailableFrom version="0.12.0" />

Desactiva la traducción automática por política, para una norma que prohíbe enviar cadenas a cualquier servicio.

```ts title="verbatra.config.ts"
provider: { id: "none" }
```

`options` puede omitirse o ser `{}`. No se construye ningún proveedor, no se lee ninguna clave y no se hace ninguna petición; lo que hace cada comando en su lugar está en [Trabajar sin traducción automática](https://verbatra.kreitz-webdev.de/es/docs/human-only-workflow.md).

## Tono y glosario entre proveedores [#tono-y-glosario-entre-proveedores]

Una petición lleva solo los términos del glosario de su locale de destino, y cada salida se comprueba contra ellos.

| Proveedor | `tone` | `glossary` |
| --- | --- | --- |
| Anthropic, OpenAI, Gemini, OpenCode, openai-compatible | se envía y se respeta | traducciones, traducciones prohibidas, términos que no se traducen y notas, enviados como datos vinculantes |
| DeepL | se asigna a la formalidad | `GLOSSARY_IGNORED`; solo se aplica `glossaryId` |
| Google Cloud Translation, LibreTranslate | `FORMALITY_DOWNGRADED` con `formal` o `informal` | `GLOSSARY_IGNORED` |

## Comportamiento que todo proveedor comparte [#comportamiento-que-todo-proveedor-comparte]

### Lotes [#lotes]

El trabajo de un locale se envía en sublotes secuenciales de como mucho [`maxBatchSize`](https://verbatra.kreitz-webdev.de/es/docs/config-file.md#maxbatchsize) entradas. Un sublote fallido se retiene y se reintenta en la siguiente ejecución mientras los demás siguen avanzando. DeepL y Google Cloud Translation además dividen un sublote para respetar sus propios topes por petición.

### Reintentos [#reintentos]

Los límites de tasa y los errores de servidor se reintentan con espera, por el cliente en OpenAI, OpenCode, openai-compatible, Anthropic y DeepL y por verbatra en Gemini. Google Cloud Translation y LibreTranslate no reintentan. Gemini respeta una espera indicada de hasta 5 segundos y hace fallar una más larga, como una cuota diaria agotada, al instante con `RATE_LIMITED`, que nombra la espera.

### Tiempo de espera de petición [#tiempo-de-espera-de-petición]

`requestTimeoutMs` (por defecto `120000` ms) evita que un servidor que nunca responde atasque una ejecución y retenga el bloqueo de escritura de un locale. Súbelo para un modelo local lento o un `maxBatchSize` grande.

```ts title="verbatra.config.ts"
provider: {
  id: "openai-compatible",
  options: {
    baseUrl: "http://192.168.178.74:1234/v1",
    model: "qwen2.5-14b-instruct",
    maxOutputTokens: 1024,
    requestTimeoutMs: 300000, // 5 minutes
  },
}
```

- **Por intento.** Cada [reintento](#reintentos) recibe el límite completo. Los proveedores LLM también reintentan un intento que agotó el tiempo, y todos menos Gemini un error de conexión, así que un servidor colgado tarda hasta tres límites más las pausas.
- **El error nombra la causa.** `TIMEOUT` significa que un intento no recibió respuesta a tiempo; las conexiones rechazadas repetidas fallan como `PROVIDER_ERROR`.
- **DeepL** no puede abortar una petición en vuelo, así que una ejecución interrumpida la deja resolverse en DeepL.

### Códigos de locale enviados al proveedor [#códigos-de-locale-enviados-al-proveedor]

<AvailableFrom version="0.12.0" />

Los archivos, el bloqueo y la memoria siempre usan los códigos de tu configuración. Solo la petición se traduce a lo que espera el proveedor:

| Proveedor | Locale de origen | Locale de destino |
| --- | --- | --- |
| DeepL | Solo el idioma: `en-US` como `EN`, `zh-Hant-TW` como `ZH`. | `zh-Hant`, `zh-TW`, `zh-HK`, `zh-MO` como `ZH-HANT`; `zh-Hans`, `zh-CN`, `zh-SG` como `ZH-HANS`. Las variantes de DeepL se conservan (`EN-GB`, `EN-US`, `PT-BR`, `PT-PT`, `ES-419`, `FR-CA`, `FR-FR`, `DE-CH`, `DE-DE`). El español con una región de Latinoamérica o del Caribe (`MX`, `AR`, `CO`, `CL`, `PE`, `VE`, `EC`, `GT`, `CU`, `BO`, `DO`, `HN`, `PY`, `SV`, `NI`, `CR`, `PA`, `UY`, `PR`, `US`, `419`) como `ES-419`. Las demás regiones y escrituras se descartan: `de-AT` como `DE`. |
| Google Cloud Translation | `zh-Hant` (`zh-HK`, `zh-MO`) como `zh-TW`, `zh-Hans` (`zh-SG`) como `zh-CN`, `nb` como `no`; todo lo demás tal como está escrito. | Igual que el origen. |
| LibreTranslate | Solo el idioma (`de-AT` como `de`), salvo que `pt-BR` se conserva y el chino se envía como `zh-Hans` o `zh-Hant` (`zh-TW` como `zh-Hant`). | Igual que el origen. |
| Anthropic, OpenAI, Gemini, OpenCode, openai-compatible | Tal como está escrito. | Igual que el origen. |

Un LLM recibe además los [nombres de idioma, escritura y región](https://verbatra.kreitz-webdev.de/es/docs/translation-safety.md#nombres-de-idioma-escritura-y-región). DeepL no tiene un inglés ni un portugués genéricos como destino, así que un destino que acaba siendo un `en` o `pt` escueto (como `en-AU`) se rechaza antes de la ejecución: asígnalo a `EN-GB`, `EN-US`, `PT-BR` o `PT-PT`.

`localeMap` sustituye el código por locale:

```ts title="verbatra.config.ts"
provider: {
  id: "deepl",
  options: {
    localeMap: {
      "en-AU": "EN-GB",
      "fr-BE": "FR-FR",
    },
  },
}
```

- **Las claves** deben ser `sourceLocale` o un locale de destino como en la configuración, o la configuración falla con `CONFIG_INVALID`. El mapa va bajo `options`, en todos los proveedores salvo `none`.
- **Los valores** son cadenas no vacías de 64 caracteres como máximo, enviadas sin cambios: como código de idioma a un proveedor de traducción automática, en lugar del código a un LLM (`"pt-BR (Brazilian Portuguese)"` funciona), cuyos nombres de idioma siguen saliendo de la clave. Un `EN` o `PT` escueto para DeepL falla con `INVALID_REQUEST`; un valor que el proveedor rechace hace fallar su sublote.
- **Efecto en la memoria.** Solo las cadenas nuevas y cambiadas se envían con un código nuevo. Un mapa no vacío forma parte de la huella de la [memoria](https://verbatra.kreitz-webdev.de/es/docs/the-cache.md), así que cambiarlo abre un compartimento aparte.

### Comprobar el soporte de idiomas de un proveedor [#comprobar-el-soporte-de-idiomas-de-un-proveedor]

<AvailableFrom version="0.12.0" />

Cada locale configurado se evalúa antes de gastar nada:

| Proveedor | Se evalúa contra | Se rechaza antes de la ejecución | Genera un aviso |
| --- | --- | --- | --- |
| DeepL | Su tabla de idiomas incluida, con el soporte de glosario y de formalidad por idioma | Un idioma de origen o de destino que no está en la lista | Un glosario para un par fuera de los idiomas de glosario, un tono sin formalidad, un código que aparece solo en parte en la lista |
| Google Cloud Translation | Su tabla de idiomas incluida | Un idioma que no está en la lista | Cualquier glosario, un tono `formal` o `informal`, un código regional que aparece en la lista solo como idioma |
| LibreTranslate | Nada antes de una ejecución; el `/languages` del servidor con `doctor --live` | Nunca | Cada locale de destino en cada ejecución, cualquier glosario, un tono `formal` o `informal` |
| Anthropic, OpenAI, Gemini, OpenCode, openai-compatible | Nada: un LLM acepta cualquier idioma | Nunca | Un idioma fuera de la [lista de idiomas bien probados](https://verbatra.kreitz-webdev.de/es/docs/language-support.md#comprobar-el-soporte-antes-de-una-ejecución) |
| none | No aplica | Nunca | Nunca |

Un locale no admitido se rechaza con [`LOCALE_UNSUPPORTED_BY_PROVIDER`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#locale_unsupported_by_provider) (salida `2`) antes de construir ningún proveedor; una advertencia nunca rechaza y aparece como [aviso](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#sdk-notice-codes). [`verbatra doctor`](https://verbatra.kreitz-webdev.de/es/docs/cli/doctor.md#soporte-de-locales) informa de cada veredicto, y su opción `--live` comprueba la lista actual del proveedor, pero `translate` siempre usa la tabla incluida. Para un idioma añadido después, asigna el locale en `localeMap`: un código explícito se envía con un aviso, no se rechaza.

### Errores estructurados [#errores-estructurados]

Un fallo de proveedor aflora como un [error estructurado y sin secretos](https://verbatra.kreitz-webdev.de/es/docs/translation-safety.md#los-errores-nunca-filtran-nada) que solo afecta a su propio sublote. Un `PROVIDER_ERROR` nombra solo el host y el puerto de un `baseUrl` de openai-compatible o LibreTranslate, y en Google solo `translation.googleapis.com`, nunca la consulta que lleva su clave.

### Límites de tokens de salida [#límites-de-tokens-de-salida]

Los proveedores LLM limitan los tokens de cada respuesta; un modelo que se detiene en el tope levanta [`OUTPUT_TRUNCATED`](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#output_truncated). verbatra vuelve a dividir un sublote truncado en mitades, bajando hacia una sola entrada, y retiene solo una entrada que sigue desbordándose. Para resolverlo del todo, baja `maxBatchSize` o sube `maxTokens` (Anthropic) o `maxOutputTokens`. Un modelo de razonamiento gasta tokens de razonamiento ocultos del mismo presupuesto, así que dale margen de sobra.

### Señales de revisión [#señales-de-revisión]

Una traducción sospechosa de cualquier proveedor se marca para revisión, no se rechaza. Consulta los [motivos de revisión](https://verbatra.kreitz-webdev.de/es/docs/error-codes.md#review-reason-codes) y [Revisar en Studio](https://verbatra.kreitz-webdev.de/es/docs/review-in-studio.md).
