Skip to main content
Jet provides comprehensive internationalization (i18n) using Transloco, with built-in support for multiple languages, right-to-left (RTL) layouts, and dynamic font loading.

Overview

The i18n system is configured to support English (LTR) and Arabic (RTL) out of the box, with an extensible architecture for adding more languages.

Configuration

Transloco is configured in src/app/app.config.ts:58:
provideTransloco({
  config: {
    availableLangs: LANGUAGE_OPTIONS.map(
      (languageOption: LanguageOption): Language => languageOption.value,
    ),
    defaultLang: DEFAULT_LANGUAGE_OPTION.value,
    prodMode: !isDevMode(),
    reRenderOnLangChange: true,
  },
  loader: TranslocoHttpLoader,
})

Global Configuration

The transloco.config.ts file defines where translation files are stored:
const config: TranslocoGlobalConfig = {
  keysManager: { output: 'public/i18n/', sort: true, unflat: true },
  langs: ['ar', 'en'],
  rootTranslationsPath: 'public/i18n/',
};

Translation Loader

Translations are loaded dynamically via HTTP (src/app/transloco-loader.ts:8):
@Injectable({ providedIn: 'root' })
export class TranslocoHttpLoader implements TranslocoLoader {
  readonly #httpClient = inject(HttpClient);
  readonly #loggerService = inject(LoggerService);

  public getTranslation(language: Language): Observable<Translation> {
    return this.#httpClient.get<Translation>(`/i18n/${language}.json`).pipe(
      catchError((error: Error): Observable<Translation> => {
        this.#loggerService.logError(error);
        const emptyTranslation: Translation = {};
        return of(emptyTranslation);
      }),
    );
  }
}
Translation files are served from /public/i18n/ as static JSON files, enabling efficient caching and lazy loading.

Language Options

Languages are defined in src/app/constants/language-options.constant.ts:4:
export const LANGUAGE_OPTIONS: LanguageOption[] = [
  {
    directionality: 'ltr',
    fontPair: 'ns-bg',
    fontPairUrl:
      'https://fonts.googleapis.com/css2?display=swap&family=Bricolage+Grotesque:opsz,[email protected],200..800&family=Noto+Sans:[email protected]',
    icon: 'translate',
    nameKey: marker('constants.english'),
    value: 'en',
  },
  {
    directionality: 'rtl',
    fontPair: 'nsa-nsa',
    fontPairUrl:
      'https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans+Arabic:[email protected]',
    icon: 'translate',
    nameKey: marker('constants.arabic'),
    value: 'ar',
  },
];

Language Configuration Properties

directionality
'ltr' | 'rtl'
Text direction for the language
fontPair
string
CSS class identifier for the font combination
fontPairUrl
string
Google Fonts URL for loading the appropriate fonts
icon
string
Material icon identifier for the language selector
nameKey
string
Translation key for the language name
value
Language
Language code (e.g., ‘en’, ‘ar’)

Translation Files

Translations are organized in JSON format. Example from public/i18n/en.json:
{
  "alerts": {
    "welcome": "Welcome!",
    "signed-out-successfully": "Signed out successfully.",
    "something-went-wrong": "Something went wrong."
  },
  "constants": {
    "arabic": "العربية",
    "english": "English",
    "home": "Home",
    "profile": "Profile",
    "settings": "Settings"
  },
  "jet-sign-in-page": {
    "email": "Email",
    "password": "Password",
    "sign-in": "Sign in",
    "sign-in-to-continue-to-x": "Sign in to continue to {{ x }}"
  }
}

Using Translations

In Templates

Use the transloco directive or pipe:
<!-- Directive -->
<h1 transloco="jet-home-page.toolbar-title"></h1>

<!-- Pipe -->
<p>{{ 'alerts.welcome' | transloco }}</p>

<!-- With parameters -->
<p>{{ 'jet-sign-in-page.sign-in-to-continue-to-x' | transloco: { x: 'Jet' } }}</p>

In Components

Inject TranslocoService:
readonly #translocoService = inject(TranslocoService);

showWelcomeMessage() {
  this.#alertService.showAlert(
    this.#translocoService.translate('alerts.welcome')
  );
}

RTL Support

Jet automatically handles RTL layouts when Arabic is selected. The layout direction is applied through CSS custom properties:
.jet-sidenav-container {
  &[dir='ltr'] {
    --jet-animation-multiplier: 1;
    --jet-safe-area-start: env(safe-area-inset-left);
    --jet-safe-area-end: env(safe-area-inset-right);
  }

  &[dir='rtl'] {
    --jet-animation-multiplier: -1;
    --jet-safe-area-start: env(safe-area-inset-right);
    --jet-safe-area-end: env(safe-area-inset-left);
  }
}

Dynamic Font Loading

Fonts are loaded dynamically based on the selected language:
  • English (LTR): Bricolage Grotesque + Noto Sans
  • Arabic (RTL): Noto Sans Arabic
The font switching is handled through CSS classes in src/styles.scss:94:
body {
  &.jet-font-pair-nsa-nsa {
    @include mat.theme(
      (
        typography: (
          brand-family: $nsa-font-family,
          plain-family: $nsa-font-family,
          bold-weight: 700,
          medium-weight: 500,
          regular-weight: 400,
        ),
      )
    );
  }
}

Material Paginator Internationalization

Jet includes a custom paginator intl class (src/app/classes/jet-mat-paginator-intl/jet-mat-paginator-intl.ts) that integrates with Transloco:
providers: [
  { provide: MatPaginatorIntl, useClass: JetMatPaginatorIntl }
]
This ensures Material components display translated text:
{
  "paginator": {
    "first-page": "First page",
    "items-per-page": "Items per page:",
    "last-page": "Last page",
    "next-page": "Next page",
    "page-x-of-y": "Page {{ x }} of {{ y }}",
    "previous-page": "Previous page"
  }
}

Adding New Languages

1

Create translation file

Add a new JSON file in public/i18n/ (e.g., fr.json)
2

Update language options

Add the language to LANGUAGE_OPTIONS constant with appropriate font configuration
3

Update Transloco config

Add the language code to transloco.config.ts:
langs: ['ar', 'en', 'fr']
4

Load appropriate fonts

Specify the Google Fonts URL in the language option configuration

Translation Key Management

Use the marker function for translation keys in constants:
import { marker } from '@jsverse/transloco-keys-manager/marker';

export const LANGUAGE_OPTIONS: LanguageOption[] = [
  {
    nameKey: marker('constants.english'),
    // ...
  }
];
The marker function doesn’t translate at runtime but helps the Transloco keys manager extract translation keys from your code.

Best Practices

Group related translations under feature-specific keys like jet-sign-in-page, jet-profile-page, etc.
Keep translation files organized with nested objects for better maintainability:
{
  "jet-profile-page": {
    "toolbar-title": "Profile",
    "save": "Save"
  }
}
Use template parameters for dynamic content:
'page-x-of-y': 'Page {{ x }} of {{ y }}'
Always test your application in RTL mode to ensure proper layout behavior.

PWA Integration

The service worker is configured to prefetch the default language (English):
{
  "resources": {
    "files": [
      "/i18n/en.json"
    ]
  }
}
Other language files are loaded on demand when users switch languages.

Next Steps

Theming

Learn about dynamic theming with RTL support

PWA Features

Explore offline capabilities

Build docs developers (and LLMs) love