Як встановити локаль у 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.