Skip to content

Guides

Server-side

The core runs anywhere JavaScript does, including Node. Create an instance, pass the locale, call t(). No DOM required.

One instance per request

Build a fresh instance per request and hand it the visitor's locale. negotiateLocale reads the Accept-Language header and picks the best match among your locales (it understands quality values, and es-PE matches es). resolveRequestLocale makes the whole decision in one call: the address first when it carries the language, then the saved choice, then the browser, then your fallback. Instances don't share state, so two requests never mix their languages.

server.ts
import { createVerbaly, negotiateLocale } from 'verbaly';
import es from './locales/es.json';
import en from './locales/en.json';

function handle(req) {
  const locale = negotiateLocale(req.headers['accept-language'], ['en', 'es']);
  const v = createVerbaly({ locale, fallback: 'en', messages: { en, es } });
  return v.t('home.title');
}

When your addresses carry the language

If your pages live at /es/dashboard, that address is the answer. Anyone who opens the link gets Spanish, whether or not they ever picked a language here, because an address is public and shared while a saved choice belongs to one person. A page without a prefix then means your source language, so a visitor who once chose Spanish never sees your English pages translated by accident.

You switch this on by telling your integration the routing you already set. Here is the whole of it, per stack:

StackWhat you write
SvelteKitPass routing to verbalyHandle, and add verbalyReroute in hooks.ts so one route tree serves every language
NuxtNothing: the module reads the address for you
Next.jsrouting: 'prefix-all' in your config, and setRequestLocale(locale) in your [locale] layout, before anything asks for text
AstrocreateRequestInstance(Astro.currentLocale ?? sourceLocale) in the page

Your pages can also point search engines at each other. alternateLinks gives you the list of addresses for one page in every language, the same list a statically rendered site gets, so a server-rendered page is not a second-class citizen. See URL strategy.

Render HTML ahead of time

For static sites, verbaly render pre-fills your built HTML per locale so pages ship already translated. See CLI → Static rendering.

Meta-frameworks

On SvelteKit, Nuxt and Next.js you do not wire any of this by hand. The SvelteKit integration, the Nuxt module and the Next.js integration pick the language per request and hydrate without a flash, all on these same primitives.

↑↓to moveEnterto open
Copied to clipboard