Localize dates, counts (#5027)

* refactor: consistent localized formatting

* refactor: localized date time

* refactor: localize relative time with strings

* chore: fix typo from copy-paste

* Clean up useTimeAgo

* Remove old ago

* Const

* Reuse

* Prettier

---------

Co-authored-by: Mary <git@mary.my.id>
This commit is contained in:
Eric Bailey 2024-08-29 19:22:53 -05:00 committed by GitHub
parent d5a7618374
commit 8651f31ebb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 375 additions and 186 deletions

View file

@ -377,7 +377,7 @@ function Inner({
hide: () => void
}) {
const t = useTheme()
const {_} = useLingui()
const {_, i18n} = useLingui()
const {currentAccount} = useSession()
const moderation = React.useMemo(
() => moderateProfile(profile, moderationOpts),
@ -393,8 +393,8 @@ function Inner({
profile.viewer?.blocking ||
profile.viewer?.blockedBy ||
profile.viewer?.blockingByList
const following = formatCount(profile.followsCount || 0)
const followers = formatCount(profile.followersCount || 0)
const following = formatCount(i18n, profile.followsCount || 0)
const followers = formatCount(i18n, profile.followersCount || 0)
const pluralizedFollowers = plural(profile.followersCount || 0, {
one: 'follower',
other: 'followers',

View file

@ -43,7 +43,7 @@ function EmbedDialogInner({
timestamp,
}: Omit<EmbedDialogProps, 'control'>) {
const t = useTheme()
const {_} = useLingui()
const {_, i18n} = useLingui()
const ref = useRef<TextInput>(null)
const [copied, setCopied] = useState(false)
@ -86,9 +86,9 @@ function EmbedDialogInner({
)} (<a href="${escapeHtml(profileHref)}">@${escapeHtml(
postAuthor.handle,
)}</a>) <a href="${escapeHtml(href)}">${escapeHtml(
niceDate(timestamp),
niceDate(i18n, timestamp),
)}</a></blockquote><script async src="${EMBED_SCRIPT}" charset="utf-8"></script>`
}, [postUri, postCid, record, timestamp, postAuthor])
}, [i18n, postUri, postCid, record, timestamp, postAuthor])
return (
<Dialog.Inner label="Embed post" style={[a.gap_md, {maxWidth: 500}]}>

View file

@ -11,6 +11,7 @@ import {
ChatBskyConvoDefs,
RichText as RichTextAPI,
} from '@atproto/api'
import {I18n} from '@lingui/core'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@ -153,14 +154,14 @@ let MessageItemMetadata = ({
)
const relativeTimestamp = useCallback(
(timestamp: string) => {
(i18n: I18n, timestamp: string) => {
const date = new Date(timestamp)
const now = new Date()
const time = new Intl.DateTimeFormat(undefined, {
const time = i18n.date(date, {
hour: 'numeric',
minute: 'numeric',
}).format(date)
})
const diff = now.getTime() - date.getTime()
@ -182,13 +183,13 @@ let MessageItemMetadata = ({
return _(msg`Yesterday, ${time}`)
}
return new Intl.DateTimeFormat(undefined, {
return i18n.date(date, {
hour: 'numeric',
minute: 'numeric',
day: 'numeric',
month: 'numeric',
year: 'numeric',
}).format(date)
})
},
[_],
)

View file

@ -1,12 +1,12 @@
import React from 'react'
import {Pressable, View} from 'react-native'
import {useLingui} from '@lingui/react'
import {android, atoms as a, useTheme, web} from '#/alf'
import * as TextField from '#/components/forms/TextField'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {CalendarDays_Stroke2_Corner0_Rounded as CalendarDays} from '#/components/icons/CalendarDays'
import {Text} from '#/components/Typography'
import {localizeDate} from './utils'
// looks like a TextField.Input, but is just a button. It'll do something different on each platform on press
// iOS: open a dialog with an inline date picker
@ -25,6 +25,7 @@ export function DateFieldButton({
isInvalid?: boolean
accessibilityHint?: string
}) {
const {i18n} = useLingui()
const t = useTheme()
const {
@ -91,7 +92,7 @@ export function DateFieldButton({
t.atoms.text,
{lineHeight: a.text_md.fontSize * 1.1875},
]}>
{localizeDate(value)}
{i18n.date(value, {timeZone: 'UTC'})}
</Text>
</Pressable>
</View>

View file

@ -1,16 +1,5 @@
import {getLocales} from 'expo-localization'
const LOCALE = getLocales()[0]
// we need the date in the form yyyy-MM-dd to pass to the input
export function toSimpleDateString(date: Date | string): string {
const _date = typeof date === 'string' ? new Date(date) : date
return _date.toISOString().split('T')[0]
}
export function localizeDate(date: Date | string): string {
const _date = typeof date === 'string' ? new Date(date) : date
return new Intl.DateTimeFormat(LOCALE.languageTag, {
timeZone: 'UTC',
}).format(_date)
}