Skip to content

Quickstart

First working translation in 5 minutes.

One translated component, one extraction run, one .po file, one runtime instance. No message IDs to invent, no dictionary files to maintain.

01 — Steps

The full local loop.

writeextracttranslaterenderrepeat

Honest note

Install the scoped @palamedes/* packages. The top-level palamedes and create-palamedes names are reserved for a future one-command setup and are not the entry point today.

  1. 01

    Install

    Core, runtime, host adapter, and the build plugin — plus the CLI as a dev dependency.

    pnpm add @palamedes/core @palamedes/react @palamedes/runtime @palamedes/vite-plugin
    pnpm add -D @palamedes/cli @vitejs/plugin-react
  2. 02

    Configure

    One YAML file declares your locales and where catalogs live.

    # palamedes.yaml
    locales: [en, de]
    source-locale: en
    catalogs:
      - path: src/locales/{locale}
        include: [src]
  3. 03

    Wire the plugin & runtime

    The Vite plugin handles the macro transform; the runtime holds the active i18n instance.

    // vite.config.ts
    import { palamedes } from "@palamedes/vite-plugin"
    export default defineConfig({ plugins: [palamedes(), react()] })
    
    // src/i18n.ts
    import { createI18n } from "@palamedes/core"
    import { setClientI18n } from "@palamedes/runtime"
    
    export const i18n = createI18n()
    setClientI18n(i18n)
  4. 04

    Write & extract

    Author the message in your component, then run one command — it creates src/locales/en.po and de.po.

    // src/App.tsx
    import { t } from "@palamedes/core/macro"
    export const App = () => <h1>{t`Welcome to Palamedes`}</h1>
    
    $ pmds extract
  5. 05

    Translate

    Open the German catalog and fill in the translated string.

    # src/locales/de.po
    msgid "Welcome to Palamedes"
    msgstr "Willkommen bei Palamedes"
  6. 06

    Load & see it render

    Load the catalogs, activate a locale, and run the dev server — the page now renders “Willkommen bei Palamedes”. That is the full local loop: transform, extraction, catalog, runtime.

    // src/main.tsx
    import { i18n } from "./i18n"
    import { messages as enMessages } from "./locales/en.po"
    import { messages as deMessages } from "./locales/de.po"
    
    i18n.load("en", enMessages)
    i18n.load("de", deMessages)
    i18n.activate("de")
    
    $ pnpm dev

02 — Next

Where to go from here

Plurals, dates & currency

ICU MessageFormat with authoring diagnostics that catch mistakes at extract time.

More →

Pick a locale strategy

Cookie, route, subdomain, or TLD — with a live demo for each, in your framework.

More →

Localize your backend

Request-local i18n for Hono and Express from the same catalogs.

More →

Migrating from Lingui?

A step-by-step playbook. Source-string-first .po catalogs are often reusable after an extraction pass; explicit-ID setups need cleanup.

More →

Something broke?

The troubleshooting guide covers the common setup failures with exact error messages.

More →

Using an AI assistant?

Point it at llms.txt — the whole API surface in one machine-readable file.

More →

Stuck? The maintainer reads every issue.