Typed-i18n: Type-Safe Internationalization for TypeScript Apps
We’re excited to introduce @qzlcorp/typed-i18n — a zero-dependency, TypeScript-first i18n library designed for modern apps that need scalable, type-safe, and modular translations.
Inspired by modern i18n libraries, typed-i18n ensures that all your translation keys are validated at compile-time, catching errors early and keeping your app robust.
Demo

Watch how TypeScript catches translation key errors at compile time, ensuring type-safe i18n throughout your app.
Live Demo
🚀 View React Demo - Interactive demo showcasing dynamic module loading, locale switching, and type-safe translations.
Features
- Module-based architecture – Organize translations by feature/page for better code-splitting.
- Compile-time type safety – All translation keys are validated at build time.
- Shape validation – TypeScript ensures all locale files match the same structure.
- Modern API – Simple
t('key')syntax with namespace support. - Mutable locale – Change language dynamically with
setLocale(). - Fallback support – Automatic fallback to default locale for missing translations.
- Zero runtime dependencies – Lightweight and performant.
Installation
npm install @qzlcorp/typed-i18n
Quick Start
1. Create translation files
// locales/common/en.json
{
"hello": "Hello",
"goodbye": "Goodbye"
}
// locales/common/fr.json
{
"hello": "Bonjour",
"goodbye": "Au revoir"
}
2. Define modules and create i18n instance
import { defineModule, createI18n } from '@qzlcorp/typed-i18n';
import commonEn from './locales/common/en.json';
import commonFr from './locales/common/fr.json';
// ⚠️ Provide explicit reference type for compile-time validation
const common = defineModule('common')<typeof commonEn>({
en: commonEn,
fr: commonFr
});
const i18n = createI18n({
locale: 'en',
fallbackLocale: 'en',
modules: { common }
});
3. Use translations
i18n.t('common.hello'); // "Hello"
// Change locale dynamically
i18n.setLocale('fr');
i18n.t('common.hello'); // "Bonjour"
// Interpolation
i18n.t('common.greeting', { name: 'John' }); // Supports {{name}} in JSON
Advanced Usage
Multiple Modules (Code-Splitting)
const dashboard = defineModule('dashboard')<typeof dashboardEn>({
en: dashboardEn,
fr: dashboardFr
});
const i18n2 = i18n.addModule(dashboard); // Returns new typed instance
i18n2.t('dashboard.title'); // ✅ Fully typed
Dynamic Module Loading (React)
const dashboardModule = defineModule('dashboard')<typeof dashboardEn>({
en: await import('./locales/dashboard/en.json'),
fr: await import('./locales/dashboard/fr.json')
});
const i18n3 = i18n.addModule(dashboardModule);
⚠️ Important: Always use the returned instance from
addModuleto preserve type safety. Original instance will still work at runtime but loses typing for new modules.
Nested Keys
{
"dashboard": {
"stats": {
"clicks": "{{count}} clicks"
}
}
}
i18n.t('common.dashboard.stats.clicks', { count: 5 }); // "5 clicks"
Get Available Locales
i18n.getLocales(); // ['en', 'fr']
Fallback Locale
const i18n = createI18n({
locale: 'de', // German not available
fallbackLocale: 'en',
modules: { common }
});
i18n.t('common.hello'); // Falls back to "Hello"
API Reference
defineModule(namespace)<Ref>(locales)
- Creates a typed translation module.
- ⚠️ Must provide explicit reference type for type-safe cross-locale validation.
createI18n(options)
locale: current localefallbackLocale: optional fallbackmodules: translation modules
Returns an instance with:
t(key, params?): translatesetLocale(locale): change localegetLocale(): get current localeaddModule(module): add module dynamically, returns new typed instancegetLocales(): get all available locales
TypeScript Tips
Always provide explicit reference type when defining modules to enable compile-time validation:
const common = defineModule('common')<typeof enJson>({
en: enJson,
fr: frJson
});
Without it, TypeScript may infer a loose union type and mismatched locale structures could pass unnoticed.
React Integration
Use @qzlcorp/typed-i18n-react for first-class React support:
<I18nProvider i18n={i18n}>
<App />
</I18nProvider>
const { t } = useTranslation<I18nModules>();
t('common.hello'); // ✅ compile-time checked
Support & License
- License: MIT
- Support: Buy Me a Coffee
Typed-i18n is your modern, type-safe, and scalable solution for managing translations in TypeScript projects.
Links