Skip to content

Commit

Permalink
fix(datetime): support key format object (#1502) (#1569)
Browse files Browse the repository at this point in the history
  • Loading branch information
horitaka committed Oct 30, 2022
1 parent 85cb55e commit e324286
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 15 deletions.
21 changes: 15 additions & 6 deletions examples/datetime/index.html
Expand Up @@ -10,32 +10,40 @@
<body>
<div id="app">
<select v-model="locale">
<option>en-US</option>
<option>ja-JP</option>
<option value="en-US">en-US</option>
<option value="ja-JP">ja-JP</option>
</select>
<p>{{ $t('current_datetime')}}: {{ $d(now, 'long') }}</p>
<p data-testid="pastDatetime">{{ $t('past_datetime')}}: {{ $d(pastDatetime, 'long') }}</p>
<p data-testid="pastYear">{{ $t('past_year')}}: {{ $d(pastDatetime, {year: '2-digit'}) }}</p>
</div>
<script>
var messages = {
'en-US': {
current_datetime: 'current datetime'
current_datetime: 'current datetime',
past_datetime: 'past datetime',
past_year: 'past year'
},
'ja-JP': {
current_datetime: '現在の日時'
current_datetime: '現在の日時',
past_datetime: '過去の日時',
past_year: '過去の年'
}
}
var dateTimeFormats = {
'en-US': {
long: {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit'
hour: '2-digit', minute: '2-digit', second: '2-digit',
timeZone: 'America/Los_Angeles'
}
},
'ja-JP': {
long: {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hour12: true,
timeZone: 'Asia/Tokyo'
}
}
}
Expand All @@ -53,7 +61,8 @@
i18n: i18n,
data: {
locale: initial,
now: new Date()
now: new Date(),
pastDatetime: new Date(Date.UTC(2012, 11, 20, 3, 0, 0))
},
watch: {
locale: function (val) {
Expand Down
37 changes: 28 additions & 9 deletions src/index.js
Expand Up @@ -18,6 +18,7 @@ import {
includes,
merge,
numberFormatKeys,
dateTimeFormatKeys,
escapeParams
} from './util'
import BaseFormatter from './format'
Expand Down Expand Up @@ -847,7 +848,8 @@ export default class VueI18n {
locale: Locale,
fallback: FallbackLocale,
dateTimeFormats: DateTimeFormats,
key: string
key: string,
options: ?DateTimeFormatOptions
): ?DateTimeFormatResult {
let _locale: Locale = locale
let formats: DateTimeFormat = dateTimeFormats[_locale]
Expand All @@ -872,28 +874,36 @@ export default class VueI18n {
return null
} else {
const format: ?DateTimeFormatOptions = formats[key]
const id = `${_locale}__${key}`
let formatter = this._dateTimeFormatters[id]
if (!formatter) {
formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format)
let formatter
if (options) {
formatter = new Intl.DateTimeFormat(_locale, Object.assign({}, format, options))
} else {
const id = `${_locale}__${key}`
formatter = this._dateTimeFormatters[id]
if (!formatter) {
formatter = this._dateTimeFormatters[id] = new Intl.DateTimeFormat(_locale, format)
}
}
return formatter.format(value)
}
}
_d (value: number | Date, locale: Locale, key: ?string): DateTimeFormatResult {
_d (value: number | Date, locale: Locale, key: ?string, options: ?DateTimeFormatOptions): DateTimeFormatResult {
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && !VueI18n.availabilities.dateTimeFormat) {
warn('Cannot format a Date value due to not supported Intl.DateTimeFormat.')
return ''
}

if (!key) {
return new Intl.DateTimeFormat(locale).format(value)
const dtf = !options ? new Intl.DateTimeFormat(locale) : new Intl.DateTimeFormat(locale, options)
return dtf.format(value)
}

const ret: ?DateTimeFormatResult =
this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key)
this._localizeDateTime(value, locale, this.fallbackLocale, this._getDateTimeFormats(), key, options)
if (this._isFallbackRoot(ret)) {
if (process.env.NODE_ENV !== 'production' && !this._isSilentTranslationWarn(key) && !this._isSilentFallbackWarn(key)) {
warn(`Fall back to datetime localization of root: key '${key}'.`)
Expand All @@ -909,6 +919,7 @@ export default class VueI18n {
d (value: number | Date, ...args: any): DateTimeFormatResult {
let locale: Locale = this.locale
let key: ?string = null
let options: ?DateTimeFormatOptions = null

if (args.length === 1) {
if (isString(args[0])) {
Expand All @@ -921,6 +932,14 @@ export default class VueI18n {
key = args[0].key
}
}

options = Object.keys(args[0]).reduce((acc, key) => {
if (includes(dateTimeFormatKeys, key)) {
return Object.assign({}, acc, { [key]: args[0][key] })
}
return acc
}, null)

} else if (args.length === 2) {
if (isString(args[0])) {
key = args[0]
Expand All @@ -930,7 +949,7 @@ export default class VueI18n {
}
}

return this._d(value, locale, key)
return this._d(value, locale, key, options)
}

getNumberFormat (locale: Locale): NumberFormat {
Expand Down
12 changes: 12 additions & 0 deletions src/util.js
Expand Up @@ -24,6 +24,18 @@ export const numberFormatKeys = [
'maximumSignificantDigits'
]

export const dateTimeFormatKeys = [
'weekday',
'era',
'year',
'month',
'day',
'hour',
'minute',
'second',
'timeZoneName'
]

/**
* utilities
*/
Expand Down
13 changes: 13 additions & 0 deletions test/e2e/test/datetime.js
@@ -0,0 +1,13 @@
module.exports = {
number: function (browser) {
browser
.url('http://localhost:8080/examples/datetime/')
.waitForElementVisible('#app', 1000)
.assert.containsText('p[data-testid="pastDatetime"]', '過去の日時: 2012/12/20 午後00:00:00')
.assert.containsText('p[data-testid="pastYear"]', '過去の年: 12年')
.click('select option[value=en-US]')
.assert.containsText('p[data-testid="pastDatetime"]', 'past datetime: 12/19/2012, 07:00:00 PM')
.assert.containsText('p[data-testid="pastYear"]', 'past year: 12')
.end()
}
}

0 comments on commit e324286

Please sign in to comment.