Integrations
Vite plugin
import verbaly from '@verbaly/vite';
export default { plugins: [verbaly({ sourceLocale: 'es' })] };Options are the same as the CLI config: sourceLocale, locales, dir, include, exclude, root. Inline options win over the config file.
How it compiles
t`Hola ${name}`becomest("x7Ka9q2f", { "name": name }), where the key is the content hash, stable across files.- The source locale ships inline; every other locale becomes its own lazy chunk, loaded on first
setLocale(). - Catalogs stay plain JSON: no proprietary format, portable to any TMS.
- This covers
.svelte,.vueand.astrofiles too: script blocks and markup, including Svelte's$tstore form and Astro frontmatter.
Dev server
- New texts are extracted as you type; catalogs and types update with a debounce, then the dev server triggers a full page reload.
- Editing a catalog by hand reloads it. A text your code owns is put back, and the terminal names the file and line where it lives. Every write starts from the files on disk, so a checkout is never undone with an older text, and a catalog saved half-typed is reported in one line while the server keeps running.
- The terminal names each of these once: a key written with two texts, a
tunder another name, a translation older than its source. - When the dev server or the build starts, it names once every file outside your
includethat writest`…`, with the pattern to add: that text is never extracted, so it would show in your source language everywhere.
Build
The virtual module
The t/verbaly singleton is for the browser. On the server, createRequestInstance(locale) builds a fresh instance per request and awaits its catalog before returning: the no-FOUC contract in one call. createInstance(options) remains for custom setups (see Server-side).
adoptPage exists when render.inlineCatalog is on. Each page carries only the messages it shows, so a router that swaps documents has to hand the next page's over: call it from the hook that fires before the swap. Astro's <ClientRouter /> is wired for you.
The generated types live in src/verbaly.d.ts (the root when there is no src/), the folder the Vite and SvelteKit templates' tsconfig already reads, and they type this module: keys autocomplete and every key's params are enforced. A fresh clone writes them with npx verbaly typegen before tsc. Move them or turn them off with the dts config option.
Not on Vite? Use @verbaly/unplugin
@verbaly/unplugin brings the same compiler to webpack 5, Rollup, esbuild and Rspack: the typed virtual:verbaly module, the tagged-template transform and the build report, which says each problem once even across the rebuilds of a watch (failOnMissing: true stops the build instead).
import { verbaly } from '@verbaly/unplugin';
export default { plugins: [verbaly.webpack({ locales: ['en', 'es'] })] };
// also: verbaly.rollup(…) · verbaly.esbuild(…) · verbaly.rspack(…)It's build-focused: run npx verbaly extract in your dev loop or CI, since live extraction and HMR remain this Vite plugin's value. ESM-only, like the compiler (use webpack.config.mjs).