Skip to content

hero.tagline

Runtime i18n for Angular, built for everyone.

Signals-first and SSR-safe: per-key fallback chains, a tiny ICU-lite formatter, and hydration that never mutates the DOM before Angular is stable.

features.grid

What you get out of the box

Fallback chains

Configure fallbacks as an ordered list and lookups run active language, then each fallback in turn, then the default language. Missing keys reach onMissingKey after a single dev-mode warning.

ICU-lite formatting

A small, dependency-free formatter handles interpolation and plural blocks (one, other, and exact matches like =0). It covers common cases without a full ICU MessageFormat implementation.

Type-safe keys

Declare a catalog schema once via module augmentation and t(), the pipe, and the RxJS compat service all narrow to valid keys and required params. Without a declaration, t() still accepts a plain string.

TransferState SSR

provideRuntimeI18nSsr() seeds the same TransferState keys the client reads on boot, so the browser reuses the server-rendered catalog instead of fetching it again. No catalog fetch runs before Angular is stable.

Catalog caching modes

Choose none to keep only the active fallback chain in memory, memory to cache every catalog for the session, or storage to hydrate from localStorage and revalidate in the background. Storage access never runs on the server.

DevTools bridge

In dev mode, the service posts structured window.postMessage events for state, translations, and missing keys, so extensions and custom panels can observe language changes as they happen. Stripped out of production builds.

hero.code-showcase

Set it up once, translate anywhere

provideRuntimeI18n() wires the service, pipe, and locale data into your app config. Templates then read translations through the i18n pipe.

// 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,
        },
      }
    ),
  ],
};
<!-- Template -->
<h1>{{ 'hello.user' | i18n:{ name: username } }}</h1>
<p>{{ 'cart.items' | i18n:{ count: items().length } }}</p>
<small>Fallback → {{ 'legacy.title' | i18n }}</small>

packages.matrix

Six packages, one release train

Core and Angular ship the runtime. PrimeNG, Material, the CLI, and the ng add schematic are optional and versioned together.

@ngx-runtime-i18n/core

Framework-agnostic primitives: the ICU-lite formatter and shared types.

Published on npm

@ngx-runtime-i18n/angular

The Angular wrapper: signals, an SSR-safe service, and pipes.

Published on npm

@ngx-runtime-i18n/primeng

Optional PrimeNG adapter that mirrors runtime language changes.

Published on npm

@ngx-runtime-i18n/material

Optional Angular Material adapter for paginator, sort, stepper, and datepicker labels.

Published on npm

@ngx-runtime-i18n/schematics

An ng add schematic that scaffolds provideRuntimeI18n() into an existing project.

Published on npm

@ngx-runtime-i18n/cli

A CLI for extracting translation keys from source and validating catalogs.

Published on npm

compare.teaser

How this compares

See how fallback chains, caching, and SSR support compare against ngx-translate, transloco, and Angular's built-in i18n on the compare page.