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.
Steps
Register the i18n plugin with multiple locales (as shown in the main guide).
Create a locale service that wraps
I18N.setLocaleand writes tolocalStorage: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>tolocaleService.changeLocale(locale)so choosing a language updates translations immediately.
Checklist
Reloading the page restores the last selected locale.
Changing the locale triggers translations everywhere without manual refresh (thanks to the
i18n:locale:changedevent).The UI defaults to the browser locale when no preference is stored.
2. Number and date formatting per locale
Goal: Display currency and dates using the active locale without writing custom formatting logic in components.
Steps
Inject
I18Nor use thedf/nfvalue converters provided by the plugin:<p>Balance: ${user.balance | nf:{ style: 'currency', currency: 'EUR' }}</p> <p>Joined: ${user.joined | df:{ dateStyle: 'long' }}</p>When the locale changes, converters re-run automatically.
Checklist
Switching between
enanddechanges decimal separators and currency symbols as expected.Dates use the correct ordering (month/day vs day/month).
No manual
Intl.NumberFormatcalls 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.
Steps
Configure the validation message provider to delegate to i18n:
import { I18nTranslationValidationMessageProvider } from '@aurelia/validation-i18n'; Aurelia.register(ValidationHtmlConfiguration.customize(options => { options.MessageProviderType = I18nTranslationValidationMessageProvider; }));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.
Checklist
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.
Steps
Configure
@aurelia/i18nwith a backend (for examplei18next-fetch-backend) so it can fetch JSON files as needed.In the route view-model, call
i18n.loadNamespacesbefore rendering:import { I18N } from '@aurelia/i18n'; import { resolve } from '@aurelia/kernel'; export class ReportsRoute { private readonly i18n = resolve(I18N); async canLoad() { await this.i18n.loadNamespaces('reports'); return true; } }Use keys like
reports:titleinside the route template. Once the namespace is loaded, translations render immediately.
Checklist
The network tab shows
/locales/{locale}/reports.jsononly 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.
5. Relative time formatting
Goal: Show human-friendly “time ago” strings that follow the active locale’s grammar.
Steps
Enable the relative-time formatter in the i18n options (it is on by default when using
@aurelia/i18n).In templates, use the
rtvalue converter:<p>Updated ${lastUpdated | rt}</p> <p>Expires ${expiresAt | rt:{ future: true }}</p>Customize thresholds and language by providing translations for
relativeTimein each locale file if the defaults are insufficient.
Checklist
Switching locale changes phrases like “just now” or “5 minutes ago” automatically.
Supplying the
{ future: true }option flips the wording to “in 2 hours,” etc.Dates in the past or future render correctly without manual math.
Reference material
Last updated
Was this helpful?