Reputation: 25
In my project we have to use several JSON translations for the entities (JSONs are sorted by type, not by language). These entities are separated from the other internationalization of the page (which we do with ngx-translation).
We have managed to parameterize the import through a pipe that obtains the type and according to this, the JSON that contains the translation is obtained. The problem is that the browser language is only updated once and if the language changes, this translation is not updated.
This is the class of the 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
}
}
This is the method from TranslationComponent that takes care of obtaining the language of the browser and modifying the internationalization manually by the user.
public changeLanguage(lang, locale) {
// Call translation service to use translation library
this.translate.use(lang);
// Sets translation variables
this.userLang = lang;
this.userLocale = locale;
}
This is the pipe call that we make from the HTML
{{"carp" | translateType:"fish" | async }}
It's the first pipe we created and we're finding it very difficult to get what we want. We try to make the pipe impure but it doesn't work, it makes the browser hang
EDIT: I'm trying to make the pipe pure passing the locale parameter. How can I make this method generic for all components?
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;
})
Upvotes: 0
Views: 1066
Reputation: 44406
Well, this is impure. It shouldn't be, but it is. The return value depends not only on name
, but also on lang
and locale
, which are not arguments to the pipe, and depending on values that are not arguments is the definition of impure.
I imagine, but cannot check, that it's some interaction between the impurity and the import
that is causing the hang.
You can make it pure by realizing that the pure response (that is, the response that depends solely on the argument name
) is not a Promise, but an Observable, one that re-emits whenever the language or locale is changed. With that in mind, you can re-write you come something like this:
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};
}
Upvotes: 1