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.