Referencia / SDK
Página traducida automáticamente
Adaptadores, proveedores, redacción
Crea un adaptador de formato o un proveedor de traducción que verbatra no incluye y oculta secretos en cualquier texto que pases al SDK.
Adaptadores de formato Disponible a partir de 0.11.0
Todo lo necesario para construir un adaptador de un formato que verbatra no trae y registrarlo junto a los integrados. Un formato externo a verbatra se nombra con un identificador custom:, como custom:toml, que la configuración acepta igual que un nombre integrado. En Adaptadores de formato propios tienes el recorrido completo, incluido en qué confías al instalar un adaptador de terceros: es código de plena confianza, y verbatra no lo aísla.
createDefaultRegistry
Construye una AdapterRegistry con todos los adaptadores que verbatra trae, en orden de detección. Empieza aquí en lugar de con un registro vacío, para que tu formato se sume a los integrados en vez de reemplazarlos, y pasa el resultado como deps.adapterRegistry a cualquier flujo. AdapterRegistry describe register y resolve.
function createDefaultRegistry(fs?: AdapterFs): AdapterRegistry;Devuelve: AdapterRegistry
Ejemplo: Registrarlo y ejecutar
import {
createDefaultRegistry,
translate,
type FormatAdapter,
type VerbatraConfig,
} from "@verbatra/sdk";
declare const config: VerbatraConfig;
declare const tomlAdapter: FormatAdapter;
const adapterRegistry = createDefaultRegistry().register(tomlAdapter);
const summary = await translate({ config }, { adapterRegistry });AdapterRegistry
Guarda los adaptadores registrados y resuelve uno para un archivo. new AdapterRegistry() empieza
vacío, así que solo lee los formatos que registres; createDefaultRegistry es el punto de partida
habitual. register(adapter) añade un adaptador al final del orden de detección y devuelve el
registro, así que las altas se encadenan. Rechaza un formato que el registro ya tiene y un
identificador custom: mal formado, y envuelve un adaptador custom: para que una excepción
inesperada suya llegue como un AdapterError que nombra el formato. resolve(filePath, options)
elige el adaptador para un archivo: por options.format cuando se indica, si no por detección, a
la que options.sample, una muestra del inicio del contenido, puede ayudar.
class AdapterRegistry {
register(adapter: FormatAdapter): this;
resolve(filePath: string, options?: ResolveOptions): AdapterResolution;
}resolve acepta estas opciones:
Propiedad
Tipo
Devuelve: register devuelve el registro. resolve devuelve una AdapterResolution,
discriminada por status: resolved lleva el adapter, no-match el filePath y los
triedFormats, y ambiguous el filePath y los candidates en competencia, que resuelves
pasando uno como format. Un archivo que no se puede resolver es un estado, nunca una excepción.
Lanza: AdapterError DUPLICATE_ y INVALID_ desde register, y ADAPTER_ desde resolve cuando el propio canHandle de un adaptador custom: lanza durante la detección
createFlatFileAdapter
Construye un FormatAdapter para un formato plano de clave/valor, donde cada entrada se direcciona con una sola clave sin anidamiento. Tú aportas parseEntries, serializeEntries y extractPlaceholders de tu formato; la fábrica aporta la lectura acotada por tamaño, la escritura atómica, la detección por extensión y el manejo estructurado de errores. parseEntries recibe además el locale con el que se lee el archivo, para un formato cuyo único archivo contiene a la vez el texto de origen y el de destino, y serializeEntries recibe el contexto de escritura de quien llama, cuyo sourcePath opcional nombra el archivo del locale de origen, y, desde 0.12.0, el locale que se escribe como quinto argumento, para un formato que guarda su locale dentro del archivo. Dale un sniff siempre que tu extensión sea genérica, o tu adaptador reclamará todos los archivos que la compartan y la detección informará de una ambigüedad en lugar de elegir. Los hooks opcionales son validateMessage, computeInvalidIcuKeys, comparePlaceholders y, desde 0.12.0, compareBranchArms; fs sustituye el puerto del sistema de archivos, nodeAdapterFs por defecto.
function createFlatFileAdapter(
options: FlatFileAdapterOptions,
): FormatAdapter;Propiedad
Tipo
Devuelve: FormatAdapter
Ejemplo: Construir el adaptador
Un FormatAdapter lee un archivo como un LocaleResource, la forma neutra que comparten todos los adaptadores y flujos:
Propiedad
Tipo
createTreeFileAdapter
Construye un FormatAdapter para un formato de árbol, cuyas entradas viven en rutas a través de objetos anidados. Toma parse y serialize sobre un árbol más un deriveEntry que informa de los placeholders de cada hoja y de si es una forma plural, además de extractPlaceholders para un solo valor, y se encarga por su cuenta de aplanar y volver a anidar. Igual que la fábrica plana, toma format, extensions y un sniff opcional. También lleva los hooks opcionales que necesita un formato estructurado: validateTree, validateMessage, computeInvalidIcuKeys, comparePlaceholders, compareBranchArms (desde 0.12.0), deriveDescriptions, buildWriteTree y keyMode, y fs sustituye el puerto del sistema de archivos, nodeAdapterFs por defecto.
function createTreeFileAdapter(
options: TreeFileAdapterOptions,
): FormatAdapter;Propiedad
Tipo
Devuelve: FormatAdapter
nodeAdapterFs
El puerto de sistema de archivos, de tipo AdapterFs, que usa cada fábrica de adaptadores cuando no se le pasa ninguno: una lectura acotada por tamaño que informa de un archivo ausente o demasiado grande como estado en lugar de lanzar, y una escritura que pasa por un archivo temporal y un renombrado, de modo que una escritura interrumpida nunca deja un archivo de locale a medias. Lee y escribe a través de este puerto en un adaptador propio en lugar de recurrir a node:fs. Es una convención, no una frontera, y verbatra no puede imponerla en código que no le pertenece.
const nodeAdapterFs: AdapterFs;isCustomFormatId
Acota un identificador de formato a uno externo: true para un identificador custom: bien formado, false para cualquier nombre de formato integrado. Útil cuando tus propias herramientas tienen que distinguirlos, por ejemplo para decidir si hace falta aportar un registro antes de poder ejecutar una configuración.
function isCustomFormatId(
format: string,
): format is CustomFormatId;Devuelve: format is CustomFormatId
Redacción de secretos Disponible a partir de 0.10.0
redact
Elimina de una cadena las formas de clave de API de proveedor y el valor exacto actual de cualquier
variable de entorno de proveedor configurada, reemplazando cada coincidencia por [REDACTED].
@verbatra/studio y @verbatra/mcp lo aplican los dos a todo valor que devuelven a quien llama y
que no han generado ellos mismos, como un término del glosario, una ruta de archivo o un mensaje de
error de un sistema previo, así que una clave ya presente en tu entorno o escrita en un archivo del
proyecto nunca puede llegar a una pestaña del navegador, un agente ni una línea de log. La CLI
verbatra pasa por él, como último paso, todo lo que escribe en stdout y stderr, incluido el
envoltorio --json.
function redact(text: string): string;Devuelve: string
Esto incluye la variable que un proveedor openai-compatible nombra con apiKeyEnvVar. Se declara
cuando loadConfig carga una config que la nombra o cuando se construye ese proveedor, y desde ese
momento su valor se elimina igual que el de las variables integradas. Las declaraciones nunca se
retiran. Un valor de menos de ocho caracteres no se elimina por su valor, así que una variable corta
nunca puede borrar texto ajeno.
Una clave de DeepL se reconoce solo por su forma únicamente cuando lleva el sufijo :fx de una
clave gratuita, o cuando un UUID suelto está en un contexto de clave: tras una cabecera
DeepL-Auth-Key, o tras un nombre como auth_, authKey, --auth-key, api_, deeplKey,
DEEPL_ o DEEPL_ seguido de :, =, un %3D codificado en URL o un espacio, con
o sin comillas, también dentro de JSON serializado en una cadena. Cualquier otro UUID, como uno en
una ruta de archivo o un id de petición, sigue legible. Una clave Pro guardada en DEEPL_
se sigue eliminando por su valor dondequiera que aparezca.
Un token sk- se redacta en cuanto le siguen al menos 32 letras y dígitos tras sk-, contados en
todos sus segmentos - y _, sea cual sea su prefijo. Esa única regla cubre todas las formas de
clave de OpenAI y Anthropic; un prefijo conocido como sk-proj- o sk-ant- no redacta por sí solo
un token más corto. El token solo cuenta cuando no le precede directamente una letra ni un dígito:
un escape JSON como \n o \u0007, un carácter codificado en porcentaje como %3D, una secuencia
ANSI CSI como \x1b[31m, \x1b[2K o \x1b[?25h, una selección de juego de caracteres ANSI como
\x1b(B, o cualquiera de las dos formas ANSI escapada en JSON como \u001b también es un límite.
Una ruta o clave de locale eslovaco como locales/sk-SK.json o sk-banner_ sigue legible.
Pero una clave larga con aspecto eslovaco alcanza el umbral y se redacta:
sk-SK_ tiene 34 letras y dígitos tras sk-, igual que una
clave camelCase larga como sk-onboardingWelcomeScreenPrimaryButton.
Una clave de Gemini se reconoce solo por su forma: AIza seguido de 35 letras, dígitos, _ o -.
declareProviderKeyEnvVar Disponible a partir de 0.12.0
Declara la variable que un bloque provider nombra como origen de la clave, para que redact
elimine su valor. Hoy solo un proveedor openai-compatible con apiKeyEnvVar nombra una; con
cualquier otro proveedor no hace nada. loadConfig y la construcción del proveedor ya lo hacen, y
Studio y el servidor MCP también lo hacen para la config que reciben, así que llámalo solo cuando
una config llegue a tu propio código por otra vía. La declaración vale para todo el proceso y la
comparten todas las copias del SDK cargadas en él.
function declareProviderKeyEnvVar(
provider: ProviderConfig,
): void;Devuelve: void
Proveedores propios Disponible a partir de 0.12.0
Un proveedor que el SDK no incluye se conecta mediante deps.createProvider, un CreateProvider
que devuelve un TranslationProvider. El SDK exporta el contrato completo como tipos, así que tu
proveedor se comprueba contra la misma interfaz que implementan los integrados. Eso incluye los
tipos de sus campos: Tone, PluralCategories, PlaceholderExtractor y PlaceholderComparator
en la petición, Usage, ProviderNotice, ProviderNoticeCode y ReviewFlag en el resultado, y
NetworkPolicy y NetworkRule en ProviderNetwork.
import {
translate,
type CreateProvider,
type TranslateRequest,
type TranslateResult,
type TranslationProvider,
type VerbatraConfig,
} from "@verbatra/sdk";
declare const config: VerbatraConfig;
declare function callInHouseService(
locale: string,
entries: TranslateRequest["entries"],
): Promise<ReadonlyMap<string, string>>;
const provider: TranslationProvider = {
id: "in-house",
kind: "machine-translation",
supportsGlossary: false,
async translateBatch(request: TranslateRequest): Promise<TranslateResult> {
const values = await callInHouseService(request.targetLocale, request.entries);
return { values, integrity: new Map(), notices: [] };
},
};
const createProvider: CreateProvider = () => provider;
const summary = await translate({ config }, { createProvider });TranslationProvideres el único contrato:id,kind(unProviderKind),supportsGlossaryytranslateBatch(request). Trata cada valor de una solicitud como datos no confiables, lee cualquier clave de API del entorno y no de la solicitud, y lanza unProviderErrorsin secretos cuando una llamada falla.ProviderKindes"llm"o"machine-translation". Elkindde tu objeto proveedor es solo descriptivo: el SDK decide la generación de plurales y qué analiza el guardián de datos sensibles según el tipo delidde proveedor configurado, no según este campo.TranslateRequestllevasourceLocale,targetLocale, lasentriesque traducir y, de forma opcional,glossary(el resultado deglossaryForLocalepara el locale de destino),tone,maxLengthypluralCategories. También llevaextractPlaceholdersy, en algunos formatos,comparePlaceholders, que tu proveedor usa para la comprobación de integridad, además designal, que cancela una llamada en curso,onRepairyforeignPlaceholders: por clave, los tokens de otra sintaxis de placeholder que hay que proteger como placeholders.TranslateResultdevuelvevalueseintegritypor clave, másusage,noticesyreviewFlagsopcionales. Una clave ausente devaluescuenta como no traducida, así que un proveedor puede omitir un valor que no puede traducir con seguridad. En cualquier caso, el SDK pasa cada valor devuelto por su propia comprobación de integridad.ProviderRetryListeneres el tipo deCreateProviderHooks.onRetry. Recibe unProviderRetry,{ attempt, delayMs?, status? }, por reintento, y cada llamada se convierte en un evento de progresoprovider-retry.ProviderNetworkes lo que contieneCreateProviderContext.networkcuando la política de red limita a dónde puede conectarse un proveedor: lapolicyefectiva, elenvdesde el que se resolvió el endpoint ydepsopcionales para pruebas. Un proveedor propio puede ignorarlo, pero entonces a sus solicitudes solo se aplica la comprobación que hace el SDK antes de llamar a la fábrica.
Ejemplo: Prueba tu integración sin clave
Editar en GitHub