Як встановити локаль у DatePipe у Angular 2?


138

Я хочу відобразити дату у європейському форматі, dd/MM/yyyyале використовуючи формат DatePipe shortDate , вона відображається лише у стилі дати США MM/dd/yyyy.
Я припускаю, що цей локальний код за замовчуванням - це en_US. Можливо, мені не вистачає в документах, але як я можу змінити параметри локалі за замовчуванням у додатку Angular2? А може, є якийсь спосіб передати користувальницький формат DatePipe?


1
Я також хотів би це знати. Я знайшов документи з датами, які пояснюють порядок y 'm' і d 'у рядку формату, ігноруються, оскільки порядок встановлюється локалом. Але немає вказівки, як встановити (або навіть отримати) локаль.
Марк Фармілое

Відповіді:


276

Станом на Angular2 RC6, ви можете встановити локальний код за замовчуванням у своєму модулі програми, додавши постачальника:

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "en-US" }, //replace "en-US" with your locale
    //otherProviders...
  ]
})

Труби з валютою / датою / номером повинні вибрати місце. LOCALE_ID - це OpaqueToken , який потрібно імпортувати з кутового / основного.

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

Для більш розширеного випадку використання, можливо, ви захочете вибрати локальний сервіс у сервісу. Місце розташування буде вирішено (один раз), коли буде створено компонент, що використовує дату:

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

Сподіваюся, це працює для вас.


43
Я вражений, що це все ще ніде не задокументовано. Не на сторінці "Дата трубопроводу" ( angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), не на сторінці загальних труб ( angular.io/docs/ts/latest/guide/pipes .html ), і це питання насправді є першим зверненням до Google ( google.com/search?q=angular%202%20locales&rct=j ). Чудова знахідка.
JP ten Berge

2
Щоб використовувати трубу в коді, тепер її слід відформатувати як new CurrencyPipe('en-US');. Сподіваємось, це корисно для чогось, оскільки це виявилося першим результатом, коли я гуглю мою проблему.
Попелясто-блакитний

1
@corolla Чи можете ви пролити трохи світла на цю послугу? Я хотів би змінити місцевість, коли програма працює, чи можливо це за допомогою цієї послуги? І як я можу реалізувати таку послугу?
Martijn van den Bergh

1
@MartijnvandenBergh, сервіс просто повертає рядок локалі - нічого фантазійного. Під час роботи програми ми мали неоднозначні результати, намагаючись змінити місцевість. Закінчилася сторінка для перезавантаження, щоб обробити всі випадки. YMMV.
віночок

1
Я також дуже боровся з цією темою, і сподіваюся, що стаття, яку я написав про це, може допомогти деяким людям: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Michael Karén

72

Рішення з LOCALE_ID чудово, якщо ви хочете один раз встановити мову для свого додатка. Але це не працює, якщо ви хочете змінити мову під час виконання. У цьому випадку ви можете реалізувати спеціальну дату.

import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Pipe({
  name: 'localizedDate',
  pure: false
})
export class LocalizedDatePipe implements PipeTransform {

  constructor(private translateService: TranslateService) {
  }

  transform(value: any, pattern: string = 'mediumDate'): any {
    const datePipe: DatePipe = new DatePipe(this.translateService.currentLang);
    return datePipe.transform(value, pattern);
  }

}

Тепер, якщо ви змінили мову відображення програми за допомогою TranslateService (див. Ngx-translate )

this.translateService.use('en');

формати вашого додатка повинні автоматично оновлюватися.

Приклад використання:

<p>{{ 'note.created-at' | translate:{date: note.createdAt | localizedDate} }}</p>
<p>{{ 'note.updated-at' | translate:{date: note.updatedAt | localizedDate:'fullDate'} }}</p>

або перевірте мій простий проект "Примітки" тут .

введіть тут опис зображення


Я отримую помилку розбору шаблону; не вдається скласти фільтр "localizedDate", який я використовував таким же чином, як пропонувався.
Prasad Shinde

Ви правильно оголосили LocalizedDatePipe? Дивіться pipe.module.ts в моєму прикладі проекту .
Мілан Хлінак

Так, я вирішив це раніше, @Milan Hlinak, я мав би відповісти на свій коментар лише тоді. Але все одно дякую за швидку відповідь. Ви чудово робите.
Prasad Shinde

