Internationalization
The @effuse/i18n package provides type-safe internationalization with reactive locale switching.
Setup
import { createI18n } from '@effuse/i18n';
const translations = {
en: {
greeting: 'Hello, {{name}}!',
app: {
title: 'My App',
},
items: {
count_one: '{{count}} item',
count_other: '{{count}} items',
},
},
es: {
greeting: '¡Hola, {{name}}!',
app: {
title: 'Mi Aplicación',
},
items: {
count_one: '{{count}} elemento',
count_other: '{{count}} elementos',
},
},
};
createI18n({
defaultLocale: 'en',
fallbackLocale: 'en',
translations,
detectLocale: true,
persistLocale: true,
});
Type-Safe Translations
For full type safety, use defineTranslations and pass the inferred type to createI18n.
import { defineTranslations, createI18n } from '@effuse/i18n';
const en = defineTranslations({
welcome: 'Welcome back, {{name}}!',
actions: {
save: 'Save Changes',
},
});
const i18n = createI18n<typeof en>({
defaultLocale: 'en',
translations: { en },
});
Using Translations
Use the useTranslation hook in your components:
import { define, computed, signal } from '@effuse/core';
import { useTranslation } from '@effuse/i18n';
const Greeting = define({
script: () => {
const { t, locale, setLocale } = useTranslation();
const userName = signal('World');
return {
greeting: computed(() => t('greeting', { name: userName.value })),
toggleLocale: () => setLocale(locale.value === 'en' ? 'es' : 'en'),
};
},
template: ({ greeting, toggleLocale }) => (
<div>
<p>{greeting}</p>
<button onClick={toggleLocale}>Change Language</button>
</div>
),
});
Nested Keys
Access nested translations using dot notation:
const { t } = useTranslation();
t('app.title'); // "My App"
Variable Interpolation
Pass variables using the {{variable}} syntax:
t('greeting', { name: 'Developer' }); // "Hello, Developer!"
Pluralization
Define plural forms with _one, _other, _zero, _two, _few, _many suffixes:
// In translations
items: {
count_one: '{{count}} item',
count_other: '{{count}} items',
}
// Usage
t('items.count', { count: 1 }); // "1 item"
t('items.count', { count: 5 }); // "5 items"
API Reference
createI18n(options)
Initializes the i18n instance. Call once at app startup.
| Option | Type | Default | Description |
|---|---|---|---|
defaultLocale | string | — | The default locale to use. |
fallbackLocale | string | — | Fallback when translation is missing. |
translations | Record<string, T> | — | Translation objects keyed by locale. |
detectLocale | boolean | false | Auto-detect locale from browser. |
persistLocale | boolean | false | Persist locale to localStorage. |
useTranslation()
Returns translation utilities for use in components.
| Property | Type | Description |
|---|---|---|
t | (key: string, params?) => string | Translate a key with optional params. |
locale | Signal<string> | Reactive current locale signal. |
setLocale | (locale: string) => Promise<void> | Change the current locale. |
hasKey | (key: string) => boolean | Check if a translation key exists. |
getI18n()
Returns the global i18n instance for direct access outside components.
import { getI18n } from '@effuse/i18n';
const i18n = getI18n();
i18n.setLocale('es');
Next Steps