From 701d7c4659439316c0f6a7bbdcb8aa355549c3b2 Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Wed, 2 Sep 2026 07:24:34 -0700 Subject: [PATCH] Fix localization for Following and Discover feed names (#11572) --- oxlint-suppressions.json | 5 ----- src/lib/strings/feed-names.ts | 19 +++++++++++++++++++ src/view/com/home/HomeHeader.tsx | 14 +++++++++----- src/view/screens/Home.tsx | 23 ++++++++++++++++++----- src/view/shell/desktop/Feeds.tsx | 20 ++++++++++---------- 5 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 src/lib/strings/feed-names.ts diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index 354ad958ff..e3051e544c 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -1528,11 +1528,6 @@ "count": 1 } }, - "src/view/screens/Home.tsx": { - "typescript/no-floating-promises": { - "count": 1 - } - }, "src/view/screens/ModerationBlockedAccounts.tsx": { "typescript/no-misused-promises": { "count": 3 diff --git a/src/lib/strings/feed-names.ts b/src/lib/strings/feed-names.ts new file mode 100644 index 0000000000..17936dcd56 --- /dev/null +++ b/src/lib/strings/feed-names.ts @@ -0,0 +1,19 @@ +import {type I18n} from '@lingui/core' +import {msg} from '@lingui/core/macro' + +import {DISCOVER_FEED_URI, TIMELINE_SAVED_FEED} from '#/lib/constants' + +type FeedNameSource = { + displayName: string + uri: string +} + +export function getLocalizedFeedName(feed: FeedNameSource, i18n: I18n): string { + if (feed.uri === TIMELINE_SAVED_FEED.value) { + return i18n._(msg({message: 'Following', context: 'feed-name'})) + } + if (feed.uri === DISCOVER_FEED_URI) { + return i18n._(msg({message: 'Discover', context: 'feed-name'})) + } + return feed.displayName +} diff --git a/src/view/com/home/HomeHeader.tsx b/src/view/com/home/HomeHeader.tsx index a2f11aa9c5..c8174e4337 100644 --- a/src/view/com/home/HomeHeader.tsx +++ b/src/view/com/home/HomeHeader.tsx @@ -1,7 +1,10 @@ import {useCallback, useMemo} from 'react' +import {useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {TIMELINE_SAVED_FEED} from '#/lib/constants' import {type NavigationProp} from '#/lib/routes/types' +import {getLocalizedFeedName} from '#/lib/strings/feed-names' import {type FeedSourceInfo} from '#/state/queries/feed' import {useSession} from '#/state/session' import {type RenderTabBarFnProps} from '#/view/com/pager/Pager' @@ -12,28 +15,29 @@ export function HomeHeader( props: RenderTabBarFnProps & { testID?: string onPressSelected: () => void - feeds: FeedSourceInfo[] + feeds: Pick[] }, ) { const {feeds, onSelect: onSelectProp} = props const {hasSession} = useSession() + const {t: l, i18n} = useLingui() const navigation = useNavigation() const hasPinnedCustom = useMemo(() => { if (!hasSession) return false return feeds.some(tab => { - const isFollowing = tab.uri === 'following' + const isFollowing = tab.uri === TIMELINE_SAVED_FEED.value return !isFollowing }) }, [feeds, hasSession]) const items = useMemo(() => { - const pinnedNames = feeds.map(f => f.displayName) + const pinnedNames = feeds.map(f => getLocalizedFeedName(f, i18n)) if (!hasPinnedCustom) { - return pinnedNames.concat('Feeds ✨') + return pinnedNames.concat(l`Feeds ✨`) } return pinnedNames - }, [hasPinnedCustom, feeds]) + }, [i18n, l, hasPinnedCustom, feeds]) const onPressFeedsLink = useCallback(() => { navigation.navigate('Feeds') diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 3bdfa82b62..5111165e6c 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -4,9 +4,14 @@ import { Reanimated3DefaultSpringConfig, withSpring, } from 'react-native-reanimated' +import {useLingui} from '@lingui/react/macro' import {useFocusEffect} from '@react-navigation/native' -import {PROD_DEFAULT_FEED} from '#/lib/constants' +import { + DISCOVER_FEED_URI, + PROD_DEFAULT_FEED, + TIMELINE_SAVED_FEED, +} from '#/lib/constants' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates' import {useSetTitle} from '#/lib/hooks/useSetTitle' @@ -15,6 +20,7 @@ import { type HomeTabNavigatorParams, type NativeStackScreenProps, } from '#/lib/routes/types' +import {getLocalizedFeedName} from '#/lib/strings/feed-names' import {emitSoftReset} from '#/state/events' import { type SavedFeedSourceInfo, @@ -114,6 +120,7 @@ function HomeScreenReady({ preferences: UsePreferencesQueryResponse pinnedFeedInfos: SavedFeedSourceInfo[] }) { + const {i18n} = useLingui() const ax = useAnalytics() const allFeeds = useMemo( () => pinnedFeedInfos.map(f => f.feedDescriptor), @@ -125,13 +132,14 @@ function HomeScreenReady({ const maybeFoundIndex = allFeeds.indexOf(maybeRawSelectedFeed) const selectedIndex = Math.max(0, maybeFoundIndex) const maybeSelectedFeed: FeedDescriptor | undefined = allFeeds[selectedIndex] + const selectedFeedInfo = pinnedFeedInfos[selectedIndex] const requestNotificationsPermission = useRequestNotificationsPermission() - useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName) + useSetTitle(selectedFeedInfo && getLocalizedFeedName(selectedFeedInfo, i18n)) useOTAUpdates() useEffect(() => { - requestNotificationsPermission('Home') + void requestNotificationsPermission('Home') }, [requestNotificationsPermission]) const pagerRef = useRef(null) @@ -223,8 +231,13 @@ function HomeScreenReady({ {...props} testID="homeScreenFeedTabs" onPressSelected={onPressSelected} - // @ts-expect-error - feeds={[{displayName: 'Following'}, {displayName: 'Discover'}]} + feeds={[ + { + displayName: 'Following', + uri: TIMELINE_SAVED_FEED.value, + }, + {displayName: 'Discover', uri: DISCOVER_FEED_URI}, + ]} /> ) } diff --git a/src/view/shell/desktop/Feeds.tsx b/src/view/shell/desktop/Feeds.tsx index 8e4e98addc..2babcfbcb0 100644 --- a/src/view/shell/desktop/Feeds.tsx +++ b/src/view/shell/desktop/Feeds.tsx @@ -1,10 +1,10 @@ import {Pressable, View} from 'react-native' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' +import {useLingui} from '@lingui/react/macro' import {useNavigation, useNavigationState} from '@react-navigation/native' import {getCurrentRoute} from '#/lib/routes/helpers' import {type NavigationProp} from '#/lib/routes/types' +import {getLocalizedFeedName} from '#/lib/strings/feed-names' import {emitSoftReset} from '#/state/events' import { type SavedFeedSourceInfo, @@ -22,7 +22,7 @@ import {useAnalytics} from '#/analytics' export function DesktopFeeds() { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const ax = useAnalytics() const {data: pinnedFeedInfos, error, isLoading} = usePinnedFeedsInfos() const selectedFeed = useSelectedFeed() @@ -100,10 +100,9 @@ export function DesktopFeeds() { /> ) })} - - {_(msg`More feeds`)} + {l`More feeds`} ) @@ -170,19 +169,20 @@ function FeedItem({ onPress: () => void }) { const t = useTheme() - const {_} = useLingui() + const {t: l, i18n} = useLingui() const { state: hovered, onIn: onHoverIn, onOut: onHoverOut, } = useInteractionState() const isFollowing = feedInfo.feedDescriptor === 'following' + const displayName = getLocalizedFeedName(feedInfo, i18n) return ( - {feedInfo.displayName} + {displayName} )