首页 > 解决方案 > 管道将字符串更改为其 JSON 转换角度的等效项

问题描述

在我的项目中,我们必须为实体使用几个 JSON 翻译(JSON 按类型排序,而不是按语言排序)。这些实体与页面的其他国际化(我们使用 ngx-translation 进行)分离。

我们已经设法通过获取类型的管道对导入进行参数化,并据此获取包含翻译的 JSON。问题是浏览器语言只更新一次,如果语言改变,这个翻译不会更新。

这是管道的类

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
    }
}

这是来自 TranslationComponent 的方法,负责获取浏览器的语言并由用户手动修改国际化。

  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 }}

这是我们创建的第一个管道,我们发现很难得到我们想要的东西。我们试图使管道不纯,但它不起作用,它使浏览器挂起

编辑:我试图使管道纯粹传递语言环境参数。如何使此方法适用于所有组件?

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;
  })

标签: angulartypescriptpipe

解决方案


嗯,这不纯的。它不应该是,但它是。返回值不仅取决于name,还取决于langlocale,它们不是管道的参数,并且取决于不是参数的值是不纯的定义。

我想,但不能检查,这是杂质和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};
}

推荐阅读