Bagaimana cara mengatur lokal di DatePipe di Angular 2?

144

Saya ingin menampilkan Tanggal menggunakan format Eropa dd/MM/yyyytetapi menggunakan format TanggalPipe Tanggal pendek hanya ditampilkan menggunakan gaya tanggal AS MM/dd/yyyy.
Saya berasumsi bahwa lokal default adalah en_US. Mungkin saya tidak ada di dokumen tetapi bagaimana saya bisa mengubah pengaturan lokal default di aplikasi Angular2? Atau mungkin adakah cara untuk meneruskan format kustom ke DatePipe?

nsbm
sumber
1
Saya ingin tahu ini juga. Saya telah menemukan dokumen pipa tanggal yang menjelaskan urutan huruf y m 'dan d dalam format string diabaikan karena urutan ditetapkan oleh lokal. Tapi tidak ada indikasi bagaimana mengatur (atau bahkan mendapatkan) lokal.
Mark Farmiloe

Jawaban:

284

Mulai Angular2 RC6, Anda bisa menyetel lokal default di modul aplikasi Anda, dengan menambahkan penyedia:

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

Pipa Currency / Date / Number harus menangkap lokal. LOCALE_ID adalah OpaqueToken , untuk diimpor dari sudut / inti.

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

Untuk kasus penggunaan yang lebih maju, Anda mungkin ingin mengambil lokal dari layanan. Lokal akan diselesaikan (sekali) ketika komponen yang menggunakan pipa tanggal dibuat:

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

Semoga berhasil untuk Anda.

daun mahkota
sumber
50
Saya kagum ini sepertinya masih belum didokumentasikan di mana pun. Bukan di halaman Pipa Tanggal ( angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), bukan di halaman pipa umum ( angular.io/docs/ts/latest/guide/pipes .html ) dan pertanyaan ini sebenarnya adalah hit pertama di Google ( google.com/search?q=angular%202%20locales&rct=j ). Great ditemukan.
JP ten Berge
2
Untuk menggunakan pipa dalam kode, Anda sekarang harus memformatnya sebagai new CurrencyPipe('en-US');. Semoga ini berguna untuk sesuatu karena ini muncul sebagai hasil pertama saat mencari masalah saya di Google.
Ash Blue
1
@corolla Bisakah Anda menjelaskan layanan itu? Saya ingin mengubah lokal saat aplikasi berjalan, apakah mungkin dengan layanan itu? Dan bagaimana saya menerapkan layanan tersebut?
Martijn van den Bergh
1
@ MartijnvandenBergh, layanan hanya mengembalikan string lokal - tidak ada yang mewah. Kami mendapatkan hasil yang beragam saat mencoba mengubah lokal saat aplikasi berjalan. Akhirnya memuat ulang halaman untuk menangani semua kasus. YMMV.
corolla
1
Saya juga berjuang keras dengan subjek ini dan saya harap artikel yang saya tulis tentang ini dapat membantu beberapa orang: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Michael Karén
74

Solusi dengan LOCALE_ID sangat bagus jika Anda ingin menyetel bahasa untuk aplikasi Anda sekali. Tapi itu tidak berhasil, jika Anda ingin mengubah bahasa selama runtime. Untuk kasus ini, Anda dapat menerapkan pipa tanggal khusus.

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

}

Sekarang jika Anda mengubah bahasa tampilan aplikasi menggunakan TranslateService (lihat ngx-translate )

this.translateService.use('en');

format dalam aplikasi Anda akan diperbarui secara otomatis.

Contoh penggunaan:

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

atau periksa proyek "Catatan" saya di sini .

masukkan deskripsi gambar di sini

