Typed React bindings for translation catalogs built with @wads.dev/i18n-ts.
The package creates an isolated translation runtime containing a Provider and a selector-based hook. It also renders typed translation tokens as React nodes. It does not own project translations, storage or platform-specific locale detection.
Status:
0.0.1-alpha.0. Public APIs 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. This repository. |
@wads.dev/i18n-editor |
Local editor for inspecting and changing bundles and, incrementally, regenerating project files. |
React applications normally install i18n-ts and i18n-react. The Editor is an optional development tool and does not become part of the application runtime.
npm install @wads.dev/i18n-ts@alpha @wads.dev/i18n-react@alphaReact is a peer dependency. The minimum supported version is 16.8.0, where Hooks were introduced. The distributed JavaScript uses createElement rather than the newer automatic JSX runtime, so the package does not force a newer React version on consuming projects.
Keep the reusable package separate from the application's catalog and bootstrap behavior:
import { createTranslationRuntime } from '@wads.dev/i18n-react'
import type { AvailableLangs, Translation } from '@wads.dev/i18n-ts'
interface AppTranslation extends Translation {
commons: {
continue: string
}
cart: {
itemCount: (count: number) => string
}
}
type AppLanguage = 'en' | 'pt'
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<AppLanguage, AppTranslation>
export const { TranslationProvider, useTranslation } =
createTranslationRuntime<AppLanguage, AppTranslation>({
availableLangs: languages,
defaultLang: 'en',
onLanguageLoaded: (language) => {
console.info(`Loaded ${language.locale}`)
},
})Render the Provider at the application boundary:
<TranslationProvider>
<App />
</TranslationProvider>Select the smallest useful scope:
const { scoped: cart } = useTranslation((translation) => translation.cart)
cart.itemCount(3)Calling the hook without a selector returns the complete deeply readonly translation tree:
const { scoped: translation, current, available, saved, setLanguage } = useTranslation()useTranslation throws a descriptive error when called outside its matching Provider.
const { setLanguage } = useTranslation()
setLanguage('pt', true)Passing undefined asks @wads.dev/i18n-ts to select from the environment locale and configured default. The current alpha keeps the selected value in Provider state; persistence is intentionally the consuming application's responsibility.
withRender turns a %token% template into a typed renderable translation:
import { withRender } from '@wads.dev/i18n-react'
const terms = withRender(
'I accept the %terms% and %privacy%.',
{
terms: 'Terms of Use',
privacy: 'Privacy Policy',
},
{
terms: (text) => <a href="/terms">{text}</a>,
privacy: (text) => <a href="/privacy">{text}</a>,
},
)Token names are inferred from the provided record and remain compatible with the TranslationRender contract from @wads.dev/i18n-ts.
Every call to createTranslationRuntime creates a distinct React Context. Independent applications, previews or embedded trees can therefore use different catalogs without a global singleton.
createTranslationRuntime(options)— creates a typed Provider and hook.withRender(template, tokens, renders?)— creates typed rich/tokenized text.CreateTranslationRuntimeOptions— runtime factory options.TranslationRuntime— factory result.TranslationContext,TranslationSelectorandUseTranslationResult— integration types.
- Translation contracts and language loading belong to
@wads.dev/i18n-ts. - React Context, hooks and React-node rendering belong here.
- Catalog composition, selected-language persistence and application bootstrap remain in the consuming project.
- Bundle editing and source-file generation belong to
@wads.dev/i18n-editor.
npm install
npm run check
npm run build
npm pack --dry-runThe package publishes ESM JavaScript and TypeScript declarations from dist/.
MIT