Angular 5管道和动态区域设置

时间:2017-11-07 12:31:34

标签: angular angular-i18n angular5

我目前有以角度4构建的应用程序,并希望升级到角度5.我正在阅读他们如何处理管道中的区域设置,似乎升级不再是一种选择。据我所知,他们也希望你 1.手动导入不同的文化 2.为每种文化构建一个单独的应用程序

问题在于我为一家支持351种不同文化的国际公司工作,我们有15个应用程序。有角度的团队真的说我现在必须构建5265个不同的应用程序,如果我想继续升级吗?如果我带着那个去找我的老板,我可能会被赶出房间。

在我们的angularJs应用程序中,我们刚刚下载了用户登录时我们需要的$ locale服务,并将提供程序设置为该服务。 Angular有什么类似的吗?如果不是,我不确定企业级应用程序如何能够使用这种语言,除非开发人员足够幸运,只需要支持一种文化。

3 个答案:

答案 0 :(得分:2)

在github上就此问题进行沟通之后,已经开始使用的想法是创建一个我在APP_INITIALIZER中调用的服务,您可以在下面看到。由于构建时的动态字符串,angular-cli将为每个文化创建一个块,然后在我提供从服务调用收到的文化字符串后,在运行时加载正确的字符串。

setLocale(localeId: string): Promise<any> {
    this.culture = localeId;
    return new Promise((resolve, reject) => {
      System.import(`@angular/common/locales/${localeId}.js`).then(
        module => {
          registerLocaleData(module.default);
          resolve();
        },
        () => {
          System.import(`@angular/common/locales/${localeId.split('-')[0]}.js`).then(module => {
            registerLocaleData(module.default);
            resolve();
          }, reject);
        }
      );
    });
  }

答案 1 :(得分:0)

我遇到了与angular4相同的问题我想使用多种语言的AOT。这就是我所做的:

管道周围的简单包装以设置区域设置。

@Pipe({name: 'datepipe', pure: true})
export class MyDatePipe extends DatePipe implements PipeTransform {
  constructor(private win: WindowRef) {
    super(win.ln);
  }

  transform(value: any, pattern?: string): string | null {
    return super.transform(value, pattern);
  }
}

区域设置的服务:

function _window(): any {
  // return the global native browser window object
  return window;
}

@Injectable()
export class WindowRef {
  get nativeWindow(): any {
    return _window();
  }

  //default locale
  public ln = 'en';


  constructor() {
    try {
       if (!isNullOrUndefined(this.nativeWindow.navigator.language) && this.nativeWindow.navigator.language !== '') {
        this.ln = this.nativeWindow.navigator.language;
      }
    }finally {}
  }
}

这适用于angular4但有了angular5我必须在main.ts中导入支持的语言环境

import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';

registerLocaleData(localeFr);

答案 2 :(得分:0)

我遇到了同样的问题,并找到了解决方法。

我决定在资产文件夹中发布角度区域设置数据(来自cldr)。 Cldr数据来自node_mopdules \ @angular \ common \ locales(您将在typescript中导入的内容)。 就在引导程序之前,使用APP_INITIALIZER,我从给定特定locale_id的资产加载当前文化数据。

诀窍是避免使用import关键字,因为EC2015不支持动态导入。 为了从js文件中获取文化数据,我编写了这个“脏”代码:

import { Injectable, Inject, LOCALE_ID } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class LoaderService {

  constructor(protected httpClient: HttpClient,
              @Inject(LOCALE_ID) protected locale: string) { }

private async loadAngularCulture(locale) {
      let angularLocaleText = await this.httpClient.get(`assets/angular-locales/${locale}.js`).toPromise();

      // extracting the part of the js code before the data, 
      // and i didn't need the plural so i just replace plural by null.
      const startPos = angularLocaleText.indexOf('export default ');
      angularLocaleText = 'return ' + angularLocaleText.substring(startPos + 15).replace('plural', null);

      // The trick is here : to read cldr data, i use a function
      const f = new Function(angularLocaleText);
      const angularLocale = f();

      // console.log(angularLocale);

      // And now, just registrer the object you just created with the function
      registerLocaleData(angularLocale);
  }

是我的mainModule,使用APP_INITIALIZER:

export function configFactory(intlLoader: SfkIntlLoaderService) {
  return intlLoader.initializer();
}

export function localFunction() {
  // the rule to get you language according. 
  // Here, for demo, i just read it from localstorage
  return localStorage.getItem('LANGUGAGE');
}

@NgModule({
 declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  )
  ],
  providers: [
    LoaderService,
    {
      provide: LOCALE_ID,
      deps: [],
      useFactory: localFunction
    },
    {
      provide: APP_INITIALIZER,
      useFactory: configFactory,
      deps: [LoaderService],
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

希望这会有所帮助!