Milan Hlinák
sumber
Saya mendapatkan kesalahan parse template; tidak dapat mengkompilasi filter 'localizedDate' yang saya gunakan dengan cara yang sama seperti yang disarankan.
Prasad Shinde
Sudahkah Anda mendeklarasikan LocalizedDatePipe dengan benar? Lihat pipe.module.ts di proyek contoh saya .
Milan Hlinák
Ya sudah saya selesaikan tadi, @Milan Hlinak seharusnya saya jawab komentar saya waktu itu saja. Tapi bagaimanapun terima kasih atas respon cepat Anda. Kamu melakukannya dengan baik.
Prasad Shinde
Ini rupanya yang saya cari. Sayang sekali bahwa pipa khusus diperlukan untuk hanya mengubah Lokal saat runtime ..
dendimiiii
3
Ini berfungsi tetapi perhatikan bahwa menggunakan pipa "tidak murni" lebih lambat dari pada "murni". Seperti panduan Angular mengatakan: Angular mengeksekusi pipa tidak murni selama setiap siklus deteksi perubahan komponen. Pipa tidak murni sering dipanggil, sesering setiap penekanan tombol atau gerakan mouse. Dengan memperhatikan hal itu, terapkan pipa yang tidak murni dengan sangat hati-hati. Pipa yang mahal dan beroperasi lama dapat merusak pengalaman pengguna.
Luca Ritossa
66

Dengan angular5jawaban di atas tidak berfungsi lagi!

Kode berikut:

app.module.ts

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

Menyebabkan kesalahan berikut:

Kesalahan: Data lokal tidak ada untuk lokal "de-at".

Dengan angular5Anda harus memuat dan mendaftarkan file lokal yang digunakan sendiri.

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

Dokumentasi

zgue
sumber
Memang jika Anda perlu menggunakan beberapa lokal lain kecuali en-US, Anda harus mendaftarkannya. Terima kasih atas jawabannya, @zgue
MikkaRin
1
Oke, itu mencegah saya sakit kepala lagi .. Thx! Dokumennya agak rumit, karena saya pikir itu registerLocaleDatasudah cukup, yah tidak.
hazard89
1
Jawaban Terbaik untuk Ionic 4!
parrycima
28

Jika Anda menggunakan TranslateServicefrom @ngx-translate/core, di bawah ini adalah versi tanpa membuat pipa baru yang berfungsi dengan pengalihan secara dinamis pada waktu proses (diuji pada Angular 7). Menggunakan localeparameter DatePipe ( dokumen ):

Pertama, nyatakan lokal yang Anda gunakan di aplikasi Anda, misalnya di 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');
}

Kemudian, gunakan pipa Anda secara dinamis:

myComponent.component.html

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

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }
knnhcn.dll
sumber
2
Ini sangat bagus. Anda bahkan tidak perlu @ ngx-translate untuk itu. Bisakah Anda menjelaskan apa yang pernyataan dalam template itu?
lama
2
@lama, dueDate (tanggal berapa pun yang ingin Anda format) | date: 'shortDate' (parameter pertama untuk pipa tanggal sesuai dengan 'format') : '' (parameter ke-2 => timeZone, "Jika tidak disediakan, gunakan zona waktu sistem lokal pengguna akhir".) : trasnlateService.currentLang (parameter ke-3 => lokal), cewek DatePipe
Diego Osornio
bagaimana jika Anda memiliki format yang disesuaikan? apakah itu juga akan dilokalkan?
Wildhammer
Satu kekurangannya adalah Anda perlu membuat translateService menjadi publik sehingga dapat diakses oleh template ...
plgod
Mengapa tepatnya menurut Anda ini adalah kelemahan? Saya tertarik dan ingin tahu;)
knnhcn
12

Saya telah melihat-lihat di date_pipe.ts dan memiliki dua bit info yang menarik. di dekat bagian atas adalah dua baris berikut:

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

Di dekat bagian bawah adalah baris ini:

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

Ini menunjukkan kepada saya bahwa pipa tanggal saat ini di-hardcode menjadi 'en-US'.

Tolong beri tahu saya jika saya salah.

