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

Я хочу отображать дату в европейском формате dd/mm/yyyy но используя формат DatePipe shortDate, он отображается только в американском стиле даты mm/dd/yyyy,
Я предполагаю, что по умолчанию это en_US. Может быть, мне не хватает документов, но как я могу изменить настройки локали по умолчанию в приложении Angular2? Или, может быть, есть какой-то способ передать пользовательский формат в DatePipe?

15 ответов

Решение

Начиная с 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
}

Надеюсь, это работает для вас.

Решение с 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>

или проверьте мой простой проект "Заметки" здесь.

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

С 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...
  ]
})

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

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

Сначала объявите локали, которые вы используете в своем приложении, например, в 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) { ... }

На 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' }}

Я заглянул в 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".

Пожалуйста, просветите меня, если я ошибаюсь.

Начиная с Angular 9 процесс локализации изменился. Ознакомьтесь с официальным документом.

Следуйте инструкциям ниже:

  1. Добавьте пакет локализации, если его еще нет: ng add @angular/localize
  2. Как сказано в документах:

Репозиторий Angular включает общие локали. Вы можете изменить исходный языковой стандарт своего приложения для сборки, установив исходный языковой стандарт в поле sourceLocale файла конфигурации рабочего пространства вашего приложения (angular.json). В процессе сборки (описанном в разделе "Объединение переводов в приложение" в этом руководстве) используется файл angular.json вашего приложения, чтобы автоматически установить токен LOCALE_ID и загрузить данные локали.

так что установите локаль в angular.jsonвот так (список доступных языков можно найти здесь):

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "test-app": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "i18n": {
        "sourceLocale": "es"
      },
      ....
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          ...
          "configurations": {
            "production": {
             ...
            },
            "ru": {
              "localize": ["ru"]
            },
            "es": {
              "localize": ["es"]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "test-app:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "test-app:build:production"
            },
            "ru":{
              "browserTarget": "test-app:build:ru"
            },
            "es": {
              "browserTarget": "test-app:build:es"
            }
          }
        },
        ...
      }
    },
    ...
  "defaultProject": "test-app"
}

В основном вам нужно определить sourceLocale в i18n раздел и добавьте конфигурацию сборки с определенной локалью, например "localize": ["es"]. При желании вы можете добавить это такserve раздел

  1. Создайте приложение с определенной локалью, используя build или serve: ng serve --configuration=es

Вы делаете что-то вроде этого:

{{ dateObj | date:'shortDate' }}

или же

{{ dateObj | date:'ddmmy' }}

См.: https://angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html

Я боролся с той же проблемой и не работал для меня, используя это

{{dateObj | date:'ydM'}}

Итак, я попробовал обходной путь, не лучшее решение, но оно сработало:

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

Я всегда могу создать собственную трубу.

Для тех, у кого проблемы с AOT, вам нужно сделать это немного по-другому с помощью useFactory:

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

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

Использование труб и никаких других установок.

LocalizedDatePipe.ts

      import { Pipe, PipeTransform } from '@angular/core';
import { Locale } from 'src/app/contentful/interfaces/locale';

@Pipe({
  name: 'localizedDate',
})
export class LocalizedDatePipe implements PipeTransform {
  transform(value: any, locale: any): any {
    const date = new Date(value);
    const options: Intl.DateTimeFormatOptions = {
      month: 'short',
      day: 'numeric',
      year: 'numeric',
    };
    return date.toLocaleDateString(locale, options);
  }
}

Search-overlay.component.html

      <span *ngIf="card.date" class="hero-cards-carousel__date">
 {{ card.date | localizedDate: vm.locale?.code }}
 </span>

Результат

«20 декабря 2012 г.»

Ответы выше, безусловно, правильные. Обратите внимание, что также возможно передать локаль с трубой:

        {{ now | date: undefined:undefined:'de-DE' }}

(Два первых параметра — это формат даты и часовой пояс, оставьте их неопределенными, если вы отлично подходите со значениями по умолчанию)

Не то, что вы хотите сделать для всех ваших трубок, но иногда это может быть удобно.

Скопированный канал 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); }
}

Хорошо, я предлагаю это решение, очень простое, используя 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);
  }

}

Это может быть немного поздно, но в моем случае (угловой 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);
}

Возможно, не лучшее решение, но простое и работает.

Другие вопросы по тегам