Framework
Vue
El paquete oficial de Vue 3 para Verbaly. Composables con limpieza automática, un componente <Trans> para rich text, y claves + params totalmente tipados.
Qué puedes lograr:
- Traduce con composables (useT, useLocale) que reaccionan a cada cambio de idioma
- Enlaza el idioma directo a un select:
useLocale()devuelve un computed escribible - Mantén claves y params totalmente tipados, con autocompletado desde tus propios mensajes
- Cero fugas: las suscripciones son por componente y se limpian vía
onScopeDispose
Instalación
Instala el paquete con tu gestor de paquetes preferido.
pnpm add @verbaly/vueSetup y composables
import { verbalyPlugin } from '@verbaly/vue';
import { verbaly } from 'virtual:verbaly';
app.use(verbalyPlugin(verbaly));<script setup>
import { useT, useLocale } from '@verbaly/vue';
const t = useT();
const locale = useLocale(); // writable: locale.value = 'en'
</script>
<template>
<p>{{ t('inbox', { count: 3 }) }}</p>
</template>- Las suscripciones son por componente y se limpian al desmontar vía
onScopeDispose. useLocale()devuelve un computed escribible, así que conéctalo directo a un select.
Escribe el texto en su lugar
Desde 0.20.0 el compilador también lee tus archivos .vue: escribe el texto fuente en el template, en un binding o en script setup, y se extrae, recibe su clave y sus tipos al guardar. Sin inventar claves, sin tocar catálogos.
<template>
<p>{{ t`Hola ${user.name}` }}</p>
<a :title="t`Abrir ajustes`">…</a>
</template>
<!-- extracted on save; the build rewrites both to t('key', …) -->¿Prefieres claves legibles? t.id('inbox.title') antes del template extrae bajo tu id en vez de un hash del contenido.
Rich text con <Trans>
La misma idea; en Vue cada tag nombrado es una render function que envuelve a sus hijos:
<script setup>
import { Trans } from '@verbaly/vue';
import { h } from 'vue';
const components = { terms: (c) => h('a', { href: '/terms' }, c) };
</script>
<template>
<Trans id='agree' :components='components' />
</template>Para links simples olvídate de la render function: el prop links (0.11.0) mapea nombres de tag a hrefs (un string o un objeto href/target/rel). components gana con el mismo nombre; los hrefs javascript: se bloquean.
Desde 0.23.0 los tags de la whitelist (<em>, <code>…) se renderizan como elementos reales sin necesidad de render function, la misma whitelist segura del intérprete de DOM; richTags la reemplaza, y el prop instance renderiza sin el plugin.
Nuxt
Las páginas renderizadas en el servidor llegan ya traducidas al idioma del visitante, y el cliente hidrata con el mismo locale y el mismo catálogo, sin flash de texto sin traducir ni mismatch de hidratación.
- Cada página se renderiza en el idioma del visitante, elegido en cada request desde su cookie o su header
Accept-Language - Sin flash de texto sin traducir: el HTML que envía el servidor y la página ya hidratada son idénticos, catálogo incluido
- Cada request tiene su propia instancia, así que dos visitantes simultáneos nunca ven el idioma del otro
- Cero cableado: una sola entrada de módulo reemplaza el setup del plugin de Vite, la negociación y la sincronización del atributo
lang
Nuxt necesita el módulo (@verbaly/nuxt) junto a los bindings de Vue:
pnpm add verbaly @verbaly/nuxt @verbaly/vueConéctalo
Una línea en nuxt.config. El módulo cablea el plugin de Vite (extracción en vivo y virtual:verbaly), negocia el locale por request y mantiene el atributo lang sincronizado:
export default defineNuxtConfig({
modules: ['@verbaly/nuxt'],
});
// locales live in your verbaly.config (npx verbaly init), or inline:
export default defineNuxtConfig({
modules: [['@verbaly/nuxt', { locales: ['en', 'es', 'pt'] }]],
});De aquí en adelante es @verbaly/vue normal: useT() / useLocale() y <Trans> funcionan sin cambios en cada componente.
Cambiar de idioma
switchLocale (export del core desde 0.18.0) carga el catálogo primero, cambia en vivo y escribe la cookie que el servidor lee, así el próximo request SSR ya coincide:
<script setup>
import { switchLocale } from 'verbaly';
import { useVerbaly } from '@verbaly/vue';
const verbaly = useVerbaly();
</script>
<template>
<button @click="switchLocale(verbaly, 'es')">Español</button>
</template>- La cookie por defecto es
verbaly-locale(la misma identidad que la key de storage del core);cookie: falseen las opciones del módulo la desactiva, paraAccept-Languagepuro. fallbackpor defecto es tu locale fuente; la negociación entiende q-values y estrecha regiones (es-PEmatcheaes).ssr: falsetambién está cubierto: el módulo resuelve el locale en el browser (cookie, luegonavigator.languages, luego fallback).- Sin dependencia de Nuxt en sí: el módulo está tipado estructuralmente, sin
@nuxt/kit. La claveverbalyennuxt.config.tsqueda totalmente tipada (autocompletado y detección de errores de tipeo), y se mantiene compatible con Nuxt 4. - ¿Sitio totalmente estático (
nuxi generate)? Prefiere salida pre-traducida por locale con verbaly render.