动态更改Angular 2中DatePipe的区域设置

Mar*_*rgh 14 locale angular2-pipe angular

我正在制作一个Angular项目,用户可以在其中切换语言.是否可以使语言环境动态化?

我已经看到你可以在NgModule中添加它,但我猜它放在那里时不是动态的吗?或者我可以通过某种服务或某种方式改变它吗?

Ant*_*nko 19

要从服务设置区域设置,您需要添加LOCALE_ID带有工厂的提供程序app.module,例如@AmolBhor答案

{
  provide: LOCALE_ID,
  deps: [SettingsService],      //some service handling global settings
  useFactory: (settingsService) => settingsService.getLanguage()  //returns locale string
}
Run Code Online (Sandbox Code Playgroud)

很遗憾,您无法更改DatePipe JIT的语言.Angular编译器LOCALE_ID在引导期间需要.

Angular有一些错误报告:

有几种解决方法:

解决方法#1

重新启动角度模块:

let _platformRef: NgModuleRef<Object>;
if(_platformRef) { _platformRef.destroy(); }
platformBrowserDynamic(providers)
    .bootstrapModule(AppModule, {providers})
    .then(platformRef => {
        _platformRef = platformRef;
    })
Run Code Online (Sandbox Code Playgroud)

*这对于Hybrid Angular/AngularJS不起作用,因为使用UpgradeModule无法破坏AngularJS.

解决方法#2

要覆盖DatePipe,NumberPipe - 无论您需要什么:

@Pipe({name: 'datepipe', pure: true})
export class MyDatePipe implements PipeTransform {
  transform(value: any, pattern?: string): string | null {
    // transform value as you like (you can use moment.js and format by locale_id from your custom service)
    return DateUtils.format(value);
  }
}
Run Code Online (Sandbox Code Playgroud)

解决方法#3

要使用已经使用自定义管道处理本地化的库,例如:

解决方法#4

每个使用的管道LOCALE_ID都有私有字段locale_locale,因此您可以在语言更改时在该管道上覆盖此字段,因为有一个管道实例.

这将起作用,因为TypeScript只是JavaScript的语法糖.在JavaScript中没有私有字段.

还记得使用tick()ApplicationRef中的方法处理应用程序中的更改检测.

@Injectable()
export class DynamicLocaleService {
  private i18nPipes: PipeTransform[];

  constructor(
    datePipe: DatePipe,
    currencyPipe: CurrencyPipe,
    decimalPipe: DecimalPipe,
    percentPipe: PercentPipe,
    private applicationRef: ApplicationRef,
  ) {
    this.i18nPipes = [
      datePipe,
      currencyPipe,
      decimalPipe,
      percentPipe,
    ]
  }

  setLocale(lang: string): void {
    this.i18nPipes.forEach(pipe => {
      if(pipe.hasOwnProperty("locale")) {
        pipe["locale"] = lang;
      } else if (pipe.hasOwnProperty("_locale")) {
        pipe["_locale"] = lang
      }
    })
    this.applicationRef.tick()
  }
}
Run Code Online (Sandbox Code Playgroud)

解决方法#5

在语言更改时重新加载应用程序.

window.location.reload()
Run Code Online (Sandbox Code Playgroud)

不幸的是,以上所有都是变通方法.

但是还有另一种解决方案 - 每种语言可以有多个捆绑包,这可能是更好的方法,因为应用程序会更快.但是这个解决方案不适用于每个应用程序,也不回答这个问题.

  • 所有语言环境都必须在 main.ts 文件中导入和注册: ``` import { registerLocaleData } from '@angular/common'; 从 '@angular/common/locales/en' 导入 locale_EN;从 '@angular/common/locales/ru' 导入 locale_RU;注册LocaleData(locale_EN); 注册LocaleData(locale_RU); ```` (2认同)

Amo*_*hor 14

使用providers您可以更改您的默认语言环境NgModule.要执行此操作您需要从angular/core导入LOCALE_ID并获取您的区域设置语言以将其传递给提供程序.

import { LOCALE_ID } from '@angular/core';

@NgModule({
    imports: [//your imports],
    providers: [
        { provide: LOCALE_ID, useValue: "en-US" }
    ]
})

...
...
{
  provide: LOCALE_ID,
  deps: [SettingsService],      //some service handling global settings
  useFactory: (settingsService) => settingsService.getLanguage()  //returns locale string
}
Run Code Online (Sandbox Code Playgroud)

希望这会帮助你.

  • 此解决方案仅适用一次.getLanguage()只被调用一次.我可以这样做,以便当我的应用程序中的某些属性发生更改时,再次调用getLanguage吗? (3认同)
  • 不,不是真的,我想让“en-US”成为一个变量,这样我就可以在应用程序运行时更改它。 (2认同)
  • @MartijnvandenBergh 您找到解决方案了吗?我也有同样的问题 (2认同)

Sau*_*abh 5

让您的服务像

import { Injectable } from '@angular/core';

@Injectable()
export class LocaleService {

  //Chosse Locale From This Link
  //https://github.com/angular/angular/tree/master/packages/common/locales
  constructor() { }

  private _locale: string;

  set locale(value: string) {
    this._locale = value;
  }
  get locale(): string {
    return this._locale || 'en-US';
  }

  public registerCulture(culture: string) {
    debugger;
    if (!culture) {
      return;
    }
    switch (culture) {
      case 'en-uk': {
        this._locale = 'en';
        console.log('Application Culture Set to English');
        break;
      }
      case 'zh-hk': {
        this._locale = 'zh-Hant';
        console.log('Application Culture Set to Traditional Chinese');
        break;
      }
      case 'zh-cn': {
        this._locale = 'zh-Hans';
        console.log('Application Culture Set to Simplified Chinese');
        break;
      }
      default: {
        this._locale = 'en';
        console.log('Application Culture Set to English');
        break;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

而在 App.module.ts

首先导入您需要的本地化,例如

import localeEN from '@angular/common/locales/en';
import localezhHant from '@angular/common/locales/zh-Hant';
import localezhHans from '@angular/common/locales/zh-Hans';
Run Code Online (Sandbox Code Playgroud)

比提供者部分

{
  provide: LOCALE_ID,
  deps: [LocaleService],
  useFactory: (LocaleService: { locale: string; }) => LocaleService.locale
}
Run Code Online (Sandbox Code Playgroud)

在末尾

registerLocaleData(localeEN);
registerLocaleData(localezhHant);
registerLocaleData(localezhHans);
Run Code Online (Sandbox Code Playgroud)

希望它会帮助某人

如果您想动态更改区域设置,请在所需组件中注入 LocaleService 并使用 registerCulture 方法,将您所需的文化传递到此