Integrações
Vue
O pacote oficial de Vue 3 para Verbaly. Composables com limpeza automática, um componente <Trans> para rich text, e chaves + params totalmente tipados.
O que você pode fazer:
- Traduza com composables (useT, useLocale) que reagem a cada troca de idioma
- Vincule o idioma direto a um select:
useLocale()retorna um computed gravável - Mantenha chaves e params totalmente tipados, com autocompletar das suas próprias mensagens
- Zero vazamentos: as assinaturas são por componente e limpas via
onScopeDispose
Instalação
Instale o pacote com o seu gerenciador de pacotes preferido.
pnpm add @verbaly/vueSetup e 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>- As assinaturas são por componente e limpas ao desmontar via
onScopeDispose. useLocale()retorna um computed gravável, então vincule-o direto a um select.- Sem o plugin instalado, no navegador?
useT()euseLocale()leem a instância que ovirtual:verbalycria, então um teste de componente não precisa de preparação. No servidor o plugin é obrigatório, porque cada requisição tem a sua própria instância.
Escreva o texto no lugar
O compilador também lê seus arquivos .vue: escreva o texto fonte em uma interpolação, em um binding de diretiva ou no script setup, e ele é extraído, ganha sua chave e seus tipos ao salvar. O texto que só é exibido nunca é extraído, então uma página pode mostrar t`…` como exemplo sem risco. Sem inventar chaves, sem tocar em 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', …) -->Prefere chaves legíveis? t.id('inbox.title') antes do template extrai sob o seu id em vez de um hash do conteúdo.
Rich text com <Trans>
A mesma ideia; no Vue cada tag nomeado é uma render function que envolve seus filhos:
<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 dispense a render function: a prop links mapeia nomes de tag para hrefs (uma string ou um objeto href/target/rel). components ganha no mesmo nome; hrefs javascript: são bloqueados.
As etiquetas da whitelist (<em>, <code>…) renderizam como elementos a sério, sem precisar de uma render function: a mesma whitelist segura que o intérprete do DOM usa. richTags sobrepõe-na, e a prop instance renderiza sem o plugin.
Nuxt
As páginas renderizadas no servidor chegam já traduzidas no idioma do visitante, e o cliente hidrata com o mesmo locale e o mesmo catálogo, sem flash de texto sem tradução nem mismatch de hidratação.
- Cada página renderiza no idioma do visitante, tirado do endereço quando ele o leva, e se não da escolha salva ou do header
Accept-Language - Sem flash de texto sem tradução: o HTML que o servidor envia e a página já hidratada são idênticos, catálogo incluído
- Cada request tem sua própria instância, então dois visitantes simultâneos nunca veem o idioma um do outro
- Zero fiação: uma única entrada de módulo substitui o setup do plugin do Vite, a negociação e a sincronização dos atributos
langedir
O Nuxt precisa do módulo (@verbaly/nuxt) junto aos bindings do Vue:
pnpm add verbaly @verbaly/nuxt @verbaly/vueConecte tudo
Uma linha no nuxt.config. O módulo liga o plugin do Vite (extração viva e virtual:verbaly), escolhe o locale por request e mantém os atributos lang e dir em sincronia. Se seus endereços levam o idioma, ele os lê sozinho e não há nada a mais para escrever:
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'] }]],
});Daqui em diante é @verbaly/vue normal: useT() / useLocale() e o <Trans> funcionam sem mudanças em cada componente.
useT() é tipado pelo seu catálogo: os tipos vão para .nuxt/verbaly.d.ts, onde o Nuxt os vincula, e npx verbaly extract escreve esse mesmo arquivo. Uma chave que nenhum catálogo tem faz o nuxi typecheck falhar.
Trocar de idioma
switchLocale (export do core) carrega o catálogo primeiro, troca ao vivo e grava o cookie que o servidor lê, então o próximo request SSR já corresponde:
<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>- O cookie padrão é
verbaly-locale(a mesma identidade da key de storage do core);cookie: falsenas opções do módulo o desativa, paraAccept-Languagepuro. fallbacké por padrão seu locale fonte; a negociação entende q-values e estreita regiões (es-PEcasa comes).ssr: falsetambém está coberto: o módulo resolve o locale no navegador, lendo primeiro o endereço quando ele leva o idioma, depois o cookie, depoisnavigator.languages, depois seu fallback.- Sem dependência do próprio Nuxt: o módulo é tipado estruturalmente, sem
@nuxt/kit. A chaveverbalyemnuxt.config.tsfica totalmente tipada (autocompletar e detecção de erros de digitação), e continua compatível com o Nuxt 4. - Site totalmente estático (
nuxi generate)? Prefira saída pré-traduzida por locale com verbaly render.