docs.getting-started
Getting started
Install the core and Angular packages and register provideRuntimeI18n().
Install
Install the core package and the Angular integration together — the Angular package expects a matching core version as a peer dependency:
npm i @ngx-runtime-i18n/angular @ngx-runtime-i18n/coreDirectory layout
Put one JSON catalog per language under src/public/i18n/:
your-app/
src/
public/
i18n/
en.json
hi.json
de.json
Catalogs are static assets, not compiled files. Serve them from /i18n/<lang>.json — the fetchCatalog function below assumes this path.
Register provideRuntimeI18n()
Add provideRuntimeI18n() to your application config with the supported languages, a fallback chain, and a fetchCatalog function that loads the JSON file for a given language:
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRuntimeI18n } from '@ngx-runtime-i18n/angular';
export const appConfig: ApplicationConfig = {
providers: [
provideRuntimeI18n(
{
defaultLang: 'en',
supported: ['en', 'hi', 'de'],
fallbacks: ['de'],
fetchCatalog: (lang, signal) =>
fetch(`/i18n/${lang}.json`, { signal }).then((r) => {
if (!r.ok) throw new Error(`Failed to load catalog: ${lang}`);
return r.json();
}),
onMissingKey: (key) => key,
},
{
localeLoaders: {
en: () => import('@angular/common/locales/global/en'),
hi: () => import('@angular/common/locales/global/hi'),
de: () => import('@angular/common/locales/global/de'),
},
options: {
autoDetect: true,
storageKey: '@ngx-runtime-i18n:lang',
cacheMode: 'storage',
cacheKeyPrefix: '@ngx-runtime-i18n:catalog:',
preferNavigatorBase: true,
},
},
),
],
};fallbacks sets the chain a missing key walks before onMissingKey runs — a key missing from hi.json falls back to de.json before onMissingKey returns the key itself.
Use translations in a component
I18nPipe covers templates. I18nService.t() covers component code that needs a translated string directly, and I18nService.lang()/ready() are signals you can read in an effect() or a template:
<!-- Template -->
<h1>{{ 'hello.user' | i18n:{ name: username } }}</h1>
<p>{{ 'cart.items' | i18n:{ count: items().length } }}</p>
<small>Fallback → {{ 'legacy.title' | i18n }}</small>// Component
import { Component, effect, inject, signal } from '@angular/core';
import { I18nPipe, I18nService } from '@ngx-runtime-i18n/angular';
@Component({
standalone: true,
imports: [I18nPipe],
template: `
<button (click)="switch('de')">Deutsch</button>
<div>{{ i18n.t('hello.user', { name: 'Ashwin' }) }}</div>
`,
})
export class ToolbarComponent {
i18n = inject(I18nService);
loaded = signal<string[]>([]);
constructor() {
effect(() => {
this.i18n.lang(); // subscribe to the signal
this.loaded.set(this.i18n.getLoadedLangs());
});
}
async switch(lang: string) {
if (this.i18n.ready()) await this.i18n.setLang(lang);
}
}Need RxJS instead of signals? Inject I18nCompatService for lang$, ready$, and t().
Next steps
The core concepts pages cover fallback chains and catalog caching in more depth. The recipes cover framework-specific integration patterns for PrimeNG and Angular Material.