Skip to main content

Language Service

The i18n system in UnPisPas is built around JSON translation files loaded per module, with placeholder-based string interpolation and per-language caching.

import { languageService, languageSupport, langsPath } from '@unpispas/upp-base';

langsPath token

Applications must provide the langsPath injection token to tell the language system where to find JSON files:

import { langsPath } from '@unpispas/upp-base';

@NgModule({
providers: [
{ provide: langsPath, useValue: '/assets/langs' }
]
})
export class AppModule {}

Translation files are expected at {langsPath}/{module}/{language}.json, e.g. /assets/langs/main/es.json.

Supported locales

CodeLanguageFlag
ESSpanish🇪🇸
EUBasque🇪🇸 (PV)
ENEnglish🇬🇧
ZHChinese🇨🇳

languageService

The root-level injectable that manages all loaded languages and modules.

Constructor behaviour

  1. Detects browser language (navigator.language).
  2. Falls back to AppConstants.defaultLanguage ('es') if not supported.
  3. Checks URL query parameter ?lang=XX to override.
  4. Loads the 'base' translation module on startup.

Methods

MethodSignatureDescription
GetLanguages()(): Array<{ lang: string, flag: string }>Returns the list of supported languages.
GetLanguage(toUpper?)(toUpper?: boolean): stringReturns the current language code.
SetLanguage(language, global?)(language: string, global?: boolean): Promise<boolean>Switches the active language. If global is true (default), all components are notified.
LoadModule(name)(name: string): Promise<boolean>Loads a translation module (e.g. 'main', 'guest') in all initialised languages. Emits OnSetLanguage on success.
tr(id, args?, language?)(id: string, args?: Array<string|number|null|undefined>, language?: string|null): stringTranslates a string ID, replacing {{placeholder}} tokens with positional arguments. Returns '...' while loading.
StrInfo(id)(id: string): { tr: string, args: any[] } | nullReturns raw translation info for a string ID (used by languageSupport).

Observables

ObservableDescription
OnSetLanguageEmits when the language changes or a new module finishes loading.

Translation file format

Each JSON file is an array of translation entries:

[
{ "id": "@loading_wait", "tr": "Cargando, espere...", "args": [] },
{ "id": "@http_request_error", "tr": "Error en la solicitud HTTP: {{status}}", "args": ["status"] }
]
  • id: unique string key, conventionally prefixed with @.
  • tr: translated text with {{argName}} placeholders.
  • args: ordered list of placeholder names matching {{…}} tokens.

languageSupport

A utility base class designed to be extended by Angular components that need reactive translations. It handles subscription to language changes and provides per-component translation caching.

import { languageSupport } from '@unpispas/upp-base';

export class MyComponent extends languageSupport implements OnDestroy {
constructor(lang: languageService, chng: ChangeDetectorRef) {
super(lang, chng);
}

ngOnDestroy() {
super.OnDestroy();
}
}

Properties

PropertyTypeDescription
languagestring | nullCurrently active language for this component.

Methods

MethodSignatureDescription
tr(id, args?)(id: string, args?: any[]): stringTranslates with per-component caching. Zero-arg translations are cached in a Map; translations with args use a separate cache keyed by string ID.
SetLanguage(language)(language: string): Promise<void>Switches this component's language without affecting the global setting (useful for bilingual receipts).
OnDestroy()(): voidUnsubscribes from language-change notifications. Must be called in the component's ngOnDestroy.

How caching works

  1. Translations with no arguments are stored in _strcache (Map<id, string>).
  2. Translations with arguments are stored in _argcache (Map<id, trinfo>) for the template, then resolved with the provided args.
  3. When the language changes, both caches are cleared and ChangeDetectorRef.detectChanges() is called.

Usage example

export class TicketComponent extends languageSupport implements OnDestroy {
constructor(private lang: languageService, private cdr: ChangeDetectorRef) {
super(lang, cdr);
}

get title(): string {
return this.tr('@ticket_title');
}

get errorMessage(): string {
return this.tr('@http_request_error', [404]);
}

ngOnDestroy() {
super.OnDestroy();
}
}