Guías

CLI

El binario verbaly viene con @verbaly/compiler (dependencia del plugin de Vite), así que npx verbaly funciona directo.

Comandos

ComandoQué hace
verbaly initGenera config + catálogos de locales y sugiere el plugin correcto para tu bundler
verbaly doctorDiagnostica el setup (config, catálogos, cableado del plugin, tipos desactualizados, keys huérfanas) y te dice el fix exacto de cada hallazgo
verbaly extractEscanea las fuentes (.js/.ts/.jsx/.tsx, y .svelte/.vue desde 0.20.0), escribe los mensajes nuevos al catálogo fuente, agrega placeholders "" al resto y regenera verbaly.d.ts
verbaly statusMuestra la cobertura de traducción por idioma de un vistazo (es: 45/48 translated), solo informativo, nunca falla
verbaly checkVerifica que cada clave tenga traducción en cada idioma. Sale con 1 ante claves faltantes o desconocidas, hecho para CI
verbaly translateLlena los huecos "" que check reporta vía un provider de traducción, Claude por defecto
verbaly exportEscribe archivos XLIFF 2.0 o CSV por idioma listos para el traductor, o recursos nativos de Android e iOS para una app móvil hermana
verbaly importRellena los catálogos desde archivos XLIFF/CSV traducidos, con cada entrada validada estructuralmente y las rotas rechazadas y reportadas
verbaly pseudoGenera un catálogo pseudo-locale de QA (en-XA) desde el fuente, exponiendo strings hardcodeados y layouts que se cortan
verbaly renderPre-llena el HTML data-verbaly por locale en tu sitio compilado, así que las páginas estáticas salen ya traducidas

Scaffolding

verbaly init deja un proyecto listo en un comando: una config tipada (.ts si tienes tsconfig, .mjs si no), tu catálogo fuente más uno por cada --locales, y los pasos siguientes para tu bundler: Vite → @verbaly/vite, el resto → @verbaly/unplugin.

npx verbaly init --locales es,pt
# created: verbaly.config.ts, locales/en.json, locales/es.json, locales/pt.json
# detected bundler: vite → pnpm add -D @verbaly/vite

Re-ejecutarlo es seguro: una config o catálogo existente se reporta como “kept” y queda intacto.

Chequeo de salud

verbaly doctor (0.13.0) es el hermano de init para proyectos ya andando: inspecciona todo el setup y reporta cada hallazgo con el comando exacto que lo arregla. Verde significa sano; los problemas salen con 1.

npx verbaly doctor
# ✓ config: verbaly.config.ts found
# ✓ catalogs: 3 locales (en, es, pt) in locales/
# ⚠ types: verbaly.d.ts is stale
#     fix: run `npx verbaly extract`
# ⚠ orphans: 2 catalog keys are no longer referenced (old.title, hero.cta)
#     fix: run `npx verbaly extract --prune` to drop them
# ✗ keys: 1 unknown key used in code (ghost.key)

Un comando para responder “¿por qué no traduce esto?” Revisa tu config, tus catálogos y el cableado del plugin, si verbaly.d.ts está al día, y cualquier key huérfana o faltante.

Claves legibles

Las claves hasheadas son el default sin config. Cuando quieras ids legibles, agrupados con namespaces de puntos, opta por mensaje con t.id:

t.id('inbox.title')`Hello ${name}`;
// extracted under "inbox.title" and rewritten to:
t('inbox.title', { name });

Los catálogos siguen siendo JSON plano. Los puntos son solo una convención de nombres. Los ids dinámicos (t.id(someVar)) no se tocan, y los ids duplicados con textos distintos disparan el warning de colisión de claves.

Flags

FlagDefaultDescripción
--rootcwdRaíz del proyecto
--dirlocalesDirectorio de catálogos
--sourceenIdioma fuente
--localesde los archivosIdiomas extra, separados por coma
--pruneoffElimina claves sin referencias (solo extract)
--watchoffRe-extrae cuando cambian los archivos fuente: extracción viva para setups con webpack, Rspack y Rollup (solo extract, 0.23.0)
--localeen-XAId del pseudo-locale (solo pseudo)
--sitedistDirectorio del sitio compilado (solo render)

Desde 0.17.0 las flags se validan por comando: una flag que pertenece a otro comando termina con un error accionable en vez de ignorarse en silencio: translate --locale es te dice que querías --locales.

Traducción máquina

verbaly translate (0.9.0) cierra el ciclo: escribir → extracttranslatecheck en verde. El provider por defecto usa Claude (@anthropic-ai/sdk como peer opcional + ANTHROPIC_API_KEY); batches de 20 por request.

npx verbaly translate --dry-run        # list what's missing, write nothing
npx verbaly translate --locales es,pt  # fill only these locales
npx verbaly translate --model claude-opus-4-8  # override the default (claude-sonnet-5)

Cada traducción se verifica: los placeholders y las etiquetas deben sobrevivir intactos. Si uno no lo hace, la traducción se rechaza y la entrada queda en "", así que check la sigue marcando hasta arreglarla.

Sin lock-in: conecta tu propio provider en verbaly.config.ts:

verbaly.config.ts
export default {
  translate: {
    provider: async ({ sourceLocale, targetLocale, messages }) => ({ /* key → translation */ }),
  },
};

Traductores y TMS

¿Humanos en el ciclo? verbaly export (0.15.0) escribe archivos XLIFF 2.0 o CSV por idioma listos para el traductor y verbaly import los trae de vuelta, validados estructuralmente con el mismo gate que translate. El flujo completo, opciones de TMS incluidas, vive en Trabajar con traductores.

Desde 0.22.0, export también escribe recursos nativos mobile: --format android-xml para el layout res/ de Android y --format ios-strings para Xcode. Las claves sin traducir se omiten para que la app haga fallback a tu idioma fuente (--missing aplica solo a los formatos de traductor).

Render estático (SSG)

verbaly render (0.10.0) mata el flash de contenido sin traducir en sitios estáticos: recorre tu HTML compilado y pre-llena cada elemento data-verbaly por locale con el runtime real: plurales, formato Intl, data-verbaly-args, traducción de atributos y rich text con whitelist.

npx vite build              # or astro build, eleventy, …
npx verbaly render          # dist/index.html filled in the source locale
                            # dist/es/index.html, dist/pt/… for the rest
npx verbaly render --site out --locales es  # custom dir / locale filter

Pseudo-localización

verbaly pseudo (0.10.0) llena un catálogo de QA (en-XA por defecto) desde el locale fuente: letras acentuadas, marcadores ⟦…⟧ y ~33% de padding. El texto que sale limpio en el build pseudo está hardcodeado; los layouts que se cortan se delatan antes de que llegue una traducción real.

npx verbaly pseudo                 # locales/en-XA.json
# "Hello {name}" → "⟦Ĥéĺĺó {name} ~⟧"

Params, bloques de variantes y tags sobreviven verbatim, garantizados por la misma validación estructural de translate. Re-ejecutar regenera el catálogo completo.

Archivo de config

Los flags ganan sobre verbaly.config.{js,mjs,ts,mts,json} en la raíz del proyecto (los configs TS necesitan esbuild instalado). Mismas opciones que el plugin de Vite, una sola fuente de verdad:

verbaly.config.mjs
export default {
  sourceLocale: 'es',
  locales: ['es', 'en', 'pt'],
  dir: 'locales',
};

Ejemplo de CI

.github/workflows/ci.yml
- run: pnpm install
- run: npx verbaly check   # fails the job on missing translations
- run: pnpm build
Copiado en el portapapeles