Как установить локаль в 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 , импортируемый из angular / core.

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 Можете ли вы пролить свет на этот сервис? Я хотел бы изменить язык при запуске приложения, возможно ли это с помощью этой службы? И как мне реализовать такой сервис?
Мартейн ван ден Берг

1
@MartijnvandenBergh, сервис просто возвращает строку локали - ничего сложного. У нас были смешанные результаты, пытаясь изменить локаль во время работы приложения. Завершена перезагрузка страницы для обработки всех случаев. YMMV.
венчик

1
Я также много боролся с этой темой, и я надеюсь, что статья, которую я написал об этом, может помочь некоторым людям: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Майкл Карен,

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', который я использовал таким же образом, как предложено.
Прасад

Вы правильно объявили LocalizedDatePipe? Смотрите pipe.module.ts в моем примере проекта .
Милан Хлинак

Да, я решил это раньше, @Milan Hlinak Я должен был ответить на мой комментарий только в то время. Но в любом случае спасибо за ваш быстрый ответ. У тебя все отлично.
Прасад Шинде

Это, видимо, то, что я искал. Это позор, что пользовательский канал требуется просто изменить Locale во время выполнения, хотя ..
dendimiiii

2
Это работает, но обратите внимание, что использовать «нечистые» трубы медленнее, чем «чистые». Как говорит руководство Angular : Angular выполняет нечистую трубу во время каждого цикла обнаружения изменений компонентов. Нечистый канал вызывается часто, так же часто, как каждое нажатие клавиши или движение мыши. Помня об этом, осторожно используйте нечистую трубу. Дорогая, долго работающая труба может разрушить пользовательский опыт.
Лука Ритосса

64

С angular5приведенным выше ответом больше не работает!

Следующий код:

app.module.ts

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

Приводит к следующей ошибке:

Ошибка: отсутствуют данные локали для локали "de-at".

При этом 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
Хорошо, что помешало мне еще одну головную боль .. Спасибо! Документ немного сложный, так как я, хотя этого registerLocaleDataбыло достаточно, ну, это не так.
danger89

1
Лучший ответ для Ionic 4!
parrycima

22

Если вы используете TranslateServicefrom @ngx-translate/core, ниже приведена версия без создания нового канала, который работает с динамическим переключением во время выполнения (протестировано на Angular 7). Используя localeпараметр DatePipe ( docs ):

Сначала объявите локали, которые вы используете в своем приложении, например 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 (любая дата, которую вы хотите отформатировать) | date: 'shortDate' (1-й параметр для конвейера даты, соответствующий 'format') : '' (2-й параметр => timeZone, "Если не указан, использует часовой пояс локальной системы конечного пользователя".) : trasnlateService.currentLang (3-й параметр => местный), чик это DatePipe
Диего Осорнио

Что делать, если вы настроили формат? это тоже будет локализовано?
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, вы можете использовать жирное стрелочное выражение в массиве provider
iuliust

{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}сделал
свое дело

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.