Skip to main content
cngx-src documentation

Localisation

CNGX ships English defaults. It does not ship translations, and it does not extract messages at build time: the contract is a DI token per feature area, read at construction, overridable app-wide or per subtree. A coverage guard (projects/core/theming/user-facing-string-coverage.spec.ts) keeps it honest - a new hardcoded string fails the suite unless it lives in an override source.


Two levels, no middle

Per key. Every area exposes a partial override, so one label changes and the rest stay English:

provideTabsI18n(withTabsI18nLabels({ tabsLabel: 'Reiter' }))

Unset keys keep their default. There is no all-or-nothing bundle to fill in.

Whole app. Collect the providers you use into one exported const. That const is your language file:

// src/i18n/de.ts
import type { Provider } from '@angular/core';
import { provideCardI18n, withCardI18nLabels } from '@cngx/common/card';
import { provideDialogConfig, withDialogLabels } from '@cngx/common/dialog';
import { provideTabsI18n, withTabsI18nLabels } from '@cngx/common/tabs';
import { provideSelectConfig, withAriaLabels } from '@cngx/forms/select';
import { provideFeedbackI18n } from '@cngx/ui/feedback';

export const DE: Provider[] = [
  provideTabsI18n(withTabsI18nLabels({ tabsLabel: 'Reiter', previousTab: 'Vorheriger' })),
  provideCardI18n(withCardI18nLabels({ selected: 'Ausgewählt', deselected: 'Abgewählt' })),
  provideDialogConfig(withDialogLabels({ close: 'Dialog schließen' })),
  provideSelectConfig(withAriaLabels({ searchInput: 'Optionen durchsuchen' })),
  provideFeedbackI18n({
    alertsRegionLabel: 'Hinweise',
    announcements: { alertDismissed: 'Hinweis verworfen' },
  }),
];
bootstrapApplication(App, { providers: [...DE] });

Both levels resolve to the same tokens. Pick the smallest surface that fits.


Why there is no provideCngxI18n()

A single aggregator would need a central type tracking every lib's i18n surface forever, and it would re-introduce the cross-lib coupling the per-token design exists to avoid. It would also add nothing: the const above is the same one-file ergonomics, composed by the consumer, maintained by nobody.

This is Pillar 3 applied to configuration - CNGX ships the hooks, you compose them.


Scoping to a subtree

Every provider is an ordinary Angular provider, so a component's viewProviders scopes it to that subtree:

@Component({
  viewProviders: [provideDialogConfigAt(withDialogLabels({ close: 'Fermer' }))],
})
export class FrenchSection {}

Areas that ship a provide*At variant name it explicitly; the rest work the same way because the token resolves through the element injector.


Where each string lives

Area Entry point
@cngx/common/stepper provideStepperI18n(withStepperI18nLabels(...))
@cngx/common/tabs provideTabsI18n(withTabsI18nLabels(...))
@cngx/common/chart provideChartI18n({ ... })
@cngx/common/card provideCardI18n(withCardI18nLabels(...))
@cngx/common/data provideRecyclerI18n({ ... })
@cngx/common/dialog provideDialogConfig(withDialogLabels(...))
@cngx/common/interactive provideCngxMenu(...) menu announcement config
@cngx/common/timeline CNGX_TIMELINE_CONFIG
@cngx/forms/select provideSelectConfig(withAriaLabels(...), withFallbackLabels(...))
@cngx/forms/input CNGX_INPUT_CONFIG aria-label bundle
@cngx/forms/filter-builder CNGX_FILTER_BUILDER_CONFIG
@cngx/ui/feedback provideFeedbackI18n({ ... }), or provideFeedback(withFeedbackI18nLabels(...))
@cngx/ui/paginator CNGX_PAGINATOR_CONFIG
@cngx/ui/toc, stat-card, accordion, breadcrumb, collection, command-palette, a11y their CNGX_*_CONFIG label bundles
@cngx/data-display/treetable CNGX_TREETABLE_CONFIG

Two naming shapes, one rule each: an area whose strings ride a dedicated i18n token uses with<Area>I18nLabels; an area whose strings ride its existing config cascade uses with<Area>Labels on that config's feature.


What is not in scope

Runtime locale switching and $localize extraction are not part of the contract. The tokens resolve at construction; swapping a language at runtime means re-creating the injector, which in practice means a reload. Component copy a consumer authors - option labels, titles, messages - was never CNGX's to translate.