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.
- 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
- 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] - 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) - 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 - 05
Translate
Open the German catalog and fill in the translated string.
# src/locales/de.po msgid "Welcome to Palamedes" msgstr "Willkommen bei Palamedes"
- 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 →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 →