web-dev-qa-db-fra.com

Modifier dynamiquement les paramètres régionaux pour DatePipe dans Angular 2

Je fais un projet Angular où l'utilisateur a la possibilité de changer de langue. Est-il possible de rendre les paramètres régionaux dynamiques?

J'ai vu que vous pouvez l'ajouter dans le NgModule mais je suppose que ce n'est pas dynamique quand je le mets là? Ou puis-je le changer d'une manière ou d'une autre via un service ou quelque chose?

11

En utilisant providers, vous pouvez modifier vos paramètres régionaux par défaut dans votre NgModule. pour ce faire, vous devez importer LOCALE_ID depuis angular/core et récupérer votre langue locale pour la transmettre aux fournisseurs.

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
}

J'espère que cela vous aidera.

11
Amol Bhor

Pour définir les paramètres régionaux à partir du service, vous devez ajouter le fournisseur LOCALE_ID Avec l'usine à app.module, Comme dans la réponse @AmolBhor

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

Malheureusement, vous ne pouvez pas changer la langue de DatePipe JIT. Angular nécessite LOCALE_ID Lors du bootstrap.

Il y a quelques rapports de bugs pour Angular:

Il existe plusieurs solutions pour cela:

Solution de contournement n ° 1

Re-bootstrapping angular:

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

* Cela ne fonctionnera pas pour Hybrid Angular/AngularJS car il n'y a aucun moyen de détruire AngularJS en utilisant UpgradeModule.

Solution de contournement n ° 2

Pour remplacer DatePipe, NumberPipe - tout ce dont vous avez besoin:

@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);
  }
}

Solution de contournement # 3

Pour utiliser une bibliothèque qui gère déjà la localisation avec des tuyaux personnalisés par exemple:

Solution de contournement # 4

Chaque pipe qui utilise LOCALE_ID A un champ privé locale ou _ locale , vous pouvez donc remplacer ce champ au niveau des canaux lors du changement de langue, car il existe une instance de canal.

Cela fonctionnera parce que TypeScript n'est que du sucre syntaxique pour JavaScript. Et en JavaScript, il n'y a pas de champs privés.

N'oubliez pas non plus de traiter la détection des modifications dans l'application en utilisant la méthode tick() dans 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()
  }
}

Solution de contournement n ° 5

Pour recharger l'application lorsque la langue est modifiée.

window.location.reload()

Malheureusement, toutes ces solutions sont des solutions de contournement.

Mais il existe également une autre solution - vous pouvez avoir plusieurs bundles pour chaque langue, ce qui sera probablement une meilleure approche car l'application sera plus rapide. Mais cette solution n'est pas applicable à toutes les applications et ne répond pas à la question.

18
Anton Temchenko

Ayez votre service comme

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;
      }
    }
  }
}

Et dans App.module.ts

première localisation d'importation dont vous avez besoin, par exemple

import localeEN from '@angular/common/locales/en';
import localezhHant from '@angular/common/locales/zh-Hant';
import localezhHans from '@angular/common/locales/zh-Hans';

Que dans la section fournisseurs

{
  provide: LOCALE_ID,
  deps: [LocaleService],
  useFactory: (LocaleService: { locale: string; }) => LocaleService.locale
}

À la fin

registerLocaleData(localeEN);
registerLocaleData(localezhHant);
registerLocaleData(localezhHans);

J'espère que cela aidera quelqu'un

si vous souhaitez modifier dynamiquement les paramètres régionaux, injectez LocaleService dans le composant souhaité et utilisez la méthode registerCulture, passez votre culture requise dans ce

0
Saurabh