Skip to content

Translating text

@flyze/lib-core-angular 1.0.0-alpha.34· latest

How to render translated text with this library, in templates and in TypeScript.

Prerequisite: transloco configured and FyzTranslateModule imported — see getting-started. Why any of it behaves the way it does: features/translation-config.

Use fyzTransloco when you have a translation key and the text lives in a translation file:

<h1>{{ 'GREETING' | fyzTransloco: { scope: 'orders', params: { name: userName } } }}</h1>

Use fyzTranslate when you have a FyzTranslationConfig — a value that carries its own text or points at a key:

<h1>{{ title | fyzTranslate }}</h1>
<h1>{{ title | fyzTranslate: { params: { name: userName } } }}</h1>

Rule of thumb: a key you wrote in the template → fyzTransloco. A value that came out of a config, an API or the platform → fyzTranslate.

// a literal the user typed — same text in every language
const staticTitle: FyzTranslationConfig = {
_type: 'static',
value: 'Hello {{name}}'
};
// one literal per language
const dynamicTitle: FyzTranslationConfig = {
_type: 'dynamic',
value: [
{ language: 'de', text: 'Hallo {{name}}' },
{ language: 'en', text: 'Hello {{name}}' }
]
};
// a key in a transloco scope
const scopedTitle: FyzTranslationConfig = {
_type: 'scoped',
value: { key: 'GREETING', scope: 'orders' }
};

scope also accepts an array for nested scopes: ['orders', 'detail'] resolves orders.detail.GREETING.

Write {{name}} in the text and supply the value at the call site:

{{ staticTitle | fyzTranslate: { params: { name: userName, count: messages.length } } }}

A config can carry defaults, which the call site overrides per key:

const greeting: FyzTranslationConfig = {
_type: 'static',
value: '{{name}} ({{role}})',
params: { name: 'unknown', role: 'guest' }
};
{{ greeting | fyzTranslate: { params: { name: 'Peter' } } }}
<!-- Peter (guest) -->

Precedence is value.params < config.params < call site. If no params exist anywhere, the text is left completely untouched — braces included. That is what keeps existing texts containing {{ }} intact.

constructor(private translate: FyzTranslateService) {}
// once, synchronously
const label = this.translate.translate(config, { params: { name: 'Peter' } });
// following the active language
this.translate
.selectTranslate(config, { params: { name: 'Peter' } })
.pipe(takeUntil(this.destroy$))
.subscribe((text) => (this.label = text));

Use selectTranslate for anything long-lived: dynamic and scoped configs re-emit on a language switch, translate() gives you the text for the language that happened to be active at that moment.

For a plain key + scope there is FyzTranslocoService.translate(key, scope, params) and its selectTranslate counterpart. Note that only selectTranslate falls back to the bare key when a scoped key is missing; the synchronous version returns the full scoped key.

  • Replace configs, do not mutate them. config.value = 'new' on an object you already passed to the pipe is never picked up — the pipe compares against that same object, so it always looks unchanged. The same goes for mutating a params object in place. Assign a new object instead; building a fresh equal one every cycle (a getter, buildParams()) is free, because the pipe compares structurally rather than by reference.
  • NULL or Unknown on screen means the config was null/undefined or not a config at all. Fix the data, not the template.
  • An empty string from a dynamic config means no entry matched the active language. There is no fallback language.
  • A bare key on screen means the scoped key did not resolve — check the scope name and that the scope’s translations are loaded (providing-runtime-translations).
  • Do not use fyzTansloco (missing r). It still works, it is deprecated.

The /transloco-test route of the test app renders every case above side by side.