I am creating a custom Angular ngx-translate Loader which either gets translations from cache or from an API. The point where I am stuck is Case 2 (see code below):
Desired procedure:
- gets translations from cache (sync)
- returns cached translations (via observer)
- gets translations from api (async)
- pares cache and api (finds difference)
- sends updated version of translations <-- How?
This is what I got:
getTranslation(lang: string): Observable<any> {
return new Observable(observer => {
// get translations from cache + start getting translations from API
const cachedTranslations = this.cacheService.getTranslation(lang);
const apiTranslations = this.http.get(environment.translationApi + lang);
if (cachedTranslations) {
// CASE #1: return cached translations
observer.next(cachedTranslations);
}
apiTranslations.subscribe(translations => {
// CASE #2: if cached translations are not up to date
// or dont exist, add new translations and reload lang
if (JSON.stringify(translations) !== JSON.stringify(cachedTranslations)) {
this.cacheService.setTranslations(lang, translations);
observer.next(translations);
}
observerplete();
}, () => {
observerplete();
});
});
}
Using observer.next()
works only once, even if it isn't pleted yet. So how do I update the translations in Case 2 where an observer.next()
already happend in Case 1?
I am creating a custom Angular ngx-translate Loader which either gets translations from cache or from an API. The point where I am stuck is Case 2 (see code below):
Desired procedure:
- gets translations from cache (sync)
- returns cached translations (via observer)
- gets translations from api (async)
- pares cache and api (finds difference)
- sends updated version of translations <-- How?
This is what I got:
getTranslation(lang: string): Observable<any> {
return new Observable(observer => {
// get translations from cache + start getting translations from API
const cachedTranslations = this.cacheService.getTranslation(lang);
const apiTranslations = this.http.get(environment.translationApi + lang);
if (cachedTranslations) {
// CASE #1: return cached translations
observer.next(cachedTranslations);
}
apiTranslations.subscribe(translations => {
// CASE #2: if cached translations are not up to date
// or dont exist, add new translations and reload lang
if (JSON.stringify(translations) !== JSON.stringify(cachedTranslations)) {
this.cacheService.setTranslations(lang, translations);
observer.next(translations);
}
observer.plete();
}, () => {
observer.plete();
});
});
}
Using observer.next()
works only once, even if it isn't pleted yet. So how do I update the translations in Case 2 where an observer.next()
already happend in Case 1?
1 Answer
Reset to default 6This answer might not be relevant to you anymore, since it's been a few months, but I'll just leave it here, in case anybody stumbles over this question in the future, just like I did, when I was looking for a solution to this problem:
So it seems like pushing two different values into the observable in the getTranslation
function messes with ngx-translate
- I found a work around though.
I'm not sure if this is the best way to do it, but it works and solves my problem, so I'm just gonna go ahead and use it.
CustomTranslateLoader:
getTranslation(lang: string): Observable<any> {
const translations = new BehaviorSubject(undefined);
translations.next(JSON.parse(this.localStorageService.getItem('translations')));
return translations;
}
loadTranslation(lang) {
return this.blockpitApiService.get('/translations/' + lang);
}
app.ponent.ts
constructor(
private translate: TranslateService,
private translateService: CustomTranslateLoader,
private localStorageService: LocalStorageService
) {
language = translate.getBrowserLang();
translate.setDefaultLang(language);
// load translations from server and update translations
this.translateService.loadTranslation(language).subscribe(response => {
this.localStorageService.setItem('translations', JSON.stringify(response.data));
translate.setTranslation(language, response.data);
translate.use(language);
});
}
Since ngx-translate
simply ignores when we push new translations into the observable, we can simply call translate.setTranslation(language, response.data)
and translate.use(language)
, to update the values used when translating.
By calling this as soon as our api call is finished, we initially see the translation that are first set in getTranslation
which ngx-translation
calls automatically and the api translations as soon as they are available when we .subscribe
to the function in our app.ponent.ts
.
This might not be ideal but it works and seems like an ok workaround - at least to me.