verbatra extract
Analiza el código de tu aplicación en busca de llamadas de traducción y añade las claves nuevas al archivo del locale de origen.
Página traducida automáticamente
Disponible a partir de 0.11.0
Todos los demás comandos parten de un archivo de locale que ya existe. extract es el único que parte de tu código: recorre las raíces de código que configures, encuentra las llamadas de traducción que hay en ellas y añade cualquier clave que todavía no esté en el archivo del locale de origen. Eso es lo que hace que verbatra sirva en un proyecto que aún no está internacionalizado, donde el catálogo es justo lo que no tienes.
No gasta nada. No construye ningún proveedor, no lee ninguna variable de entorno de clave de API y no hace ninguna petición de red, así que una ejecución sin clave configurada funciona.
Sinopsis
verbatra extract [flags]Configuración
extract se controla desde el bloque extract de tu configuración. Una ejecución sin él falla con EXTRACT_NOT_CONFIGURED y salida 2.
import { defineConfig } from "@verbatra/sdk";
export default defineConfig({
sourceLocale: "en",
targetLocales: ["de", "fr"],
format: "i18next-json",
files: { pattern: "locales/{locale}.json" },
provider: { id: "gemini", options: { model: "gemini-2.5-flash", maxOutputTokens: 4096 } },
extract: {
framework: "i18next",
roots: ["src"],
},
});Flags
| Flag | Argumento | Por defecto | Efecto |
|---|---|---|---|
--cwd | <path> | directorio actual | resuelve la configuración, las raíces de código y los archivos de locale desde este directorio |
--config | <path> | busca uno | carga este archivo de configuración en lugar de buscar uno |
--dry-run | ninguno | desactivado | informa de lo que se añadiría y no escribe nada |
--json | ninguno | desactivado | imprime un envoltorio JSON en stdout con el resultado bajo result |
Qué encuentra
El framework i18next lee las formas de llamada t(...), $t(...) y <object>.t(...) en archivos .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts y .cts, cada una también como llamada opcional y con lista explícita de argumentos de tipo. La clave es el primer argumento. El valor por defecto es el segundo argumento o un campo defaultValue en el objeto de opciones:
t("nav.home"); // key only, written with an empty value
t("nav.away", "Away"); // positional default
t("nav.help", { defaultValue: "Help" }); // default on the options object
t?.("nav.back"); // optional call
t<string>("nav.next"); // explicit type argumentSe entienden los comentarios, las cadenas y las expresiones regulares, así que una llamada escrita dentro de un comentario no se recoge y un t( entrecomillado dentro de una cadena no se convierte en clave.
La clave y el valor por defecto tienen que ser un literal completo. t("user." + id) se informa como dinámico en lugar de escribirse como la clave user., y t("nav.home", { defaultValue: "Home" + suffix }) añade la clave sin valor por defecto en lugar de con uno truncado.
La clave también tiene que nombrar una ruta direccionable. t("user."), t(".lead") y t("a..b") son literales completos, pero cada uno lleva un segmento vacío, y los formatos de árbol parten la clave por el ., así que la clave acabaría bajo un hijo sin nombre que tu aplicación nunca lee. Esas también se informan como dinámicas.
Los namespaces todavía no se resuelven
Una clave con namespace, la forma t("common:nav.home"), se informa como dinámica y nunca se escribe. Una configuración de verbatra se dirige a un único archivo de catálogo, así que no hay ningún sitio para common:nav.home que signifique lo que tu configuración de i18next entiende por ello.
Conviene que sepas lo que cuesta antes de ejecutarlo: si tu proyecto nombra un namespace en cada llamada, cada llamada es dinámica y la ejecución no añade nada. Es deliberado en esta primera versión. extract hoy sirve en un proyecto que se queda con un solo namespace y escribe sus claves sin el prefijo; levantar el límite es lo siguiente tras el segundo framework.
Qué escribe
Solo el archivo del locale de origen, y solo las claves que son realmente nuevas:
- Una clave que ya está en el catálogo conserva su valor tal cual. Un valor por defecto dejado en una llamada nunca sobrescribe un valor que hayas editado tú o un traductor.
- Una clave del catálogo que ninguna llamada menciona se deja intacta.
extractañade e informa; nunca borra.verbatra diff --unusedlista esas claves. - Una ejecución que no encuentra nada nuevo no escribe nada en absoluto, así que el archivo queda idéntico byte a byte y su fecha de modificación no cambia.
- Nunca se escribe un archivo de locale de destino. Ejecuta
verbatra translatedespués deextractpara rellenar las claves nuevas.
Hay dos formatos que no se crean desde cero, ni aquí ni en ninguna otra parte de verbatra: xliff necesita un archivo de destino ya existente y apple-xcstrings necesita un catálogo creado en Xcode. Para esos dos, crea antes el catálogo de origen; extract añade entonces a ese archivo.
Qué informa en lugar de adivinar
Todo lo que el análisis no puede resolver vuelve como datos, de modo que un archivo incómodo nunca aborta la ejecución:
| Se informa como | Cuándo |
|---|---|
dynamic | el argumento de la clave no es una única cadena estática completa, o nombra una ruta que verbatra no puede direccionar: una variable, un acceso a propiedad, un literal de plantilla que lleva una expresión, una concatenación, una clave con namespace o una clave con un segmento de ruta vacío. Nunca se escribe con una clave adivinada, truncada o imposible de direccionar. |
conflicts | una clave aparece en dos llamadas que no coinciden en su valor por defecto. No se escribe ninguno de los dos, porque elegir uno haría que tu catálogo dependiera del orden de recorrido de directorios. |
withoutDefault | una clave se añadió con valor vacío porque su llamada no aportaba ningún valor por defecto. Rellénalo y luego traduce. |
diagnostics | un archivo o directorio no se pudo leer entero: desapareció, supera el límite de tamaño, el análisis falló con él, un comentario de bloque o un literal de plantilla sin cerrar abandonó el resto, o, en un archivo .tsx, .jsx o .js, un elemento JSX nunca se cierra o una cadena entre comillas en el código llega al final de su línea. Se sigue informando de lo leído antes de ese punto. |
Nada de esto cambia el código de salida. Son hallazgos, no fallos.
Límites del análisis
Nunca se lee nada fuera de las roots configuradas. node_modules, .git, .next, .turbo, .verbatra, dist, build y coverage se omiten siempre, y extract.exclude añade tus propios nombres de directorio a ese conjunto. Los enlaces simbólicos no se siguen, así que un enlace no puede sacar el análisis fuera de una raíz.
El resultado lleva únicamente claves, valores y ubicaciones de archivo y línea. El contenido de un archivo de código nunca viaja en él.
Ejemplos
# add every new key found in your source to the source locale file
verbatra extract
# preview the keys that would be added, write nothing
verbatra extract --dry-run
# machine-readable result for a CI step
verbatra extract --jsonUna ejecución se ve así:
verbatra extract
42 files scanned, 18 keys already present
added 3 keys to locales/en.json
new keys (3):
nav.home src/components/Nav.tsx:14
nav.away src/components/Nav.tsx:15
cart.empty src/routes/cart.tsx:31
dynamic keys (1):
src/routes/product.tsx:88Códigos de salida
| Código | Significado |
|---|---|
0 | el análisis se ejecutó, con independencia de lo que encontrara |
2 | no se pudo ejecutar: un error de uso, la ausencia del bloque extract, un formato que no se puede resolver, un catálogo de origen que no se puede analizar o un catálogo de origen que no se pudo escribir |
No hay salida 1. Las llamadas dinámicas y los valores por defecto en conflicto se informan, no se tratan como una ejecución fallida, así que extract en CI solo falla cuando de verdad no pudo hacer su trabajo.
Relacionado
- El archivo de configuración documenta el bloque
extract. verbatra translaterellena los locales de destino una vez existen las claves nuevas.verbatra checkinforma del desfase que crean las claves nuevas.- El SDK expone la misma capacidad como
extract().