Improve notification localization (#5550)

* Improve notification localization (#3911)

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update PostMeta.tsx

* Update RightNav.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* a11y

* Update FeedItem.tsx

* Update PostThreadItem.tsx

* Update PostThreadItem.tsx

* revert

* Update FeedItem.tsx

* Update FeedItem.tsx

* Update FeedItem.tsx

* Revert "Merge remote-tracking branch 'upstream/main' into Improve-notification-localization"

This reverts commit f435d1e7ed, reversing
changes made to dae2aee676.

* Reapply "Merge remote-tracking branch 'upstream/main' into Improve-notification-localization"

This reverts commit c93ac19048.

* Update ThreadgateBtn.tsx

* Rm import edits for now

* Cleanups

---------

Co-authored-by: Minseo Lee <itoupluk427@gmail.com>
This commit is contained in:
Eric Bailey
2024-10-31 12:11:54 -05:00
committed by GitHub
parent 1e32327de0
commit 41452de165
+168 -61
View File
@@ -1,4 +1,10 @@
import React, {memo, useEffect, useMemo, useState} from 'react' import React, {
memo,
type ReactElement,
useEffect,
useMemo,
useState,
} from 'react'
import { import {
Animated, Animated,
Pressable, Pressable,
@@ -17,7 +23,7 @@ import {
} from '@atproto/api' } from '@atproto/api'
import {AtUri} from '@atproto/api' import {AtUri} from '@atproto/api'
import {TID} from '@atproto/common-web' import {TID} from '@atproto/common-web'
import {msg, plural, Trans} from '@lingui/macro' import {msg, Plural, plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native' import {useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
@@ -167,7 +173,32 @@ let FeedItem = ({
) )
} }
let action = '' const niceTimestamp = niceDate(i18n, item.notification.indexedAt)
const firstAuthor = authors[0]
const firstAuthorName = sanitizeDisplayName(
firstAuthor.profile.displayName || firstAuthor.profile.handle,
)
const firstAuthorLink = (
<TextLink
key={firstAuthor.href}
style={[pal.text, s.bold]}
href={firstAuthor.href}
text={
<Text emoji style={[pal.text, s.bold]}>
{forceLTR(firstAuthorName)}
</Text>
}
disableMismatchWarning
/>
)
const additionalAuthorsCount = authors.length - 1
const hasMultipleAuthors = additionalAuthorsCount > 0
const formattedAuthorsCount = hasMultipleAuthors
? formatCount(i18n, additionalAuthorsCount)
: ''
let a11yLabel = ''
let notificationContent: ReactElement
let icon = ( let icon = (
<HeartIconFilled <HeartIconFilled
size="xl" size="xl"
@@ -177,10 +208,55 @@ let FeedItem = ({
]} ]}
/> />
) )
if (item.type === 'post-like') { if (item.type === 'post-like') {
action = _(msg`liked your post`) a11yLabel = hasMultipleAuthors
? _(
msg`${firstAuthorName} and ${plural(additionalAuthorsCount, {
one: `${formattedAuthorsCount} other`,
other: `${formattedAuthorsCount} others`,
})} liked your post`,
)
: _(msg`${firstAuthorName} liked your post`)
notificationContent = hasMultipleAuthors ? (
<Trans>
{firstAuthorLink} and{' '}
<Text style={[pal.text, s.bold]}>
<Plural
value={additionalAuthorsCount}
one={`${formattedAuthorsCount} other`}
other={`${formattedAuthorsCount} others`}
/>
</Text>{' '}
liked your post
</Trans>
) : (
<Trans>{firstAuthorLink} liked your post</Trans>
)
} else if (item.type === 'repost') { } else if (item.type === 'repost') {
action = _(msg`reposted your post`) a11yLabel = hasMultipleAuthors
? _(
msg`${firstAuthorName} and ${plural(additionalAuthorsCount, {
one: `${formattedAuthorsCount} other`,
other: `${formattedAuthorsCount} others`,
})} reposted your post`,
)
: _(msg`${firstAuthorName} reposted your post`)
notificationContent = hasMultipleAuthors ? (
<Trans>
{firstAuthorLink} and{' '}
<Text style={[pal.text, s.bold]}>
<Plural
value={additionalAuthorsCount}
one={`${formattedAuthorsCount} other`}
other={`${formattedAuthorsCount} others`}
/>
</Text>{' '}
reposted your post
</Trans>
) : (
<Trans>{firstAuthorLink} reposted your post</Trans>
)
icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} /> icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} />
} else if (item.type === 'follow') { } else if (item.type === 'follow') {
let isFollowBack = false let isFollowBack = false
@@ -204,40 +280,96 @@ let FeedItem = ({
} }
} }
if (isFollowBack) { if (isFollowBack && !hasMultipleAuthors) {
action = _(msg`followed you back`) /*
* Follow-backs are ungrouped, grouped follow-backs not supported atm,
* see `src/state/queries/notifications/util.ts`
*/
a11yLabel = _(msg`${firstAuthorName} followed you back`)
notificationContent = <Trans>{firstAuthorLink} followed you back</Trans>
} else { } else {
action = _(msg`followed you`) a11yLabel = hasMultipleAuthors
? _(
msg`${firstAuthorName} and ${plural(additionalAuthorsCount, {
one: `${formattedAuthorsCount} other`,
other: `${formattedAuthorsCount} others`,
})} followed you`,
)
: _(msg`${firstAuthorName} followed you`)
notificationContent = hasMultipleAuthors ? (
<Trans>
{firstAuthorLink} and{' '}
<Text style={[pal.text, s.bold]}>
<Plural
value={additionalAuthorsCount}
one={`${formattedAuthorsCount} other`}
other={`${formattedAuthorsCount} others`}
/>
</Text>{' '}
followed you
</Trans>
) : (
<Trans>{firstAuthorLink} followed you</Trans>
)
} }
icon = <PersonPlusIcon size="xl" style={{color: t.palette.primary_500}} /> icon = <PersonPlusIcon size="xl" style={{color: t.palette.primary_500}} />
} else if (item.type === 'feedgen-like') { } else if (item.type === 'feedgen-like') {
action = _(msg`liked your custom feed`) a11yLabel = hasMultipleAuthors
? _(
msg`${firstAuthorName} and ${plural(additionalAuthorsCount, {
one: `${formattedAuthorsCount} other`,
other: `${formattedAuthorsCount} others`,
})} liked your custom feed`,
)
: _(msg`${firstAuthorName} liked your custom feed`)
notificationContent = hasMultipleAuthors ? (
<Trans>
{firstAuthorLink} and{' '}
<Text style={[pal.text, s.bold]}>
<Plural
value={additionalAuthorsCount}
one={`${formattedAuthorsCount} other`}
other={`${formattedAuthorsCount} others`}
/>
</Text>{' '}
liked your custom feed
</Trans>
) : (
<Trans>{firstAuthorLink} liked your custom feed</Trans>
)
} else if (item.type === 'starterpack-joined') { } else if (item.type === 'starterpack-joined') {
a11yLabel = hasMultipleAuthors
? _(
msg`${firstAuthorName} and ${plural(additionalAuthorsCount, {
one: `${formattedAuthorsCount} other`,
other: `${formattedAuthorsCount} others`,
})} signed up with your starter pack`,
)
: _(msg`${firstAuthorName} signed up with your starter pack`)
notificationContent = hasMultipleAuthors ? (
<Trans>
{firstAuthorLink} and{' '}
<Text style={[pal.text, s.bold]}>
<Plural
value={additionalAuthorsCount}
one={`${formattedAuthorsCount} other`}
other={`${formattedAuthorsCount} others`}
/>
</Text>{' '}
signed up with your starter pack
</Trans>
) : (
<Trans>{firstAuthorLink} signed up with your starter pack</Trans>
)
icon = ( icon = (
<View style={{height: 30, width: 30}}> <View style={{height: 30, width: 30}}>
<StarterPack width={30} gradient="sky" /> <StarterPack width={30} gradient="sky" />
</View> </View>
) )
action = _(msg`signed up with your starter pack`)
} else { } else {
return null return null
} }
a11yLabel += ` · ${niceTimestamp}`
const formattedCount =
authors.length > 1 ? formatCount(i18n, authors.length - 1) : ''
const firstAuthorName = sanitizeDisplayName(
authors[0].profile.displayName || authors[0].profile.handle,
)
const niceTimestamp = niceDate(i18n, item.notification.indexedAt)
const a11yLabelUsers =
authors.length > 1
? _(msg` and `) +
plural(authors.length - 1, {
one: `${formattedCount} other`,
other: `${formattedCount} others`,
})
: ''
const a11yLabel = `${firstAuthorName}${a11yLabelUsers} ${action} ${niceTimestamp}`
return ( return (
<Link <Link
@@ -260,7 +392,7 @@ let FeedItem = ({
accessibilityLabel={a11yLabel} accessibilityLabel={a11yLabel}
accessible={!isAuthorsExpanded} accessible={!isAuthorsExpanded}
accessibilityActions={ accessibilityActions={
authors.length > 1 hasMultipleAuthors
? [ ? [
{ {
name: 'toggleAuthorsExpanded', name: 'toggleAuthorsExpanded',
@@ -288,7 +420,6 @@ let FeedItem = ({
onToggleAuthorsExpanded() onToggleAuthorsExpanded()
} }
}} }}
onBeforePress={onBeforePress}
onPointerEnter={() => { onPointerEnter={() => {
setHover(true) setHover(true)
}} }}
@@ -303,7 +434,7 @@ let FeedItem = ({
</View> </View>
<View style={styles.layoutContent}> <View style={styles.layoutContent}>
<ExpandListPressable <ExpandListPressable
hasMultipleAuthors={authors.length > 1} hasMultipleAuthors={hasMultipleAuthors}
onToggleAuthorsExpanded={onToggleAuthorsExpanded}> onToggleAuthorsExpanded={onToggleAuthorsExpanded}>
<CondensedAuthorsList <CondensedAuthorsList
visible={!isAuthorsExpanded} visible={!isAuthorsExpanded}
@@ -313,42 +444,18 @@ let FeedItem = ({
/> />
<ExpandedAuthorsList visible={isAuthorsExpanded} authors={authors} /> <ExpandedAuthorsList visible={isAuthorsExpanded} authors={authors} />
<Text <Text
style={[styles.meta, a.self_start]} style={[styles.meta, a.self_start, pal.text]}
accessibilityHint="" accessibilityHint=""
accessibilityLabel={a11yLabel}> accessibilityLabel={a11yLabel}>
<TextLink {notificationContent}
key={authors[0].href}
style={[pal.text, s.bold]}
href={authors[0].href}
text={
<Text emoji style={[pal.text, s.bold]}>
{forceLTR(firstAuthorName)}
</Text>
}
disableMismatchWarning
/>
{authors.length > 1 ? (
<>
<Text style={[pal.text]}>
{' '}
<Trans>and</Trans>{' '}
</Text>
<Text style={[pal.text, s.bold]}>
{plural(authors.length - 1, {
one: `${formattedCount} other`,
other: `${formattedCount} others`,
})}
</Text>
</>
) : undefined}
<Text style={[pal.text]}> {action}</Text>
<TimeElapsed timestamp={item.notification.indexedAt}> <TimeElapsed timestamp={item.notification.indexedAt}>
{({timeElapsed}) => ( {({timeElapsed}) => (
<Text <>
style={[pal.textLight, styles.pointer]} <Text style={[a.ml_xs, pal.textLight]}>&middot;</Text>
title={niceTimestamp}> <Text style={[a.ml_xs, pal.textLight]} title={niceTimestamp}>
{' ' + timeElapsed} {timeElapsed}
</Text> </Text>
</>
)} )}
</TimeElapsed> </TimeElapsed>
</Text> </Text>