如何在Angular 2的DatePipe中设置语言环境?


138

我想使用欧洲格式显示日期,dd/MM/yyyy但使用DatePipe shortDate格式仅使用美国日期样式显示MM/dd/yyyy
我假设多数民众赞成在默认语言环境是en_US。也许我在文档中找不到,但是如何更改Angular2应用程序中的默认语言环境设置?也许有某种方法可以将自定义格式传递给DatePipe?


1
我也想知道这一点。我发现日期管道文档解释了格式字符串中y的m和d的顺序,因为该顺序是由语言环境设置的。但是没有指示如何设置(甚至获取)语言环境。
Mark Farmiloe '16

Answers:


275

从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 10 Berge,

2
要在代码中使用管道,您现在必须将其格式设置为new CurrencyPipe('en-US');。希望这对某些事情很有用,因为这是在Google搜索我的问题时的第一个结果。
Ash Blue

1
@corolla您可以对这项服务有所了解吗?我想在应用运行时更改语言环境,使用该服务可以吗?我将如何实施这种服务?
Martijn van den Bergh

1
@MartijnvandenBergh,该服务仅返回语言环境字符串-没什么花哨的。尝试在应用运行时更改语言环境的结果参差不齐。结束了重新加载页面以处理所有情况。YMMV。
花冠

1
我在这个主题上也做了大量的工作,希望我写的这篇文章能对某些人有所帮助:medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
MichaelKarén19年

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>

在此处检查我的简单“ Notes”项目。

在此处输入图片说明


我收到模板解析错误;无法以建议的相同方式编译过滤器“ 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...
  ]
})

导致以下错误:

错误:缺少语言环境“ 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足够了,但事实并非如此。
危险89年

1
离子4的最佳答案!
parrycima

22

如果您使用TranslateServicefrom @ngx-translate/core,则下面是没有创建新管道的版本,该管道可在运行时动态切换(在Angular 7上进行了测试)。使用DatePipe的locale参数(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' (与'format'相对应的日期管道的第一个参数) :” (第二个参数=> timeZone,“未提供时,使用最终用户的本地系统时区”。)trasnlateService.currentLang (第三个参数=>本地),将此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”。

如果我错了,请赐教。



您可能想在下面查看花冠的答案。它是最新的,并提供了很好的解决方案。
Mark Langer

9

在app.module.ts上添加以下导入。有区域设置选项列表在这里

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开始,您可以在providers数组中使用粗箭头表达式
iuliust

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

可能不是最好的解决方案,但简单可行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.