Impove Intl formatting (#5372)
* Improve Intl formatting * Additional fixes * Fixed formatters were not updated on locale change * Fixed formatNumber was not updated on locale change * Additional formatting and fixes after merge * Run prepr:frontend * Remove `'` in icon map * Run `pnpm install` * fix: lint + import * Additional fixes --------- Co-authored-by: Calum H. <calum@modrinth.com> Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
@@ -1,35 +1,14 @@
|
||||
import { computed, type ComputedRef } from 'vue'
|
||||
import { LRUCache } from 'lru-cache'
|
||||
|
||||
import { injectI18n } from '../providers/i18n'
|
||||
import { LOCALES } from './i18n.ts'
|
||||
|
||||
export type Formatter = (
|
||||
value: Date | number | null | string | undefined,
|
||||
options?: FormatOptions,
|
||||
) => string
|
||||
const formatterCache = new LRUCache<string, Intl.RelativeTimeFormat>({ max: 5 })
|
||||
|
||||
export interface FormatOptions {
|
||||
roundingMode?: 'halfExpand' | 'floor' | 'ceil'
|
||||
}
|
||||
|
||||
const formatters = new Map<string, ComputedRef<Intl.RelativeTimeFormat>>()
|
||||
|
||||
export function useRelativeTime(): Formatter {
|
||||
export function useRelativeTime() {
|
||||
const { locale } = injectI18n()
|
||||
|
||||
const formatterRef = computed(() => {
|
||||
const localeDefinition = LOCALES.find((loc) => loc.code === locale.value)
|
||||
return new Intl.RelativeTimeFormat(locale.value, {
|
||||
numeric: localeDefinition?.numeric || 'auto',
|
||||
style: 'long',
|
||||
})
|
||||
})
|
||||
|
||||
if (!formatters.has(locale.value)) {
|
||||
formatters.set(locale.value, formatterRef)
|
||||
}
|
||||
|
||||
return (value: Date | number | null | string | undefined) => {
|
||||
return (value: Date | number | string | null | undefined) => {
|
||||
if (value == null) {
|
||||
return ''
|
||||
}
|
||||
@@ -50,7 +29,7 @@ export function useRelativeTime(): Formatter {
|
||||
const months = Math.round(diff / 2629746000)
|
||||
const years = Math.round(diff / 31556952000)
|
||||
|
||||
const rtf = formatterRef.value
|
||||
const rtf = getFormatter(locale.value)
|
||||
|
||||
if (Math.abs(seconds) < 60) {
|
||||
return rtf.format(seconds, 'second')
|
||||
@@ -69,3 +48,16 @@ export function useRelativeTime(): Formatter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getFormatter(locale: string): Intl.RelativeTimeFormat {
|
||||
let formatter = formatterCache.get(locale)
|
||||
if (!formatter) {
|
||||
const localeDefinition = LOCALES.find((loc) => loc.code === locale)
|
||||
formatter = new Intl.RelativeTimeFormat(locale, {
|
||||
numeric: localeDefinition?.numeric || 'auto',
|
||||
style: 'long',
|
||||
})
|
||||
formatterCache.set(locale, formatter)
|
||||
}
|
||||
return formatter
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user