Introduction
Compile-time i18n for JavaScript, TypeScript, React, and beyond
Welcome to SayKit
SayKit is a framework-agnostic internationalisation toolkit built around compile-time message extraction, typed configuration, and small runtime primitives.
You author messages inline with tagged templates or JSX. A build-tool plugin extracts them to translation files and rewrites your source to small runtime calls. At runtime, a tiny Say instance formats those messages using ICU MessageFormat, with plurals, ordinals, and select, against whichever locale you've activated.
SayKit is in active development (pre-1.0). Public APIs may change before the stable 1.0 release.
Why SayKit?
Author in code
Write messages inline with tagged templates or JSX. No keys, no string tables, no juggling translation IDs by hand.
Compile-time extraction
A Babel or unplugin transform extracts messages during build. Your source stays small and ergonomic.
ICU MessageFormat
Full support for plurals, ordinals, and select using the ICU standard the rest of the i18n world already uses.
Framework agnostic
A small core runtime, plus adapters for React, Next.js, TanStack Start, Carbon, Expo, and anything else with a build plugin.
Typed config
A Zod-validated saykit.config.ts file defines locales, buckets, formatters, and transformers, all under TypeScript.
Plain translation files
Import .po files (or your own format) directly. Bundlers turn them into JS catalogues, no shipped extractor, no extra runtime.
How it works
SayKit has four moving parts that wire up like this:
- You author messages with
say`...`or<Say>...</Say>in source files. - The
saykitCLI extracts them into per-locale files (src/locales/en.po,fr.po, …). - Translators (or you) fill in the translations in those files.
- At build time a SayKit plugin transforms your source, macros become small runtime calls, and
import en from './locales/en.po'becomes a plain JS object. - At runtime, a
Sayinstance picks a locale and formats messages on demand.
There's no SaaS, no proxy, no extra service. Translation files live in your repo, next to the code they describe.