Angular 管道将字符串更改为其JSON转换的等效值
在我的项目中,我们必须对实体使用几个JSON翻译(JSON是按类型排序的,而不是按语言排序的)。这些实体与页面的其他国际化(我们使用ngx翻译)分离 我们已经设法通过一个获取类型的管道来参数化导入,并根据该管道获取包含转换的JSON。问题是浏览器语言只更新一次,如果语言发生更改,则不会更新此翻译 这是管道的等级Angular 管道将字符串更改为其JSON转换的等效值,angular,typescript,pipe,Angular,Typescript,Pipe,在我的项目中,我们必须对实体使用几个JSON翻译(JSON是按类型排序的,而不是按语言排序的)。这些实体与页面的其他国际化(我们使用ngx翻译)分离 我们已经设法通过一个获取类型的管道来参数化导入,并根据该管道获取包含转换的JSON。问题是浏览器语言只更新一次,如果语言发生更改,则不会更新此翻译 这是管道的等级 import { Pipe, PipeTransform } from '@angular/core'; import { TranslationComponent } from './
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 }}
这是我们创建的第一个管道,我们发现很难得到我们想要的。
我们试图让管道变得不纯,但它不起作用,它让浏览器挂起
EDIT:我试图使管道纯粹地传递locale参数。
如何使此方法适用于所有组件
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;
})
嗯,这是不纯洁的。不应该是,但确实是。返回值不仅取决于name
,还取决于lang
和locale
,它们不是管道的参数,并且取决于非参数的值是不纯的定义
我想象,但无法检查,是杂质和导入之间的某种交互作用导致了挂起
您可以通过认识到纯响应(即仅依赖于参数name
的响应)不是承诺,而是可观察的,在语言或区域设置发生更改时重新发出的响应,从而使其变得纯粹。考虑到这一点,您可以重新编写以下内容:
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};
}
import{BehaviorSubject,pipe,merge,map,switchMap,from}from'rxjs';
@管道({name:'translateType'})
导出类EntityTranslatorPipe实现PipeTransform{
构造函数(私有translationComponent:translationComponent){}
静态只读userLang=new BehaviorSubject('en');
静态只读userLocale=newbehaviorsubject('en');
转换(名称:字符串,类型?:字符串):可观察{
返回此.getNameTranslated(名称,键入| |“”)
}
getNameTranslated(名称:string,类型:string):可观察{
返回合并(EntityTranslatorPipe.userLang,
EntityTranslatorPipe.this.userLocale).pipe(
映射([lang,locale])=>async{
const json=wait import(`./entity/${lang}.json`);
constEntityFiltered=json.default.find(d=>
d、 locale.EUen.replace(/\s+/g',).toLowerCase()
===name.replace(/\s+/g',).toLowerCase();
返回entityFiltered.locale[locale];
}),
switchMap(from));//展平每个承诺
}
}
...
更改语言(语言,区域设置){
这个。翻译。使用(lang);
EntityTranslatorPipe.userLang.next(lang);
EntityTranslatorPipe.userLocale.next(locale};
}
我无法在管道上实例化区域设置和更改语言的方法,因为这是由TranslationComponent完成的。如果我将区域设置添加为管道条目会怎么样?当您更改区域设置时,它将是纯的,对吗?问题是如何检测更改,因为您必须在使用管道的所有组件中执行此操作…@Yerehia-抱歉,我误读了您的原始代码。请参见编辑。transform()
的返回值是一个可观察的值,每当thisLang
和thisleage
发出时,它都会发出。您不必检测更改:您只需使用| async
即可,Angular将负责更新屏幕。