Це, мабуть, те, що я шукав. Прикро, що потрібна спеціальна труба, щоб просто змінити локальний процес під час виконання ..
dendimiiii

2
Це працює, але зверніть увагу, що використовувати "нечисті" труби повільніше, ніж "чисті". Як говорить посібник Angular : Angular виконує нечисту трубу під час кожного циклу виявлення зміни компонентів. Нечисту трубу називають часто, так само часто, як кожен натискання клавіші або переміщення миші. Зважаючи на це, з великою обережністю застосовуйте нечисту трубу. Дорога довга труба може зруйнувати досвід користувача.
Лука Рітосса

64

З angular5вищезазначеною відповіддю більше не працює!

Наступний код:

app.module.ts

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "de-at" }, //replace "de-at" with your locale
    //otherProviders...
  ]
})

Приводить до наступної помилки:

Помилка: відсутні локальні дані для локалі "де-у".

З angular5ви повинні завантажити та зареєструвати використовувану локаль файл на свій розсуд.

app.module.ts

import { NgModule, LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localeDeAt from '@angular/common/locales/de-at';

registerLocaleData(localeDeAt);

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "de-at" }, //replace "de-at" with your locale
    //otherProviders...
  ]
})

Документація


Дійсно, якщо вам потрібно використовувати інший локаль, крім en-US, вам слід зареєструвати його. Дякую за відповідь, @zgue
MikkaRin

1
Добре, що завадило мені ще один головний біль .. Thx! Документ трохи складний, тому що я хоч і цього registerLocaleDataбув достатньо, ну це не так.
небезпека89

1
Найкращий відповідь на Ionic 4!
parrycima

22

Якщо ви використовуєте TranslateServiceз @ngx-translate/core, нижче - версія без створення нової труби, яка працює з динамічним перемиканням під час виконання (тестується на Angular 7). Використання localeпараметра DatePipe ( документи ):

Спочатку оголосіть локалі, які ви використовуєте у вашій програмі, наприклад у app.component.ts:

import localeIt from '@angular/common/locales/it';
import localeEnGb from '@angular/common/locales/en-GB';
.
.
.
ngOnInit() {
    registerLocaleData(localeIt, 'it-IT');
    registerLocaleData(localeEnGb, 'en-GB');
}

Потім динамічно використовуйте трубу:

myComponent.component.html

<span>{{ dueDate | date: 'shortDate' : '' : translateService.currentLang }}</span>

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }

2
Це напрочуд приємно. Для цього вам навіть не потрібен @ ngx-translate. Чи можете ви пояснити, що робить висловлювання в шаблоні?
лама

2
@lama, dueDate (будь-яку дату, яку ви хочете відформатувати) | дата: 'shortDate' (1-й параметр для труби дати, що відповідає 'формату') : '' (2-й параметр => timeZone, "Якщо не постачається, використовується часовий пояс локальної системи кінцевого користувача".) : trasnlateService.currentLang (3-й параметр => місцеві), курча цей DatePipe
Diego Osornio

що робити, якщо ви налаштували формат? це теж буде локалізовано?
Wildhammer

12

Я переглянув date_pipe.ts, і він має два біти інформації, які цікавлять. у верхній частині розташовані наступні два рядки:

// TODO: move to a global configurable location along with other i18n components.
var defaultLocale: string = 'en-US';

У нижній частині знаходиться цей рядок:

return DateFormatter.format(value, defaultLocale, pattern);

Це підказує мені, що на сьогоднішній день трубопровідний термін важко кодований як "en-US".

Будь ласка, просвітліть мене, якщо я помиляюся.



Ви можете перевірити відповідь віночка нижче. Він більш сучасний і забезпечує чудове рішення.
Марк Лангер

9

На app.module.ts додайте наступний імпорт. Існує список опцій Locale тут .

import es from '@angular/common/locales/es';
import { registerLocaleData } from '@angular/common';
registerLocaleData(es);

Потім додайте провайдера

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "es-ES" }, //your locale
  ]
})

Використовуйте труби в html. Ось кутова документація на це.

{{ dateObject | date: 'medium' }}

Justo necesitaba esto!
alexchvrches

5

Ви робите щось подібне:

{{ dateObj | date:'shortDate' }}

