Outcome Recipes
Outcome-oriented scenarios for @aurelia/i18n covering locale switching, formatting, and validation integration.
1. Locale switcher that persists the user’s preference
Goal: Let the user pick a language, apply it immediately, and remember the choice across sessions.
Register the i18n plugin with multiple locales (as shown in the main guide).
Create a locale service that wraps I18N.setLocale and writes to localStorage:
import { I18N } from '@aurelia/i18n';
import { resolve } from '@aurelia/kernel';
export class LocaleService {
private readonly i18n = resolve(I18N);
private readonly storageKey = 'preferred-locale';
constructor() {
const saved = localStorage.getItem(this.storageKey);
if (saved) {
void this.i18n.setLocale(saved);
}
}
async changeLocale(locale: string) {
await this.i18n.setLocale(locale);
localStorage.setItem(this.storageKey, locale);
}
}
Bind a <select> to localeService.changeLocale(locale) so choosing a language updates translations immediately.
Reloading the page restores the last selected locale.
Changing the locale triggers translations everywhere without manual refresh (thanks to the i18n:locale:changed event).
The UI defaults to the browser locale when no preference is stored.
Goal: Display currency and dates using the active locale without writing custom formatting logic in components.
Inject I18N or use the df/nf value converters provided by the plugin:
When the locale changes, converters re-run automatically.
Switching between en and de changes decimal separators and currency symbols as expected.
Dates use the correct ordering (month/day vs day/month).
No manual Intl.NumberFormat calls are needed in view-models.
3. Validation messages that respect the current locale
Goal: Integrate @aurelia/i18n with the validation plugin so error messages translate automatically.
Configure the validation message provider to delegate to i18n using ValidationI18nConfiguration:
Provide translations for the built-in validation keys (for example, validation.required).
When the locale service changes languages, validation errors re-render with the translated message.
Required-field errors display in English by default and in German after switching locales.
Custom rule messages use translated strings from your resource files.
No manual string concatenation is needed in validators or components.
4. Lazy-load namespaces per route
Goal: Keep initial bundles small by loading translation namespaces on demand when a route activates.
Configure @aurelia/i18n with a backend (for example i18next-fetch-backend) so it can fetch JSON files as needed.
In the route view-model, call i18n.i18next.loadNamespaces before rendering (accessing the underlying i18next instance):
Use keys like reports:title inside the route template. Once the namespace is loaded, translations render immediately.
The network tab shows /locales/{locale}/reports.json only when the route loads.
Subsequent navigations reuse the cached namespace (unless you opt in to reloading).
Users do not see missing key warnings because namespaces load before the view activates.
Goal: Show human-friendly “time ago” strings that follow the active locale’s grammar.
Enable the relative-time formatter in the i18n options (it is on by default when using @aurelia/i18n).
In templates, use the rt value converter:
Customize thresholds and language by providing translations for relativeTime in each locale file if the defaults are insufficient.
Switching locale changes phrases like "just now" or "5 minutes ago" automatically.
Past dates render as "X ago" and future dates render as "in X" automatically based on the date value.
Dates in the past or future render correctly without manual math.
Reference material
Last updated