Open-source i18n tooling for JavaScript & TypeScript
One translation model.Every framework.
Write messages where your UI happens. Keep source-string-first .po catalogs your translators can actually read. Ship the same runtime model across Next.js, TanStack Start, SolidStart, Waku, React Router, and Remix v3 — with a Rust core that ran a checked extract/update benchmark across a real-app-shaped 1,500-file corpus 12.99× faster than Lingui on the recorded machine-local run.
Quick install
pnpm add -D @palamedes/cli$ pmds extractConfig loaded from palamedes.yamlFound 312 files to extract from-> src/locales/en.po-> src/locales/de.po✓ Extracted 640 messages from 312 files (34ms)
$ pmds auditCatalog audit passed: 0 error(s), 2 warning(s), 0 infosrc/locales/de.po[Warning] missing-translation [de]: 28 entries[Warning] unused-context [de]: 1 entry
$ pmds report --fail-if-below 90Locale Translated Missing Completeen 640/640 0 100%de 612/640 28 95.6%es 598/640 42 93.4%✓ All locales above threshold
01 — Model
Your i18n setup should not splinter when your framework changes.
Most teams relearn internationalization with every migration: new runtime, new message IDs, new catalog quirks. Palamedes keeps the parts you touch every day stable — and lets the framework be the only thing that changes.
Write messages in place
Macro-style authoring next to your JSX. No message-ID bookkeeping, no separate dictionary files to keep in sync.
More →One identity model
Messages are identified by message + context — stable across refactors, frameworks, and years of catalog history.
More →One runtime call
getI18n() resolves the active instance everywhere: server components, client islands, backend request handlers.
More →02 — Workflow
The whole workflow, honestly small.
01
Write
src/*.tsx
t`…` macro in the component
02
Extract
pmds
one native command
03
Translate
.po catalog
source-string-first
04
Render
every framework
same runtime model
import { t, plural } from "@palamedes/core/macro"import { Trans } from "@palamedes/react"export function Booking({ seats }: { seats: number }) {return (<><h1>{t`Your trip to Lisbon`}</h1><p>{plural(seats, { one: "# seat left", other: "# seats left" })}</p><Trans>Free cancellation until <b>24 hours</b> before departure.</Trans></>)}
Messages live where the UI happens.
Rendered
The same component, in every locale, in every framework.
en-US
Your trip to Lisbon
Jul 12, 2026
de-DE
Deine Reise nach Lissabon
12. Juli 2026
es-ES
Tu viaje a Lisboa
12 jul 2026
03 — Proof
We don't ask you to trust a slogan. The repo shows the work.
Every framework/strategy combination is a real app, re-verified in CI through the same Playwright flow — with public demos where the hosting is ready. Every benchmark number links to a checked-in, re-runnable report.
| Framework | Cookiecookie | Routeroute | Subdomainsubdomain | TLDtld |
|---|---|---|---|---|
| Next.jsnextjs | ✓ verified provisioningsource | |||
| TanStack Starttanstack | ✓ verified provisioningsource | |||
| SolidStartsolidstart | ✓ verified provisioningsource | |||
| Wakuwaku | ✓ verified provisioningsource | |||
| React Routerreact-router | ✓ verified provisioningsource | |||
| Remix v3remix | ✓ verified provisioningsource | ✓ verified provisioningsource | ✓ verified provisioningsource |
● live demo · ◌ provisioning (#306) · ✓ CI browser-verified — all 24 apps run the same verification flow
Realistic corpus — 1,500 files across ~400k lines, 6,000 messages (median of 7 runs)
Machine-local run (darwin/arm64, Node v24.18.0, 2026-07-06), median of 7 runs — not a marketing average. Methodology →
04 — Scope
Palamedes deliberately owns less. It keeps the part of i18n you touch every day — your messages, your catalog, the runtime lookup — and hands everything framework-specific back to your framework.
Palamedes owns it — same on every framework
└─── one Rust core, everywhere ───┘
Your framework owns it — different on every stack
Switch frameworks, and only the bottom row changes. The top row is the same code you already wrote.
05 — Maintainer
Built from repeat experience, not a weekend take.
Palamedes is maintained by Sebastian Software GmbH. It is the third generation of source-string-first JavaScript i18n tooling from the same author — from gettext-style macro systems in qooxdoo to a full enterprise Lingui migration at Regrello (acquired by Salesforce in 2025). The lessons are written down as 16 ADRs before you depend on the tool.
06 — Packages
Small packages, one model.
You own the code. You run the commands. Every piece is a scoped npm package your repo controls.
@palamedes/cli
Extraction CLI for workflows and CI
npm →
@palamedes/core
App-facing i18n instance
npm →
@palamedes/runtime
Runtime bridge for transformed code
npm →
@palamedes/react
React translation components
npm →
@palamedes/solid
Solid translation components
npm →
@palamedes/vite-plugin
Recommended Vite entry point
npm →
@palamedes/next-plugin
Recommended Next.js entry point
npm →
The top-level palamedes name is reserved — the scoped packages above are the install path today.