libs/ngx-pfe/util/i18n-from-state/pipe/pfe-i18n-from-state.pipe.ts

Metadata

Relationships

Depends on

No results matching.

Index

Methods

Methods

transform
transform(query: string | undefined | null, ..._interpolationParameters: unknown[])
Parameters :
Name Type Optional
query string | undefined | null No
_interpolationParameters unknown[] No
Returns : any
import { PFE_LOGGER, PfeBusinessService } from '@allianz/ngx-pfe';
import { ChangeDetectorRef, inject, OnDestroy, Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { merge } from 'rxjs';
import { take } from 'rxjs/operators';
import { PfeI18nFromStateHandler, REPLACEMENT_SEPARATOR } from '../pfe-i18n-from-state-handler';

@Pipe({
  name: 'pfeI18nFromState',
  pure: false, // required to update the value when the promise is resolved
  standalone: false,
})
export class PfeI18nFromStatePipe implements PipeTransform, OnDestroy {
  private translateService = inject(TranslateService);
  private changeDetectorRef = inject(ChangeDetectorRef);
  private pfeI18nFromStateHandler = new PfeI18nFromStateHandler(inject(PfeBusinessService), this.translateService, inject(PFE_LOGGER));

  private value = '';
  private lastKey: string | undefined;

  private translationChangeSubscription = merge(
    this.translateService.onTranslationChange,
    this.translateService.onLangChange,
    this.translateService.onFallbackLangChange
  ).subscribe(() => this.updateValue());

  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
  transform(query: string | undefined | null, ..._interpolationParameters: unknown[]): any {
    if (!query) {
      return query;
    }
    if (query !== this.lastKey) {
      this.lastKey = query;
      this.updateValue();
    }
    return this.value;
  }

  ngOnDestroy(): void {
    this.translationChangeSubscription.unsubscribe();
    this.pfeI18nFromStateHandler.destroy();
  }

  /**
   * Translates the current key and subscribes to the state values used in it.
   * The plain translation is used until the render with the state values is done. It is available right away
   * when the translations are already loaded.
   */
  private updateValue(): void {
    const key = this.lastKey;
    if (key) {
      this.translateService
        .get(key)
        .pipe(take(1))
        .subscribe((translation) => {
          if (key === this.lastKey) {
            this.value = translation;
          }
        });
      this.pfeI18nFromStateHandler.initializeAndSubscribe(key, (translatedText: string) => this.renderText(key, translatedText));
    }
  }

  /**
   * Called by PfeI18nFromStateHandler when the key is changed/translated or when one of the used state values from
   * the expression changes.
   * The result is dropped if the key changed while rendering, so a slower render of a previous key can't overwrite it.
   */
  private async renderText(key: string, translatedText: string): Promise<void> {
    let result = '';
    for (const textChunk of translatedText.split(REPLACEMENT_SEPARATOR)) {
      const finalText = await this.pfeI18nFromStateHandler.getFinalText(textChunk);
      result = result + finalText;
    }
    const value = result ? await this.translateService.get(result).toPromise() : '';
    if (key !== this.lastKey) {
      return;
    }
    this.value = value;

    this.changeDetectorRef.markForCheck();
  }
}

results matching ""

    No results matching ""