Mark Farmiloe
sumber
Anda mungkin ingin melihat jawaban corolla di bawah ini. Ini lebih mutakhir dan memberikan solusi hebat.
Mark Langer
9

Di app.module.ts tambahkan impor berikut. Ada daftar opsi LOCALE di sini .

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

Kemudian tambahkan penyedia

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

Gunakan pipa di html. Berikut adalah dokumentasi sudut untuk ini.

{{ dateObject | date: 'medium' }}
Alejandro del Río
sumber
Justo necesitaba esto!
alexchvrches
5

Anda melakukan sesuatu seperti ini:

{{ dateObj | date:'shortDate' }}

atau

{{ dateObj | date:'ddmmy' }}

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

Langley
sumber
maaf jika tidak jelas dalam pertanyaan saya tetapi ini persis apa yang saya lakukan tetapi dengan pola 'shortDate' dan itu hanya ditampilkan dalam gaya AS. Gaya waktunya bagus.
nsbm
Contoh kedua menunjukkan format yang diteruskan ke DatePipe, itu yang Anda inginkan bukan?
Langley
Sudah mencoba tapi tidak berhasil. Tunjukkan hanya angka '5' secara terpisah dari tanggal.
nsbm
3

Saya berjuang dengan masalah yang sama dan tidak berhasil untuk saya menggunakan ini

{{dateObj | date:'ydM'}}

Jadi, saya sudah mencoba solusi, bukan solusi terbaik tetapi berhasil:

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

Saya selalu dapat membuat pipa khusus.

hydrangenius
sumber
3

Bagi mereka yang mengalami masalah dengan AOT, Anda perlu melakukannya sedikit berbeda dengan useFactory:

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

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})
vidalsasoon
sumber
4
pada angular5, Anda dapat menggunakan ekspresi panah besar dalam array penyedia
iuliust
{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}melakukan trik untuk saya;)
JoxieMedina
1

Mulai dari proses lokalisasi Angular 9 diubah. Lihat dokumen resmi .

Ikuti langkah-langkah di bawah ini:

  1. Tambahkan paket pelokalan jika belum ada: ng add @angular/localize
  2. Seperti yang dikatakan di dokumen:

Repositori Angular mencakup lokal umum. Anda bisa mengubah lokal sumber aplikasi Anda untuk build dengan menyetel lokal sumber di bidang sourceLocale di file konfigurasi ruang kerja aplikasi Anda (angular.json). Proses build (dijelaskan dalam Menggabungkan terjemahan ke dalam aplikasi dalam panduan ini) menggunakan file angular.json aplikasi Anda untuk menyetel token LOCALE_ID secara otomatis dan memuat data lokal.

jadi setel lokal angular.jsonseperti ini (daftar lokal yang tersedia dapat ditemukan di sini ):

{
  "$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"
}

Pada dasarnya Anda perlu mendefinisikan sourceLocaledi i18nbagian dan menambahkan konfigurasi build dengan lokal tertentu seperti "localize": ["es"]. Opsional Anda dapat menambahkannya jadi servebagian

  1. Bangun aplikasi dengan lokal tertentu menggunakan buildatau serve:ng serve --configuration=es
Petr Pokrovskiy
sumber
0

Menyalin pipa google mengubah lokal dan berfungsi untuk negara saya, mungkin mereka tidak menyelesaikannya untuk semua lokal. Di bawah ini adalah kodenya.

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); }
}
Dživo Jelić
sumber
0

Oke, saya usulkan solusi ini, sangat sederhana, menggunakan 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);
  }

}
LizanLycan
sumber
-1

Ini mungkin sedikit terlambat, tetapi dalam kasus saya (sudut 6), saya membuat pipa sederhana di atas DatePipe, seperti ini:

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

Mungkin bukan solusi terbaik, tapi sederhana dan berhasil.

Ngoc Nam Nguyen
sumber