або

{{ dateObj | date:'ddmmy' }}

Дивіться: https://angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html


Вибачте, якщо це було не ясно в моєму запитанні, але це саме те, що я роблю, але з малюнком 'shortDate', і це показано лише в американському стилі. Стиль часу прекрасний.
nsbm

Другий приклад показує перехід формату до DatePipe, це те, чого ви хотіли ні?
Ленглі

Спробував, але це не працює. Покажіть просто число "5" незалежно від дати.
nsbm

3

Я боровся з тим же питанням і не працював для мене, використовуючи це

{{dateObj | date:'ydM'}}

Отже, я спробував вирішити не найкраще рішення, але це спрацювало:

{{dateObj | date:'d'}}/{{dateObj | date:'M'}}/{{dateObj | date:'y'}}

Я завжди можу створити власну трубу.


3

Тим, хто має проблеми з AOT, потрібно зробити це трохи інакше за допомогою useFactory:

export function getCulture() {
    return 'fr-CA';
}

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})

4
станом на angular5, ви можете використовувати вираз жирової стрілки в масиві постачальників
липня 1717

{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}зробив трюк для мене;)
JoxieMedina

0

Скопійована труба google змінила місцевість, і вона працює для моєї країни. Можливо, вони не закінчили її для всіх локалів. Нижче наведено код.

import {
    isDate,
    isNumber,
    isPresent,
    Date,
    DateWrapper,
    CONST,
    isBlank,
    FunctionWrapper
} from 'angular2/src/facade/lang';
import {DateFormatter} from 'angular2/src/facade/intl';
import {PipeTransform, WrappedValue, Pipe, Injectable} from 'angular2/core';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';


var defaultLocale: string = 'hr';

@CONST()
@Pipe({ name: 'mydate', pure: true })
@Injectable()
export class DatetimeTempPipe implements PipeTransform {
    /** @internal */
    static _ALIASES: { [key: string]: String } = {
        'medium': 'yMMMdjms',
        'short': 'yMdjm',
        'fullDate': 'yMMMMEEEEd',
        'longDate': 'yMMMMd',
        'mediumDate': 'yMMMd',
        'shortDate': 'yMd',
        'mediumTime': 'jms',
        'shortTime': 'jm'
    };


    transform(value: any, args: any[]): string {
        if (isBlank(value)) return null;

        if (!this.supports(value)) {
            console.log("DOES NOT SUPPORT THIS DUEYE ERROR");
        }

        var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
        if (isNumber(value)) {
            value = DateWrapper.fromMillis(value);
        }
        if (StringMapWrapper.contains(DatetimeTempPipe._ALIASES, pattern)) {
            pattern = <string>StringMapWrapper.get(DatetimeTempPipe._ALIASES, pattern);
        }
        return DateFormatter.format(value, defaultLocale, pattern);
    }

    supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
}

0

Гаразд, пропоную це рішення, дуже просте, з використанням ngx-translate

import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Pipe({
  name: 'localizedDate',
  pure: false
})
export class LocalizedDatePipe implements PipeTransform {

  constructor(private translateService: TranslateService) {
}

  transform(value: any): any {
    const date = new Date(value);

    const options = { weekday: 'long',
                  year: 'numeric',
                  month: 'long',
                  day: 'numeric',
                  hour: '2-digit',
                  minute: '2-digit',
                  second: '2-digit'
                    };

    return date.toLocaleString(this.translateService.currentLang, options);
  }

}

-1

Це може бути трохи пізно, але в моєму випадку (кутовий 6) я створив просту трубку поверх DatePipe, приблизно так:

private _regionSub: Subscription;
private _localeId: string;

constructor(private _datePipe: DatePipe, private _store: Store<any>) {
  this._localeId = 'en-AU';
  this._regionSub = this._store.pipe(select(selectLocaleId))
    .subscribe((localeId: string) => {
      this._localeId = localeId || 'en-AU';
    });
}

ngOnDestroy() { // Unsubscribe }

transform(value: string | number, format?: string): string {
  const dateFormat = format || getLocaleDateFormat(this._localeId, FormatWidth.Short);
  return this._datePipe.transform(value, dateFormat, undefined, this._localeId);
}

Можливо, це не найкраще рішення, але просте і працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.