i18n 文件在生产中缓存

gsi*_*dze 8 internationalization angular

我有语言服务来在我的应用程序中实现国际化。sometimes基本上它在开发模式和生产模式下都可以正常工作。

我的问题是sometimes旧版本的 json 文件缓存在浏览器中(如果我以隐身模式打开网站,一切都会按预期进行)。

我的 json 文件位于assets/i18n目录下

语言.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();
  }
}
Run Code Online (Sandbox Code Playgroud)

语言.模块.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 {}
Run Code Online (Sandbox Code Playgroud)

翻译.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();
  }
}
Run Code Online (Sandbox Code Playgroud)

示例用例:

<div>{{ text | translate }}</div>
Run Code Online (Sandbox Code Playgroud)

我能做些什么?

roy*_*yka 1

我们利用 GitLab 构建流程和environment.ts文件设法解决了这个问题。

我们更新了environment.ts文件以包含“版本”字段:

export const environment = {
  production: false,
  version: 'local' // replaced via the environment.prod.ts file via GitLab build script
};
Run Code Online (Sandbox Code Playgroud)

然后,我们还替换了environment.prod.ts文件以包含相同的版本字段,但带有易于替换的标签:

export const environment = {
  production: true,
  version: 'BUILD_TAG_VERSION'
};
Run Code Online (Sandbox Code Playgroud)

我们在我们的app.module.ts HttpLoaderFactory

export function HttpLoaderFactory(http: HttpClient) {
  return new MultiTranslateHttpLoader(http, [
    {prefix: './assets/i18n/messages.', suffix: `.json?version=${environment.version}`},
  ]);
}
Run Code Online (Sandbox Code Playgroud)

最后,在构建步骤中,我们将 BUILD_TAG_VERSION 替换为标签/分支名称。在我们的例子中,我们使用 GitLab,因此在我们的.gitlab-ci.yml文件中,我们在构建项目之前运行了以下脚本:

sed -i "s/BUILD_TAG_VERSION/$CI_COMMIT_REF_NAME/g" src/environments/environment.prod.ts
Run Code Online (Sandbox Code Playgroud)

每次构建项目时,这都会替换 BUILD_TAG_VERSION,并保证在任何版本上都会提取文件的新版本。