
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
@qzlcorp/typed-i18n-react
Advanced tools
React bindings for @qzlcorp/typed-i18n with full TypeScript support.

See how TypeScript ensures type-safe translations in React apps with full autocomplete and compile-time validation.
🚀 View Live Demo - See dynamic module loading, locale switching, and type-safe translations in action.
pnpm add @qzlcorp/typed-i18n @qzlcorp/typed-i18n-react
To get static type errors for incorrect translation keys you MUST pass your module type (or use a pre-bound wrapper hook). Without the generic, t() falls back to a loose pattern like ${string}.${string} and invalid keys will not error at compile time.
// i18n.ts
const app = defineModule('app')<typeof enApp>({ en: enApp, fr: frApp });
export const i18n = createI18n({ locale: 'en', fallbackLocale: 'en', modules: { app } });
export type I18nModules = { app: typeof app };
// Component: GOOD (strict key union)
const { t } = useTranslation<I18nModules>();
t('app.title'); // OK
t('app.missing'); // ❌ Type error at compile time
// Component: WEAK (no generic) – do NOT use this form if you want key checking
const { t: tLoose } = useTranslation();
tLoose('app.missing'); // ✅ Compiles (no static safety)
Recommended ergonomic wrapper so you never forget the generic:
// i18n-hooks.ts
export const useAppTranslation = () => useTranslation<I18nModules>();
export const useAppLocale = () => useLocale<I18nModules>();
export const useAppI18n = () => useI18n<I18nModules>();
// Component
const { t } = useAppTranslation();
If you later add modules dynamically, you can widen the type:
const dashboard = defineModule('dashboard')<typeof enDashboard>({ en: enDashboard });
const updated = useAppI18n().addModule(dashboard);
// For immediate strict typing in this scope:
const { t: tWithDashboard } = useTranslation<I18nModules & { dashboard: typeof dashboard }>();
Load only the namespaces a feature needs by passing a modules object to useTranslation. Each module is registered once and cached by namespace, so repeated renders stay cheap.
import { dashboardModule } from "./modules/dashboard";
const { t } = useTranslation<
I18nModules,
{ dashboard: typeof dashboardModule }
>({
dashboard: dashboardModule,
});
console.log(t("dashboard.title"));
Keep the modules object stable (imported or memoized) to avoid unnecessary effect churn. After the hook registers a module, the provider widens the shared i18n instance so other components can access the new namespace without reloading it.
import { createI18n, defineModule } from '@qzlcorp/typed-i18n';
import { I18nProvider } from '@qzlcorp/typed-i18n-react';
// Define your modules
const common = defineModule('common')<typeof enCommon>({
en: enCommon,
fr: frCommon,
});
// Create i18n instance
const i18n = createI18n({
locale: 'en',
fallbackLocale: 'en',
modules: { common },
});
// Wrap your app
function App() {
return (
<I18nProvider i18n={i18n}>
<YourApp />
</I18nProvider>
);
}
import { useTranslation, useLocale } from '@qzlcorp/typed-i18n-react';
function MyComponent() {
const { t, locale } = useTranslation();
const { setLocale, locales } = useLocale();
return (
<div>
<h1>{t('common.hello')}</h1>
<p>Current locale: {locale}</p>
<select value={locale} onChange={(e) => setLocale(e.target.value)}>
{locales.map((loc) => (
<option key={loc} value={loc}>{loc}</option>
))}
</select>
</div>
);
}
I18nProviderProvider component that makes i18n instance available to all child components.
Props:
i18n - The i18n instance created with createI18n()children - React childrenuseTranslation()Returns translation function and current locale.
Returns:
t(key, params?) - Translate function with parameter interpolationt(key, options?) - Translate function with options (supports returnObjects)locale - Current active localefunction MyComponent() {
const { t, locale } = useTranslation();
// Simple translation
const title = t('common.title');
// With parameters
const greeting = t('common.greeting', { name: 'React' });
// Get nested objects (i18next compatible)
const config = t('app.config', { returnObjects: true });
// Both params and returnObjects
const data = t('dashboard.stats', {
params: { count: 5 },
returnObjects: false
});
return <div>{title}</div>;
}
⚠️ Pass your module type generic (e.g. useTranslation<I18nModules>()) for strict key unions.
Optional argument: useTranslation<I18nModules, ExtraModules>({ ...ExtraModules }) dynamically registers more namespaces (e.g. page-level modules) and widens t to cover them.
useLocale()Returns locale management functions.
Returns:
locale - Current active localesetLocale(locale) - Change locale (triggers re-renders)locales - Array of all available localesuseI18n()Returns the full i18n instance for advanced use cases.
Returns:
I18nInstance with all methods<Trans> ComponentComponent for translating JSX with embedded HTML tags and React components. Safer than dangerouslySetInnerHTML - parses translation strings and builds React elements.
Props:
i18nKey - Translation key (optional - if not provided, uses children)children - Can be used as the translation source instead of i18nKey (optional)values - Interpolation parameters (optional)components - Custom React components to use for tags (optional)defaults - Include default HTML components like <strong>, <em>, etc. (default: true)Note: Either i18nKey or children should be provided. If both are present, i18nKey takes precedence.
Default supported tags (when defaults={true}):
<strong>, <b> - Bold text<em>, <i> - Italic text<u> - Underlined text<br/> - Line break<p>, <span> - Block/inline containers// Translation JSON
{
"welcome": "Hello <strong>{{name}}</strong>!",
"action": "Click <link>here</link> to continue"
}
// Using i18nKey (recommended for externalized translations)
<Trans i18nKey="common.welcome" values={{ name: "John" }} />
// Renders: Hello <strong>John</strong>!
// Using children as translation source (inline translations)
<Trans values={{ name: "John" }}>
Hello <strong>{{name}}</strong>!
</Trans>
// Renders: Hello <strong>John</strong>!
// Using children with JSX elements (preserves attributes)
const description = (
<>
Check the <a href="/docs">documentation</a> for more info
</>
);
<Trans components={{ a: <a /> }}>{description}</Trans>
// Renders: Check the <a href="/docs">documentation</a> for more info
// Custom components with i18nKey
<Trans
i18nKey="common.action"
components={{
link: <a href="/next" className="btn" />
}}
/>
// Renders: Click <a href="/next" class="btn">here</a> to continue
// Custom components with children
<Trans components={{ link: <a href="/next" className="btn" /> }}>
Click <link>here</link> to continue
</Trans>
// Renders: Click <a href="/next" class="btn">here</a> to continue
// Multiple tags
// Translation: "This is <strong>bold</strong> and <em>italic</em>"
<Trans i18nKey="common.formatted" />
// Nested tags
// Translation: "Text with <strong>bold and <em>italic</em> nested</strong>"
<Trans i18nKey="common.nested" />
// Disable default components
<Trans i18nKey="common.text" defaults={false} components={{ custom: <CustomComponent /> }} />
Safety note: The <Trans> component does NOT use dangerouslySetInnerHTML. It safely parses the translation string and builds React elements using React.cloneElement(), preventing XSS vulnerabilities.
✅ Automatic Re-renders - Components re-render when locale changes
✅ Full Type Safety - All translation keys are typed
✅ Trans Component - Safe HTML/JSX translation without XSS risks
✅ React 18 Ready - Built with modern React patterns
✅ Small Bundle - Minimal overhead
✅ Tree Shakeable - Only import what you use
MIT © Q.Z.L Corp.
FAQs
React bindings for @qzlcorp/typed-i18n
We found that @qzlcorp/typed-i18n-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.