Start
Getting started
Verbaly inverts the usual i18n flow: you write natural text in your code and the compiler extracts messages, generates stable keys, types and per-locale bundles. Requirements: Node 20+ and Vite 7 or 8.
- 1
Install
Add the runtime and the Vite plugin. Pick your package manager.
pnpm add verbaly @verbaly/vite - 2
Scaffold it in one command
npx verbaly initwrites the config, creates thelocales/catalogs and detects your bundler. It never overwrites anything. Prefer wiring by hand? The steps below do the same.terminalnpx verbaly init # config + locales/ + bundler detection - 3
Add the plugin
vite.config.tsimport verbaly from '@verbaly/vite'; export default { plugins: [verbaly({ sourceLocale: 'es' })], };sourceLocaleis the language you write in. Every other locale comes from a JSON catalog inlocales/: drop anen.jsonorpt.jsonthere and Verbaly picks them up automatically. - 4
Write text, not keys
src/app.tsimport { t, setLocale } from 'virtual:verbaly'; const saludo = t`Hola ${name}, tienes ${count} mensajes`; await setLocale('pt'); // lazy-loads pt chunkIn dev, the plugin extracts messages live: your source catalog fills itself, other locales get
""placeholders, andverbaly.d.tskeeps keys and params typed. - 5
Translate and verify
terminalnpx verbaly extract # sync catalogs + types npx verbaly check # exit 1 if anything is missing
What the virtual module exports
| Export | Description |
|---|---|
| t | Translate: t('key', params) or tagged t`...` |
| setLocale(locale) | Async: lazy-loads that locale's chunk, then switches |
| getLocale() | Current locale |
| subscribe(fn) | Re-run UI on locale/message changes; returns unsubscribe |
| verbaly | The underlying instance (advanced use) |