All files / lib/services i18n.service.ts

75.68% Statements 28/37
50% Branches 13/26
75% Functions 3/4
74.29% Lines 26/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 1031x 1x 1x                   1x 1x 1x     1x     1x   1x   1x 1x 1x   1x   1x                   21x         21x   21x       21x         3x 3x 3x   3x             18x       18x           18x       3x                                          
import { Inject, Injectable, Logger } from '@nestjs/common';
import * as format from 'string-format';
import {
  I18N_OPTIONS,
  I18N_TRANSLATIONS,
  I18N_LANGUAGES,
  I18N_LANGUAGES_SUBJECT,
  I18N_TRANSLATIONS_SUBJECT,
} from '../i18n.constants';
import { I18nOptions } from '..';
import { I18nTranslation } from '../interfaces/i18n-translation.interface';
import * as _ from 'lodash';
import { Observable, BehaviorSubject } from 'rxjs';
import { I18nParser } from '../parsers/i18n.parser';
import { take } from 'rxjs/operators';
 
@Injectable()
export class I18nService {
  constructor(
    @Inject(I18N_OPTIONS)
    private readonly i18nOptions: I18nOptions,
    @Inject(I18N_TRANSLATIONS)
    private readonly translations: Observable<I18nTranslation>,
    @Inject(I18N_LANGUAGES)
    private readonly supportedLanguages: Observable<string[]>,
    private readonly logger: Logger,
    private readonly parser: I18nParser,
    @Inject(I18N_LANGUAGES_SUBJECT)
    private readonly languagesSubject: BehaviorSubject<string[]>,
    @Inject(I18N_TRANSLATIONS_SUBJECT)
    private readonly translationsSubject: BehaviorSubject<I18nTranslation>,
  ) {}
 
  public async translate(
    key: string,
    options?: {
      lang?: string;
      args?: Array<{ [k: string]: any } | string> | { [k: string]: any };
    },
  ): Promise<string> {
    options = {
      lang: this.i18nOptions.fallbackLanguage,
      ...options,
    };
 
    const { lang, args } = options;
 
    const translationsByLanguage = (
      await this.translations.pipe(take(1)).toPromise()
    )[lang];
 
    if (
      translationsByLanguage === undefined ||
      translationsByLanguage === null ||
      (!!translationsByLanguage && !translationsByLanguage.hasOwnProperty(key))
    ) {
      Eif (lang !== this.i18nOptions.fallbackLanguage) {
        const message = `Translation "${key}" in "${lang}" does not exist.`;
        this.logger.error(message);
 
        return this.translate(key, {
          lang: this.i18nOptions.fallbackLanguage,
          args: args,
        });
      }
    }
 
    let translation = translationsByLanguage
      ? translationsByLanguage[key]
      : key;
 
    Iif (translation && (args || (args instanceof Array && args.length > 0))) {
      translation = format(
        translation,
        ...(args instanceof Array ? args || [] : [args]),
      );
    }
    return translation || key;
  }
 
  public async getSupportedLanguages() {
    return this.supportedLanguages.pipe(take(1)).toPromise();
  }
 
  public async refresh() {
    const translations = await this.parser.parse();
    if (translations instanceof Observable) {
      this.translationsSubject.next(
        await translations.pipe(take(1)).toPromise(),
      );
    } else {
      this.translationsSubject.next(translations);
    }
 
    const languages = await this.parser.languages();
    if (languages instanceof Observable) {
      this.languagesSubject.next(await languages.pipe(take(1)).toPromise());
    } else {
      this.languagesSubject.next(languages);
    }
  }
}