refactor: localize relative time with strings
This commit is contained in:
+51
-30
@@ -1,7 +1,5 @@
|
|||||||
import {I18n} from '@lingui/core'
|
import {I18n} from '@lingui/core'
|
||||||
import {msg} from '@lingui/macro'
|
import {defineMessage, msg} from '@lingui/macro'
|
||||||
|
|
||||||
import {MONTH_FALLBACK_LOCALES} from '#/locale/constants'
|
|
||||||
|
|
||||||
const NOW = 5
|
const NOW = 5
|
||||||
const MINUTE = 60
|
const MINUTE = 60
|
||||||
@@ -18,33 +16,57 @@ export function ago(i18n: I18n, date: number | string | Date): string {
|
|||||||
} else {
|
} else {
|
||||||
ts = date
|
ts = date
|
||||||
}
|
}
|
||||||
|
|
||||||
const diffSeconds = Math.floor((Date.now() - ts) / 1e3)
|
const diffSeconds = Math.floor((Date.now() - ts) / 1e3)
|
||||||
|
|
||||||
|
// We can't use `i18n.number` with a `unit` format here because ICU (which
|
||||||
|
// provides localization data) doesn't seem to have narrow unit display
|
||||||
|
// formatting for locales like Japanese, Spanish, French and Turkish.
|
||||||
|
|
||||||
|
// We'll use `defineMessage` here instead of our usual `msg` as we can pass
|
||||||
|
// an object with a `comment` property that better describes what these
|
||||||
|
// strings are supposed to be. These comments get stripped out in production.
|
||||||
|
|
||||||
|
// Intermediate variables are created to improve the interpolation keys.
|
||||||
|
|
||||||
if (diffSeconds < NOW) {
|
if (diffSeconds < NOW) {
|
||||||
return i18n._(msg`now`)
|
return i18n._(msg`now`)
|
||||||
} else if (diffSeconds < MINUTE) {
|
} else if (diffSeconds < MINUTE) {
|
||||||
return i18n.number(diffSeconds, {
|
const seconds = diffSeconds
|
||||||
style: 'unit',
|
|
||||||
unitDisplay: 'narrow',
|
return i18n._(
|
||||||
unit: 'second',
|
defineMessage({
|
||||||
})
|
message: `${seconds}s`,
|
||||||
|
comment: `How many seconds has passed, displayed in a narrow form`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else if (diffSeconds < HOUR) {
|
} else if (diffSeconds < HOUR) {
|
||||||
return i18n.number(Math.floor(diffSeconds / MINUTE), {
|
const minutes = Math.floor(diffSeconds / MINUTE)
|
||||||
style: 'unit',
|
|
||||||
unitDisplay: 'narrow',
|
return i18n._(
|
||||||
unit: 'minute',
|
defineMessage({
|
||||||
})
|
message: `${minutes}m`,
|
||||||
|
comment: `How many minutes has passed, displayed in a narrow form`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else if (diffSeconds < DAY) {
|
} else if (diffSeconds < DAY) {
|
||||||
return i18n.number(Math.floor(diffSeconds / HOUR), {
|
const hours = Math.floor(diffSeconds / HOUR)
|
||||||
style: 'unit',
|
|
||||||
unitDisplay: 'narrow',
|
return i18n._(
|
||||||
unit: 'hour',
|
defineMessage({
|
||||||
})
|
message: `${hours}h`,
|
||||||
|
comment: `How many minutes has passed, displayed in a narrow form`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else if (diffSeconds < MONTH_30) {
|
} else if (diffSeconds < MONTH_30) {
|
||||||
return i18n.number(Math.round(diffSeconds / DAY), {
|
const days = Math.round(diffSeconds / DAY)
|
||||||
style: 'unit',
|
|
||||||
unitDisplay: 'narrow',
|
return i18n._(
|
||||||
unit: 'day',
|
defineMessage({
|
||||||
})
|
message: `${days}d`,
|
||||||
|
comment: `How many minutes has passed, displayed in a narrow form`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let months = diffSeconds / MONTH
|
let months = diffSeconds / MONTH
|
||||||
if (months % 1 >= 0.9) {
|
if (months % 1 >= 0.9) {
|
||||||
@@ -54,13 +76,12 @@ export function ago(i18n: I18n, date: number | string | Date): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (months < 12) {
|
if (months < 12) {
|
||||||
if (MONTH_FALLBACK_LOCALES.includes(i18n.locale)) return `${months}mo`
|
return i18n._(
|
||||||
|
defineMessage({
|
||||||
return i18n.number(months, {
|
message: `${months}mo`,
|
||||||
style: 'unit',
|
comment: `How many months has passed, displayed in a narrow form`,
|
||||||
unitDisplay: 'narrow',
|
}),
|
||||||
unit: 'month',
|
)
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return i18n.date(new Date(ts))
|
return i18n.date(new Date(ts))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
// The narrow unit display for `month` in English is `m`, which conflicts with
|
|
||||||
// the one for `minute` (also `m`), this also goes for any locale that currently
|
|
||||||
// falls back to English for narrow-unit display (missing localization?)
|
|
||||||
export const MONTH_FALLBACK_LOCALES = ['en', 'ja', 'es', 'fr', 'tr']
|
|
||||||
Reference in New Issue
Block a user