Saltar al contenido

Integraciones

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:

Instalación

Instala el paquete con tu gestor de paquetes preferido.

 pnpm add @verbaly/vue

Setup y composables

main.ts
import { verbalyPlugin } from '@verbaly/vue';
import { verbaly } from 'virtual:verbaly';

app.use(verbalyPlugin(verbaly));
Inbox.vue
<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>

Escribe el texto en su lugar

El compilador también lee tus archivos .vue: escribe el texto fuente en una interpolación, en un binding de directiva o en script setup, y se extrae, recibe su clave y sus tipos al guardar. El texto que solo se muestra nunca se extrae, así que una página puede enseñar t`…` como ejemplo sin riesgo. Sin inventar claves, sin tocar catálogos.

Inbox.vue
<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:

Agree.vue
<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 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.

Las etiquetas de la whitelist (<em>, <code>…) se renderizan como elementos de verdad, sin necesidad de una render function: la misma whitelist segura que usa el intérprete del DOM. richTags la sobrescribe, y la 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.

Nuxt necesita el módulo (@verbaly/nuxt) junto a los bindings de Vue:

 pnpm add verbaly @verbaly/nuxt @verbaly/vue

Conéctalo

Una línea en nuxt.config. El módulo conecta el plugin de Vite (extracción viva y virtual:verbaly), elige el locale por request y mantiene los atributos lang y dir en sincronía. Si tus direcciones llevan el idioma, las lee él solo y no hay nada más que escribir:

nuxt.config.ts
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.

useT() está tipado por tu catálogo: los tipos van a .nuxt/verbaly.d.ts, donde Nuxt los enlaza, y npx verbaly extract escribe ese mismo fichero. Una clave que ningún catálogo tiene hace fallar nuxi typecheck.

Cambiar de idioma

switchLocale (export del core) carga el catálogo primero, cambia en vivo y escribe la cookie que el servidor lee, así el próximo request SSR ya coincide:

LangPicker.vue
<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>
↑↓para moverteEnterpara abrir
Copiado en el portapapeles