Framework-independent TypeScript foundations for strongly typed internationalization.
i18n-ts gives a project one translation contract shared by every language, lazy language loading, a portable JSON bundle format and a machine-readable project configuration. It has no runtime dependencies and no React, DOM or application-specific coupling.
Status:
0.0.1-alpha.0. Public APIs and JSON formats may change before1.0.0.
| Project | Responsibility |
|---|---|
@wads.dev/i18n-ts |
Framework-independent contracts, language loading, project configuration and portable bundles. |
@wads.dev/i18n-react |
React Provider, hooks and rich translation rendering built on i18n-ts. |
@wads.dev/i18n-html |
DOM bindings and static HTML translation-reference discovery built on i18n-ts. |
@wads.dev/i18n-editor |
Local editor for inspecting and changing bundles and, incrementally, regenerating project files. |
Use only the packages required by the project. The core remains independent of React and of the Editor.
Translation files are application code: their structure changes, keys move, languages grow and mistakes should fail during development rather than reach users. This package keeps that foundation small and explicit:
- TypeScript verifies that locales implement compatible structures.
- Dynamic translations keep the same function signature in every language.
- Languages can be loaded lazily and their resulting trees are immutable.
- A JSON bundle lets editors and tools work without importing the application runtime.
i18n.config.jsonexplains project structure to CLIs, editors and AI agents.
Platform integrations are separate. React support belongs to @wads.dev/i18n-react, DOM/HTML support belongs to @wads.dev/i18n-html, and translation editing belongs to @wads.dev/i18n-editor. The same contracts can support future Swift and Kotlin runtimes.
Install the current alpha explicitly:
npm install @wads.dev/i18n-ts@alphaAfter a stable release:
npm install @wads.dev/i18n-tsCreate the contract shared by all locales:
import type { Translation } from '@wads.dev/i18n-ts'
export interface AppTranslation extends Translation {
commons: {
continue: string
}
cart: {
itemCount: (count: number) => string
}
}Implement it once per language:
import type { AppTranslation } from '../base.js'
const en: AppTranslation = {
commons: { continue: 'Continue' },
cart: { itemCount: (count) => `${count} items` },
}
export default enimport type { AppTranslation } from '../base.js'
const pt: AppTranslation = {
commons: { continue: 'Continuar' },
cart: { itemCount: (count) => `${count} itens` },
}
export default ptThe compiler now catches missing keys, incompatible nested structures and different function parameters.
import { loadLanguage, type AvailableLangs } from '@wads.dev/i18n-ts'
import type { AppTranslation } from './base.js'
const languages = {
en: {
name: 'English',
short: 'EN',
locale: 'en-US',
lang: () => import('./translations/en.js'),
},
pt: {
name: 'Português',
short: 'PT',
locale: 'pt-BR',
lang: () => import('./translations/pt.js'),
},
} satisfies AvailableLangs<'en' | 'pt', AppTranslation>
const selected = await loadLanguage(languages, 'en', 'pt-BR')
selected.lang.commons.continueloadLanguage selects an available language, loads it when necessary and deeply freezes the translation tree. Selection accepts an explicit language and otherwise falls back through the environment locale to the configured default.
Add i18n.config.json to the repository root. The application runtime does not need this file: it exists primarily to describe the project to AI agents and to @wads.dev/i18n-editor. Its catalogFile points to the project-root-relative TypeScript module that exports Langs, allowing the Editor to generate a missing bundle automatically.
The Editor uses it to understand which key segments represent modules or features, how object names map to real folders, where root translations belong and which files should be regenerated after editing. This keeps structural knowledge outside application code.
See Project configuration for the complete schema, replacers, aliases and path-resolution examples.
The bundle is a portable, JSON-safe snapshot of the complete translation catalog, including language metadata, values and updatedAt. It separates translation review from the source-code layout.
npx i18n-bundle \
--input src/i18n/index.ts \
--config i18n.config.json \
--output i18n.bundle.jsonThe bundle can be opened by @wads.dev/i18n-editor or shared with translators without giving them the repository or asking them to navigate many TypeScript files. After review, the edited bundle can return to the development team and be redistributed into the configured project structure. The resulting source changes remain ordinary files, so the Git diff becomes the final safety and review layer before merge.
The alpha currently supports bundle generation, visualization and in-memory editing. Regenerating the complete TypeScript file tree from a reviewed bundle is the next Editor/CLI integration step; the configuration and export plan already describe those destinations.
See Bundle and translation-review workflow for responsibilities, handoff stages and validation guidance.
The input module must export Langs. The command requires TypeScript in the consuming project when the catalog is written in TypeScript. When --config is supplied, a normalized i18n.config.json is copied beside the generated bundle so a separately served editor can load it automatically.
Bundle APIs are available separately:
import {
assertBundle,
parseBundle,
type I18nBundle,
} from '@wads.dev/i18n-ts/bundle'Functions inside translation trees are serialized as descriptors so editors can inspect them without executing application code.
The published package includes portable instructions under AI/. Projects can direct agents to these files instead of copying i18n instructions into every repository:
node_modules/@wads.dev/i18n-ts/AI/ARCHITECTURE.md
node_modules/@wads.dev/i18n-ts/AI/PROMPT_TRANSLATE_FILE.md
node_modules/@wads.dev/i18n-ts/AI/PROMPT_CREATE_TRANSLATION_KEY.md
node_modules/@wads.dev/i18n-ts/AI/PROMPT_UPDATE_TRANSLATION.md
node_modules/@wads.dev/i18n-ts/AI/PROMPT_ADD_LANG_TO_PROJECT.md
The guides begin by reading the host repository instructions and i18n.config.json; they do not assume React or a fixed project layout.
| Import | Responsibility |
|---|---|
@wads.dev/i18n-ts |
Runtime types and loadLanguage. |
@wads.dev/i18n-ts/bundle |
Portable bundle types, validation and serialization. |
@wads.dev/i18n-ts/config |
Project configuration types, defaults and normalization. |
The root import deliberately excludes editor and CLI concerns.
npm install
npm run check
npm run build
npm pack --dry-runThe source is entirely TypeScript. The build produces ESM JavaScript and declaration files in dist/.
MIT