6

I have language service to achieve internationalization in my app. Basically it works ok in dev mode and sometimes in production as well.

My problem is that sometimes old version of my json files are cached in browser (If I'll open website in incognito mode everything is as expected).

I have my json files under assets/i18n directory

language.service.ts:

import { HttpBackend, HttpClient } from '@angular/common/http';
import { Injectable, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs/internal/Subject';
import { Subscription } from 'rxjs/internal/Subscription';

@Injectable({
  providedIn: 'root'
})
export class LanguageService implements OnDestroy {
  activeLanguage: string = 'ka';
  data: any = {};
  data$: Subject<any>;
  dataSubscription: Subscription = new Subscription();

  constructor(
    private httpClient: HttpClient,
    private httpBackend: HttpBackend
  ) {
    this.data$ = new Subject();
    this.httpClient = new HttpClient(httpBackend);
  }

  loadLanguageFile(lang: string): void {
    if (lang) {
      this.activeLanguage = lang;
    }
    const path = `../assets/i18n/${this.activeLanguage}.json`;
    if (this.data[this.activeLanguage]) {
      this.data$.next(this.data[this.activeLanguage]);
    } else {
      this.dataSubscription = this.httpClient.get(path).subscribe(res => {
        this.data[this.activeLanguage] = res;
        this.data$.next(this.data[this.activeLanguage]);
      });
    }
  }

  ngOnDestroy(): void {
    this.dataSubscription.unsubscribe();
  }
}

language.module.ts:

import { APP_INITIALIZER, NgModule } from '@angular/core';

import { LanguageService } from './language.service';

@NgModule({
  imports: [],
  exports: [],
  declarations: [],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [LanguageService],
      useFactory: (language: LanguageService) => () => {
        return language.loadLanguageFile('ka');
      }
    }
  ]
})
export class LanguageModule {}

translate.pipe.ts:

import { OnDestroy, Pipe, PipeTransform } from '@angular/core';
import { LanguageService } from '@app/core/services/language/language.service';
import { Subscription } from 'rxjs/internal/Subscription';

@Pipe({
  name: 'translate',
  pure: false
})
export class TranslatePipe implements PipeTransform, OnDestroy {
  data: any;
  subscription: Subscription = new Subscription();

  constructor(private languageService: LanguageService) {
    this.subscription = this.languageService.data$.subscribe(res => {
      this.data = res;
    });
  }

  transform(key: string): string {
    this.data = this.languageService.data[this.languageService.activeLanguage];
    return this.data && this.data[key] ? this.data[key] : key;
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

sample use case:

<div>{{ text | translate }}</div>

What can I do?

gsiradze
  • 4,583
  • 15
  • 64
  • 111
  • if your files get cached caches will get clear at some point.it's only a problem if you change translation files often.in such a case you can do something like this :: https://stackoverflow.com/questions/15041603/how-to-prevent-the-browser-from-caching-a-json-file . basically you have to add some random query string values. but how can you do this with angular .angular loads file internally you cannot change it.actually you can create a custom translate loader so you can change urls as you want https://github.com/ngx-translate/http-loader but i think you can off caching from servers too. – Madhawa Priyashantha Feb 23 '19 at 10:31
  • @MadhawaPriyashantha Thanks for answer. your provided `http-loader` uses third party library called `ngx-translate`. At first I want to achieve the same solution by miself – gsiradze Feb 23 '19 at 12:30
  • ohh sorry .but wait considering this line `const path = `../assets/i18n/${this.activeLanguage}.json`;` you don't need to do any hard work just append random generated value to end of the .json just like in the attached answer.like const path = `../assets/i18n/${this.activeLanguage}.json?nocache=${myRandomValue}`; i hope this will work – Madhawa Priyashantha Feb 23 '19 at 12:33
  • sorry comment format is messed due to backtick. – Madhawa Priyashantha Feb 23 '19 at 12:38
  • @MadhawaPriyashantha well.. That one works as expected. thanks – gsiradze Feb 23 '19 at 13:40
  • great my pleasure – Madhawa Priyashantha Feb 23 '19 at 13:42
  • @MadhawaPriyashantha what about adding this as an answer? – TweeZz Feb 08 '20 at 11:43

0 Answers0