Канал для изменения строки на эквивалент ее JSON перевода angular - PullRequest
0 голосов
/ 08 мая 2020

В моем проекте мы должны использовать несколько JSON переводов для сущностей (JSON сортируются по типу, а не по языку). Эти сущности отделены от другой интернационализации страницы (что мы делаем с помощью ngx-translation).

Нам удалось параметризовать импорт через канал, который получает тип, и в соответствии с этим JSON содержащий перевод получается. Проблема в том, что язык браузера обновляется только один раз, и если язык изменяется, этот перевод не обновляется.

Это класс Pipe

import { Pipe, PipeTransform } from '@angular/core';
import { TranslationComponent } from './translation.component';

@Pipe({name: 'translateType'})
export class EntityTranslatorPipe implements PipeTransform {
    constructor(private translationComponent: TranslationComponent){}

    transform(name: string, type?: string){

        return this.getNameTranslated(name, type)
    }
    async getNameTranslated(name,  type){
        const locale = this.translationComponent.userLocale+this.translationComponent.userLang
        var result
        await import('./entity/'+type+'.json').then(res =>{
            var entityJSON = JSON.parse(JSON.stringify(res));
            //We take out the entity that matches the filter(is compared removing whitespaces and in lowercase to avoid many mismatches)
            const entityFiltered = entityJSON.default.find(d => d.locale.EUen.replace(/\s+/g, '').toLowerCase() === name.replace(/\s+/g, '').toLowerCase())
            result = entityFiltered.locale[locale];
        })
        return result
    }
}

Это метод из Компонент перевода, который обеспечивает получение языка браузера и изменение интернационализации вручную пользователем.

  public changeLanguage(lang, locale) {
    // Call translation service to use translation library
    this.translate.use(lang);

    // Sets translation variables
    this.userLang = lang;
    this.userLocale = locale;
  }

Это вызов канала, который мы делаем из HTML

{{"carp" | translateType:"fish" | async }}

Это первый пайп, который мы создали, и нам очень трудно получить то, что мы хотим. Мы пытаемся сделать канал нечистым, но это не работает, из-за этого браузер зависает

EDIT: Я пытаюсь сделать канал чистым, передав параметр локали. Как сделать этот метод универсальным c для всех компонентов?

constructor(private translationComponent: TranslationComponent, private translateService: TranslateService) {}
  locale = this.translationComponent.userLocale+this.translationComponent.userLang
  aux = this.translateService.onLangChange.subscribe(lang=>{
    this.locale = this.translationComponent.getLocaleDefault(this.locale)+lang.lang;
  })

1 Ответ

0 голосов
/ 08 мая 2020

Ну, это нечисто. Не должно быть, но это так. Возвращаемое значение зависит не только от name, но также от lang и locale, которые не являются аргументами для конвейера, и в зависимости от значений, которые не являются аргументами, является определение нечистого.

Я полагаю, но не могу проверить, что зависание вызывает какое-то взаимодействие между примесью и import.

Вы можете сделать его чистым, осознав, что чистый отклик (то есть отклик, исключительно на аргументе name) - это не Promise, а Observable, который повторно генерируется при изменении языка или локали. Имея это в виду, вы можете переписать, что вы получите примерно так:

import { BehaviorSubject, pipe, merge, map, switchMap, from } from 'rxjs';

@Pipe({name: 'translateType'})
export class EntityTranslatorPipe implements PipeTransform {
  constructor(private translationComponent: TranslationComponent){}

  static readonly userLang = new BehaviorSubject('en');
  static readonly userLocale = new BehaviorSubject('en');

  transform(name: string, type?: string): Observable<string> {
    return this.getNameTranslated(name, type || '')
  }
  getNameTranslated(name: string, type: string): Observable<string> {
    return merge(EntityTranslatorPipe.userLang, 
                 EntityTranslatorPipe.this.userLocale).pipe(
      map(([lang, locale]) => async {
        const json = await import(`./entity/${lang}.json`);
        const entityFiltered = json.default.find(d => 
            d.locale.EUen.replace(/\s+/g, '').toLowerCase()
               === name.replace(/\s+/g, '').toLowerCase());
        return  entityFiltered.locale[locale];
      }),
      switchMap(from)); // flatten each Promise
  }
}
...
changeLanguage(lang, locale) {
    this.translate.use(lang);
    EntityTranslatorPipe.userLang.next(lang);
    EntityTranslatorPipe.userLocale.next(locale};
}
...