Skip to content

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 22.12+ and Vite 7 or 8.

  • Node 22.12+ · Vite 7/8
  • TypeScript-first
  • ~3 KB0 dependencies
  1. Install

    Add the runtime, the Vite plugin and the compiler, which is where the verbaly command lives. Pick your package manager.

     pnpm add verbaly @verbaly/vite @verbaly/compiler

    The runtime is always the same; the second one depends on your setup. On webpack, Rollup, esbuild or Rspack you install @verbaly/unplugin instead, and Next.js, Nuxt and Astro have their own. See Packages.

  2. Scaffold it in one command

    npx verbaly init writes the config, creates the locales/ catalogs and detects your bundler, so it names the plugin you need and where to wire it. It never overwrites anything. Wiring the plugin is yours to do, and it is the next step.

    npx verbaly init      # config + locales/ + the integration to install
  3. Add the plugin

    vite.config.ts
    import verbaly from '@verbaly/vite';
    
    export default {
      plugins: [verbaly({ sourceLocale: 'es' })],
    };

    sourceLocale is the language you write in. If you do not list locales, every JSON catalog in locales/ is a language: drop an en.json or pt.json there and Verbaly picks them up. List locales and that list is the whole list, so a file you left behind is ignored.

  4. Write text, not keys

    src/app.ts
    import { t, setLocale } from 'virtual:verbaly';
    
    const saludo = t`Hola ${name}, tienes ${count} mensajes`;
    
    await setLocale('pt'); // lazy-loads pt chunk

    In dev, the plugin extracts messages live: your source catalog fills itself, other locales get "" placeholders, and the generated types keep keys and params typed.

  5. Translate and verify

    npx verbaly extract   # sync catalogs + types
    npx verbaly check     # exit 1 if anything is missing

What the virtual module exports

ExportDescription
tTranslate: 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
verbalyThe underlying instance (advanced use)
↑↓to moveEnterto open
Copied to clipboard