Framework
Vue
The official Vue 3 package for Verbaly. Composables with automatic cleanup, a <Trans> component for rich text, and keys + params fully typed.
What you can accomplish:
- Translate with composables (useT, useLocale) that react to every locale switch
- Bind the locale directly to a select:
useLocale()returns a writable computed - Keep keys and params fully typed, with autocompletion from your own messages
- Zero leaks: subscriptions are per-component and cleaned up via
onScopeDispose
Installation
Install the package with your preferred package manager.
pnpm add @verbaly/vueSetup & 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>- Subscriptions are per-component and cleaned up on unmount via
onScopeDispose. useLocale()returns a writable computed, so you can bind it directly to a select.
Write the text in place
Since 0.20.0 the compiler reads your .vue files too: write the source text in the template, in a binding or in script setup, and it is extracted, keyed and typed on save. No key to invent, no catalog to touch.
<template>
<p>{{ t`Hola ${user.name}` }}</p>
<a :title="t`Abrir ajustes`">…</a>
</template>
<!-- extracted on save; the build rewrites both to t('key', …) -->Prefer readable keys? t.id('inbox.title') before the template extracts under your id instead of a content hash.
Rich text with <Trans>
Same idea; in Vue each named tag is a render function that wraps its children:
<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>For plain links skip the render function: the links prop (0.11.0) maps tag names to hrefs (a string or an href/target/rel object). components wins on the same name; javascript: hrefs are blocked.
Since 0.23.0 whitelisted tags (<em>, <code>…) render as real elements with no render function needed, the same safe whitelist as the DOM interpreter; richTags overrides it, and the instance prop renders without the plugin.
Nuxt
Server-rendered pages arrive already translated in the visitor's language, and the client hydrates with the same locale and catalog: no flash of untranslated text, no hydration mismatch.
- Every page renders in the visitor's language, chosen per request from their cookie or
Accept-Languageheader - No flash of untranslated text: the HTML the server sends and the page after hydration are identical, catalog included
- Each request gets its own instance, so simultaneous visitors never see each other's language
- Zero wiring: one module entry replaces the Vite plugin setup, the negotiation and the
langattribute sync
Nuxt needs the module (@verbaly/nuxt) alongside the Vue bindings:
pnpm add verbaly @verbaly/nuxt @verbaly/vueWire it up
One line in nuxt.config. The module wires the Vite plugin (live extraction and virtual:verbaly), negotiates the locale per request and keeps the lang attribute in sync:
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'] }]],
});From here it's plain @verbaly/vue: useT() / useLocale() and <Trans> work unchanged in every component.
Switching languages
switchLocale (a core export since 0.18.0) loads the catalog first, switches live, then writes the cookie the server reads, so the next SSR request already matches:
<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>- The cookie defaults to
verbaly-locale(same identity as the core's storage key);cookie: falsein the module options disables it, for pureAccept-Language. fallbackdefaults to your source locale; negotiation understands q-values and narrows regions (es-PEmatcheses).ssr: falseis covered too: the module resolves the locale in the browser (cookie, thennavigator.languages, then fallback).- No dependency on Nuxt itself: the module is typed structurally, without
@nuxt/kit. Theverbalykey innuxt.config.tsis still fully typed (autocomplete and typo checking), and it stays compatible across Nuxt 4. - Fully static site (
nuxi generate)? Prefer pre-translated output per locale with verbaly render.