about summary refs log tree commit diff
path: root/src/view/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/screens')
-rw-r--r--src/view/screens/AppPasswords.tsx31
-rw-r--r--src/view/screens/CommunityGuidelines.tsx19
-rw-r--r--src/view/screens/CopyrightPolicy.tsx19
-rw-r--r--src/view/screens/Feeds.tsx2
-rw-r--r--src/view/screens/LanguageSettings.tsx125
-rw-r--r--src/view/screens/Lists.tsx7
-rw-r--r--src/view/screens/Moderation.tsx13
-rw-r--r--src/view/screens/ModerationBlockedAccounts.tsx21
-rw-r--r--src/view/screens/ModerationMutedAccounts.tsx19
-rw-r--r--src/view/screens/NotFound.tsx11
-rw-r--r--src/view/screens/Notifications.tsx9
-rw-r--r--src/view/screens/PostLikedBy.tsx5
-rw-r--r--src/view/screens/PostRepostedBy.tsx5
-rw-r--r--src/view/screens/PostThread.tsx5
-rw-r--r--src/view/screens/PreferencesHomeFeed.tsx16
-rw-r--r--src/view/screens/PreferencesThreads.tsx2
-rw-r--r--src/view/screens/PrivacyPolicy.tsx19
-rw-r--r--src/view/screens/ProfileFeed.tsx7
-rw-r--r--src/view/screens/ProfileFeedLikedBy.tsx5
-rw-r--r--src/view/screens/ProfileFollowers.tsx5
-rw-r--r--src/view/screens/ProfileFollows.tsx5
-rw-r--r--src/view/screens/ProfileList.tsx40
-rw-r--r--src/view/screens/SavedFeeds.tsx34
-rw-r--r--src/view/screens/Search/Search.tsx14
-rw-r--r--src/view/screens/Settings.tsx4
-rw-r--r--src/view/screens/Support.tsx23
-rw-r--r--src/view/screens/TermsOfService.tsx7
27 files changed, 330 insertions, 142 deletions
diff --git a/src/view/screens/AppPasswords.tsx b/src/view/screens/AppPasswords.tsx
index b2eee392a..bc77a48cd 100644
--- a/src/view/screens/AppPasswords.tsx
+++ b/src/view/screens/AppPasswords.tsx
@@ -183,9 +183,10 @@ export const AppPasswords = withAuthRequired(
 function AppPasswordsHeader() {
   const {isTabletOrDesktop} = useWebMediaQueries()
   const pal = usePalette('default')
+  const {_} = useLingui()
   return (
     <>
-      <ViewHeader title="App Passwords" showOnDesktop />
+      <ViewHeader title={_(msg`App Passwords`)} showOnDesktop />
       <Text
         type="sm"
         style={[
@@ -220,14 +221,16 @@ function AppPassword({
   const onDelete = React.useCallback(async () => {
     openModal({
       name: 'confirm',
-      title: 'Delete App Password',
-      message: `Are you sure you want to delete the app password "${name}"?`,
+      title: _(msg`Delete app password`),
+      message: _(
+        msg`Are you sure you want to delete the app password "${name}"?`,
+      ),
       async onPressConfirm() {
         await deleteMutation.mutateAsync({name})
         Toast.show('App password deleted')
       },
     })
-  }, [deleteMutation, openModal, name])
+  }, [deleteMutation, openModal, name, _])
 
   const primaryLocale =
     contentLanguages.length > 0 ? contentLanguages[0] : 'en-US'
@@ -245,15 +248,17 @@ function AppPassword({
           {name}
         </Text>
         <Text type="md" style={[pal.text, styles.pr10]} numberOfLines={1}>
-          Created{' '}
-          {Intl.DateTimeFormat(primaryLocale, {
-            year: 'numeric',
-            month: 'numeric',
-            day: 'numeric',
-            hour: '2-digit',
-            minute: '2-digit',
-            second: '2-digit',
-          }).format(new Date(createdAt))}
+          <Trans>
+            Created{' '}
+            {Intl.DateTimeFormat(primaryLocale, {
+              year: 'numeric',
+              month: 'numeric',
+              day: 'numeric',
+              hour: '2-digit',
+              minute: '2-digit',
+              second: '2-digit',
+            }).format(new Date(createdAt))}
+          </Trans>
         </Text>
       </View>
       <FontAwesomeIcon icon={['far', 'trash-can']} style={styles.trashIcon} />
diff --git a/src/view/screens/CommunityGuidelines.tsx b/src/view/screens/CommunityGuidelines.tsx
index 712172c3b..1931c6f13 100644
--- a/src/view/screens/CommunityGuidelines.tsx
+++ b/src/view/screens/CommunityGuidelines.tsx
@@ -9,6 +9,8 @@ import {ScrollView} from 'view/com/util/Views'
 import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<
   CommonNavigatorParams,
@@ -16,6 +18,7 @@ type Props = NativeStackScreenProps<
 >
 export const CommunityGuidelinesScreen = (_props: Props) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const setMinimalShellMode = useSetMinimalShellMode()
 
   useFocusEffect(
@@ -26,16 +29,18 @@ export const CommunityGuidelinesScreen = (_props: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Community Guidelines" />
+      <ViewHeader title={_(msg`Community Guidelines`)} />
       <ScrollView style={[s.hContentRegion, pal.view]}>
         <View style={[s.p20]}>
           <Text style={pal.text}>
-            The Community Guidelines have been moved to{' '}
-            <TextLink
-              style={pal.link}
-              href="https://blueskyweb.xyz/support/community-guidelines"
-              text="blueskyweb.xyz/support/community-guidelines"
-            />
+            <Trans>
+              The Community Guidelines have been moved to{' '}
+              <TextLink
+                style={pal.link}
+                href="https://blueskyweb.xyz/support/community-guidelines"
+                text="blueskyweb.xyz/support/community-guidelines"
+              />
+            </Trans>
           </Text>
         </View>
         <View style={s.footerSpacer} />
diff --git a/src/view/screens/CopyrightPolicy.tsx b/src/view/screens/CopyrightPolicy.tsx
index 816c1c1ee..2026f28c6 100644
--- a/src/view/screens/CopyrightPolicy.tsx
+++ b/src/view/screens/CopyrightPolicy.tsx
@@ -9,10 +9,13 @@ import {ScrollView} from 'view/com/util/Views'
 import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'CopyrightPolicy'>
 export const CopyrightPolicyScreen = (_props: Props) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const setMinimalShellMode = useSetMinimalShellMode()
 
   useFocusEffect(
@@ -23,16 +26,18 @@ export const CopyrightPolicyScreen = (_props: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Copyright Policy" />
+      <ViewHeader title={_(msg`Copyright Policy`)} />
       <ScrollView style={[s.hContentRegion, pal.view]}>
         <View style={[s.p20]}>
           <Text style={pal.text}>
-            The Copyright Policy has been moved to{' '}
-            <TextLink
-              style={pal.link}
-              href="https://blueskyweb.xyz/support/community-guidelines"
-              text="blueskyweb.xyz/support/community-guidelines"
-            />
+            <Trans>
+              The Copyright Policy has been moved to{' '}
+              <TextLink
+                style={pal.link}
+                href="https://blueskyweb.xyz/support/community-guidelines"
+                text="blueskyweb.xyz/support/community-guidelines"
+              />
+            </Trans>
           </Text>
         </View>
         <View style={s.footerSpacer} />
diff --git a/src/view/screens/Feeds.tsx b/src/view/screens/Feeds.tsx
index a6d47f5ce..5d62125ce 100644
--- a/src/view/screens/Feeds.tsx
+++ b/src/view/screens/Feeds.tsx
@@ -467,7 +467,7 @@ export const FeedsScreen = withAuthRequired(function FeedsScreenImpl(
     <View style={[pal.view, styles.container]}>
       {isMobile && (
         <ViewHeader
-          title="Feeds"
+          title={_(msg`Feeds`)}
           canGoBack={false}
           renderButton={renderHeaderBtn}
           showBorder
diff --git a/src/view/screens/LanguageSettings.tsx b/src/view/screens/LanguageSettings.tsx
index 649daea0e..7a2e54dc8 100644
--- a/src/view/screens/LanguageSettings.tsx
+++ b/src/view/screens/LanguageSettings.tsx
@@ -14,16 +14,19 @@ import {
 } from '@fortawesome/react-native-fontawesome'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {useFocusEffect} from '@react-navigation/native'
-import {LANGUAGES} from 'lib/../locale/languages'
+import {APP_LANGUAGES, LANGUAGES} from 'lib/../locale/languages'
 import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
 import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
 
-export function LanguageSettingsScreen(_: Props) {
+export function LanguageSettingsScreen(_props: Props) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const langPrefs = useLanguagePrefs()
   const setLangPrefs = useLanguagePrefsApi()
   const {isTabletOrDesktop} = useWebMediaQueries()
@@ -52,6 +55,15 @@ export function LanguageSettingsScreen(_: Props) {
     [langPrefs, setLangPrefs],
   )
 
+  const onChangeAppLanguage = React.useCallback(
+    (value: Parameters<PickerSelectProps['onValueChange']>[0]) => {
+      if (langPrefs.appLanguage !== value) {
+        setLangPrefs.setAppLanguage(value)
+      }
+    },
+    [langPrefs, setLangPrefs],
+  )
+
   const myLanguages = React.useMemo(() => {
     return (
       langPrefs.contentLanguages
@@ -71,15 +83,109 @@ export function LanguageSettingsScreen(_: Props) {
         styles.container,
         isTabletOrDesktop && styles.desktopContainer,
       ]}>
-      <ViewHeader title="Language Settings" showOnDesktop />
+      <ViewHeader title={_(msg`Language Settings`)} showOnDesktop />
 
       <View style={{paddingTop: 20, paddingHorizontal: 20}}>
+        {/* APP LANGUAGE */}
+        <View style={{paddingBottom: 20}}>
+          <Text type="title-sm" style={[pal.text, s.pb5]}>
+            <Trans>App Language</Trans>
+          </Text>
+          <Text style={[pal.text, s.pb10]}>
+            <Trans>
+              Select your app language for the default text to display in the
+              app
+            </Trans>
+          </Text>
+
+          <View style={{position: 'relative'}}>
+            <RNPickerSelect
+              value={langPrefs.appLanguage}
+              onValueChange={onChangeAppLanguage}
+              items={APP_LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({
+                label: l.name,
+                value: l.code2,
+                key: l.code2,
+              }))}
+              style={{
+                inputAndroid: {
+                  backgroundColor: pal.viewLight.backgroundColor,
+                  color: pal.text.color,
+                  fontSize: 14,
+                  letterSpacing: 0.5,
+                  fontWeight: '500',
+                  paddingHorizontal: 14,
+                  paddingVertical: 8,
+                  borderRadius: 24,
+                },
+                inputIOS: {
+                  backgroundColor: pal.viewLight.backgroundColor,
+                  color: pal.text.color,
+                  fontSize: 14,
+                  letterSpacing: 0.5,
+                  fontWeight: '500',
+                  paddingHorizontal: 14,
+                  paddingVertical: 8,
+                  borderRadius: 24,
+                },
+                inputWeb: {
+                  // @ts-ignore web only
+                  cursor: 'pointer',
+                  '-moz-appearance': 'none',
+                  '-webkit-appearance': 'none',
+                  appearance: 'none',
+                  outline: 0,
+                  borderWidth: 0,
+                  backgroundColor: pal.viewLight.backgroundColor,
+                  color: pal.text.color,
+                  fontSize: 14,
+                  letterSpacing: 0.5,
+                  fontWeight: '500',
+                  paddingHorizontal: 14,
+                  paddingVertical: 8,
+                  borderRadius: 24,
+                },
+              }}
+            />
+
+            <View
+              style={{
+                position: 'absolute',
+                top: 1,
+                right: 1,
+                bottom: 1,
+                width: 40,
+                backgroundColor: pal.viewLight.backgroundColor,
+                borderRadius: 24,
+                pointerEvents: 'none',
+                alignItems: 'center',
+                justifyContent: 'center',
+              }}>
+              <FontAwesomeIcon
+                icon="chevron-down"
+                style={pal.text as FontAwesomeIconStyle}
+              />
+            </View>
+          </View>
+        </View>
+
+        <View
+          style={{
+            height: 1,
+            backgroundColor: pal.border.borderColor,
+            marginBottom: 20,
+          }}
+        />
+
+        {/* PRIMARY LANGUAGE */}
         <View style={{paddingBottom: 20}}>
           <Text type="title-sm" style={[pal.text, s.pb5]}>
-            Primary Language
+            <Trans>Primary Language</Trans>
           </Text>
           <Text style={[pal.text, s.pb10]}>
-            Select your preferred language for translations in your feed.
+            <Trans>
+              Select your preferred language for translations in your feed.
+            </Trans>
           </Text>
 
           <View style={{position: 'relative'}}>
@@ -161,13 +267,16 @@ export function LanguageSettingsScreen(_: Props) {
           }}
         />
 
+        {/* CONTENT LANGUAGES */}
         <View style={{paddingBottom: 20}}>
           <Text type="title-sm" style={[pal.text, s.pb5]}>
-            Content Languages
+            <Trans>Content Languages</Trans>
           </Text>
           <Text style={[pal.text, s.pb10]}>
-            Select which languages you want your subscribed feeds to include. If
-            none are selected, all languages will be shown.
+            <Trans>
+              Select which languages you want your subscribed feeds to include.
+              If none are selected, all languages will be shown.
+            </Trans>
           </Text>
 
           <Button
diff --git a/src/view/screens/Lists.tsx b/src/view/screens/Lists.tsx
index 00711784d..c97be4a02 100644
--- a/src/view/screens/Lists.tsx
+++ b/src/view/screens/Lists.tsx
@@ -15,6 +15,7 @@ import {SimpleViewHeader} from 'view/com/util/SimpleViewHeader'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
+import {Trans} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'>
 export const ListsScreen = withAuthRequired(
@@ -56,10 +57,10 @@ export const ListsScreen = withAuthRequired(
           }>
           <View style={{flex: 1}}>
             <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}>
-              User Lists
+              <Trans>User Lists</Trans>
             </Text>
             <Text style={pal.textLight}>
-              Public, shareable lists which can drive feeds.
+              <Trans>Public, shareable lists which can drive feeds.</Trans>
             </Text>
           </View>
           <View>
@@ -74,7 +75,7 @@ export const ListsScreen = withAuthRequired(
               }}>
               <FontAwesomeIcon icon="plus" color={pal.colors.text} />
               <Text type="button" style={pal.text}>
-                New
+                <Trans>New</Trans>
               </Text>
             </Button>
           </View>
diff --git a/src/view/screens/Moderation.tsx b/src/view/screens/Moderation.tsx
index 37eecf22d..10b72fe9e 100644
--- a/src/view/screens/Moderation.tsx
+++ b/src/view/screens/Moderation.tsx
@@ -17,11 +17,14 @@ import {useAnalytics} from 'lib/analytics/analytics'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
 export const ModerationScreen = withAuthRequired(
   function Moderation({}: Props) {
     const pal = usePalette('default')
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {screen, track} = useAnalytics()
     const {isTabletOrDesktop} = useWebMediaQueries()
@@ -47,7 +50,7 @@ export const ModerationScreen = withAuthRequired(
           isTabletOrDesktop ? styles.desktopContainer : pal.viewLight,
         ]}
         testID="moderationScreen">
-        <ViewHeader title="Moderation" showOnDesktop />
+        <ViewHeader title={_(msg`Moderation`)} showOnDesktop />
         <View style={styles.spacer} />
         <TouchableOpacity
           testID="contentFilteringBtn"
@@ -63,7 +66,7 @@ export const ModerationScreen = withAuthRequired(
             />
           </View>
           <Text type="lg" style={pal.text}>
-            Content filtering
+            <Trans>Content filtering</Trans>
           </Text>
         </TouchableOpacity>
         <Link
@@ -77,7 +80,7 @@ export const ModerationScreen = withAuthRequired(
             />
           </View>
           <Text type="lg" style={pal.text}>
-            Moderation lists
+            <Trans>Moderation lists</Trans>
           </Text>
         </Link>
         <Link
@@ -91,7 +94,7 @@ export const ModerationScreen = withAuthRequired(
             />
           </View>
           <Text type="lg" style={pal.text}>
-            Muted accounts
+            <Trans>Muted accounts</Trans>
           </Text>
         </Link>
         <Link
@@ -105,7 +108,7 @@ export const ModerationScreen = withAuthRequired(
             />
           </View>
           <Text type="lg" style={pal.text}>
-            Blocked accounts
+            <Trans>Blocked accounts</Trans>
           </Text>
         </Link>
       </CenteredView>
diff --git a/src/view/screens/ModerationBlockedAccounts.tsx b/src/view/screens/ModerationBlockedAccounts.tsx
index 702a8d44e..1c592dde8 100644
--- a/src/view/screens/ModerationBlockedAccounts.tsx
+++ b/src/view/screens/ModerationBlockedAccounts.tsx
@@ -21,6 +21,8 @@ import {ErrorScreen} from '../com/util/error/ErrorScreen'
 import {ProfileCard} from 'view/com/profile/ProfileCard'
 import {logger} from '#/logger'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts'
 import {cleanError} from '#/lib/strings/errors'
 
@@ -31,6 +33,7 @@ type Props = NativeStackScreenProps<
 export const ModerationBlockedAccounts = withAuthRequired(
   function ModerationBlockedAccountsImpl({}: Props) {
     const pal = usePalette('default')
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {isTabletOrDesktop} = useWebMediaQueries()
     const {screen} = useAnalytics()
@@ -104,7 +107,7 @@ export const ModerationBlockedAccounts = withAuthRequired(
           pal.border,
         ]}
         testID="blockedAccountsScreen">
-        <ViewHeader title="Blocked Accounts" showOnDesktop />
+        <ViewHeader title={_(msg`Blocked Accounts`)} showOnDesktop />
         <Text
           type="sm"
           style={[
@@ -112,9 +115,11 @@ export const ModerationBlockedAccounts = withAuthRequired(
             pal.text,
             isTabletOrDesktop && styles.descriptionDesktop,
           ]}>
-          Blocked accounts cannot reply in your threads, mention you, or
-          otherwise interact with you. You will not see their content and they
-          will be prevented from seeing yours.
+          <Trans>
+            Blocked accounts cannot reply in your threads, mention you, or
+            otherwise interact with you. You will not see their content and they
+            will be prevented from seeing yours.
+          </Trans>
         </Text>
         {isEmpty ? (
           <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
@@ -127,9 +132,11 @@ export const ModerationBlockedAccounts = withAuthRequired(
             ) : (
               <View style={[styles.empty, pal.viewLight]}>
                 <Text type="lg" style={[pal.text, styles.emptyText]}>
-                  You have not blocked any accounts yet. To block an account, go
-                  to their profile and selected "Block account" from the menu on
-                  their account.
+                  <Trans>
+                    You have not blocked any accounts yet. To block an account,
+                    go to their profile and selected "Block account" from the
+                    menu on their account.
+                  </Trans>
                 </Text>
               </View>
             )}
diff --git a/src/view/screens/ModerationMutedAccounts.tsx b/src/view/screens/ModerationMutedAccounts.tsx
index fe0b4bf14..36bcbf1fa 100644
--- a/src/view/screens/ModerationMutedAccounts.tsx
+++ b/src/view/screens/ModerationMutedAccounts.tsx
@@ -21,6 +21,8 @@ import {ErrorScreen} from '../com/util/error/ErrorScreen'
 import {ProfileCard} from 'view/com/profile/ProfileCard'
 import {logger} from '#/logger'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts'
 import {cleanError} from '#/lib/strings/errors'
 
@@ -31,6 +33,7 @@ type Props = NativeStackScreenProps<
 export const ModerationMutedAccounts = withAuthRequired(
   function ModerationMutedAccountsImpl({}: Props) {
     const pal = usePalette('default')
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {isTabletOrDesktop} = useWebMediaQueries()
     const {screen} = useAnalytics()
@@ -104,7 +107,7 @@ export const ModerationMutedAccounts = withAuthRequired(
           pal.border,
         ]}
         testID="mutedAccountsScreen">
-        <ViewHeader title="Muted Accounts" showOnDesktop />
+        <ViewHeader title={_(msg`Muted Accounts`)} showOnDesktop />
         <Text
           type="sm"
           style={[
@@ -112,8 +115,10 @@ export const ModerationMutedAccounts = withAuthRequired(
             pal.text,
             isTabletOrDesktop && styles.descriptionDesktop,
           ]}>
-          Muted accounts have their posts removed from your feed and from your
-          notifications. Mutes are completely private.
+          <Trans>
+            Muted accounts have their posts removed from your feed and from your
+            notifications. Mutes are completely private.
+          </Trans>
         </Text>
         {isEmpty ? (
           <View style={[pal.border, !isTabletOrDesktop && styles.flex1]}>
@@ -126,9 +131,11 @@ export const ModerationMutedAccounts = withAuthRequired(
             ) : (
               <View style={[styles.empty, pal.viewLight]}>
                 <Text type="lg" style={[pal.text, styles.emptyText]}>
-                  You have not muted any accounts yet. To mute an account, go to
-                  their profile and selected "Mute account" from the menu on
-                  their account.
+                  <Trans>
+                    You have not muted any accounts yet. To mute an account, go
+                    to their profile and selected "Mute account" from the menu
+                    on their account.
+                  </Trans>
                 </Text>
               </View>
             )}
diff --git a/src/view/screens/NotFound.tsx b/src/view/screens/NotFound.tsx
index c2125756c..2508a9ed2 100644
--- a/src/view/screens/NotFound.tsx
+++ b/src/view/screens/NotFound.tsx
@@ -12,9 +12,12 @@ import {NavigationProp} from 'lib/routes/types'
 import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const NotFoundScreen = () => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const navigation = useNavigation<NavigationProp>()
   const setMinimalShellMode = useSetMinimalShellMode()
 
@@ -36,13 +39,15 @@ export const NotFoundScreen = () => {
 
   return (
     <View testID="notFoundView" style={pal.view}>
-      <ViewHeader title="Page not found" />
+      <ViewHeader title={_(msg`Page not found`)} />
       <View style={styles.container}>
         <Text type="title-2xl" style={[pal.text, s.mb10]}>
-          Page not found
+          <Trans>Page not found</Trans>
         </Text>
         <Text type="md" style={[pal.text, s.mb10]}>
-          We're sorry! We can't find the page you were looking for.
+          <Trans>
+            We're sorry! We can't find the page you were looking for.
+          </Trans>
         </Text>
         <Button
           type="primary"
diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx
index c892ee4e3..4ed9c7f74 100644
--- a/src/view/screens/Notifications.tsx
+++ b/src/view/screens/Notifications.tsx
@@ -18,6 +18,8 @@ import {s, colors} from 'lib/styles'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {logger} from '#/logger'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useUnreadNotifications} from '#/state/queries/notifications/unread'
 import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
 import {listenSoftReset, emitSoftReset} from '#/state/events'
@@ -28,6 +30,7 @@ type Props = NativeStackScreenProps<
 >
 export const NotificationsScreen = withAuthRequired(
   function NotificationsScreenImpl({}: Props) {
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
     const scrollElRef = React.useRef<FlatList>(null)
@@ -83,7 +86,7 @@ export const NotificationsScreen = withAuthRequired(
               style={[pal.text, {fontWeight: 'bold'}]}
               text={
                 <>
-                  Notifications{' '}
+                  <Trans>Notifications</Trans>{' '}
                   {hasNew && (
                     <View
                       style={{
@@ -107,7 +110,7 @@ export const NotificationsScreen = withAuthRequired(
 
     return (
       <View testID="notificationsScreen" style={s.hContentRegion}>
-        <ViewHeader title="Notifications" canGoBack={false} />
+        <ViewHeader title={_(msg`Notifications`)} canGoBack={false} />
         <Feed
           onScroll={onMainScroll}
           scrollElRef={scrollElRef}
@@ -116,7 +119,7 @@ export const NotificationsScreen = withAuthRequired(
         {(isScrolledDown || hasNew) && (
           <LoadLatestBtn
             onPress={onPressLoadLatest}
-            label="Load new notifications"
+            label={_(msg`Load new notifications`)}
             showIndicator={hasNew}
           />
         )}
diff --git a/src/view/screens/PostLikedBy.tsx b/src/view/screens/PostLikedBy.tsx
index 2f45908b3..ab7bbcefe 100644
--- a/src/view/screens/PostLikedBy.tsx
+++ b/src/view/screens/PostLikedBy.tsx
@@ -7,12 +7,15 @@ import {ViewHeader} from '../com/util/ViewHeader'
 import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
 import {makeRecordUri} from 'lib/strings/url-helpers'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostLikedBy'>
 export const PostLikedByScreen = withAuthRequired(({route}: Props) => {
   const setMinimalShellMode = useSetMinimalShellMode()
   const {name, rkey} = route.params
   const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -22,7 +25,7 @@ export const PostLikedByScreen = withAuthRequired(({route}: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Liked by" />
+      <ViewHeader title={_(msg`Liked by`)} />
       <PostLikedByComponent uri={uri} />
     </View>
   )
diff --git a/src/view/screens/PostRepostedBy.tsx b/src/view/screens/PostRepostedBy.tsx
index abe03467a..eabbc4a4e 100644
--- a/src/view/screens/PostRepostedBy.tsx
+++ b/src/view/screens/PostRepostedBy.tsx
@@ -7,12 +7,15 @@ import {ViewHeader} from '../com/util/ViewHeader'
 import {PostRepostedBy as PostRepostedByComponent} from '../com/post-thread/PostRepostedBy'
 import {makeRecordUri} from 'lib/strings/url-helpers'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostRepostedBy'>
 export const PostRepostedByScreen = withAuthRequired(({route}: Props) => {
   const {name, rkey} = route.params
   const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
   const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -22,7 +25,7 @@ export const PostRepostedByScreen = withAuthRequired(({route}: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Reposted by" />
+      <ViewHeader title={_(msg`Reposted by`)} />
       <PostRepostedByComponent uri={uri} />
     </View>
   )
diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx
index 844a96d11..0476e182b 100644
--- a/src/view/screens/PostThread.tsx
+++ b/src/view/screens/PostThread.tsx
@@ -19,6 +19,8 @@ import {clamp} from 'lodash'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useResolveUriQuery} from '#/state/queries/resolve-uri'
 import {ErrorMessage} from '../com/util/error/ErrorMessage'
 import {CenteredView} from '../com/util/Views'
@@ -29,6 +31,7 @@ export const PostThreadScreen = withAuthRequired(function PostThreadScreenImpl({
   route,
 }: Props) {
   const queryClient = useQueryClient()
+  const {_} = useLingui()
   const {fabMinimalShellTransform} = useMinimalShellMode()
   const setMinimalShellMode = useSetMinimalShellMode()
   const {openComposer} = useComposerControls()
@@ -74,7 +77,7 @@ export const PostThreadScreen = withAuthRequired(function PostThreadScreenImpl({
 
   return (
     <View style={s.hContentRegion}>
-      {isMobile && <ViewHeader title="Post" />}
+      {isMobile && <ViewHeader title={_(msg`Post`)} />}
       <View style={s.flex1}>
         {uriError ? (
           <CenteredView>
diff --git a/src/view/screens/PreferencesHomeFeed.tsx b/src/view/screens/PreferencesHomeFeed.tsx
index 2fd0eff37..fe17be5e8 100644
--- a/src/view/screens/PreferencesHomeFeed.tsx
+++ b/src/view/screens/PreferencesHomeFeed.tsx
@@ -92,7 +92,7 @@ export function PreferencesHomeFeed({navigation}: Props) {
         styles.container,
         isTabletOrDesktop && styles.desktopContainer,
       ]}>
-      <ViewHeader title="Home Feed Preferences" showOnDesktop />
+      <ViewHeader title={_(msg`Home Feed Preferences`)} showOnDesktop />
       <View
         style={[
           styles.titleSection,
@@ -142,7 +142,7 @@ export function PreferencesHomeFeed({navigation}: Props) {
             </Text>
             <ToggleButton
               type="default-light"
-              label="Followed users only"
+              label={_(msg`Followed users only`)}
               isSelected={Boolean(
                 variables?.hideRepliesByUnfollowed ??
                   preferences?.feedViewPrefs?.hideRepliesByUnfollowed,
@@ -188,8 +188,8 @@ export function PreferencesHomeFeed({navigation}: Props) {
               label={
                 variables?.hideReposts ??
                 preferences?.feedViewPrefs?.hideReposts
-                  ? 'No'
-                  : 'Yes'
+                  ? _(msg`No`)
+                  : _(msg`Yes`)
               }
               isSelected={
                 !(
@@ -223,8 +223,8 @@ export function PreferencesHomeFeed({navigation}: Props) {
               label={
                 variables?.hideQuotePosts ??
                 preferences?.feedViewPrefs?.hideQuotePosts
-                  ? 'No'
-                  : 'Yes'
+                  ? _(msg`No`)
+                  : _(msg`Yes`)
               }
               isSelected={
                 !(
@@ -259,8 +259,8 @@ export function PreferencesHomeFeed({navigation}: Props) {
               label={
                 variables?.lab_mergeFeedEnabled ??
                 preferences?.feedViewPrefs?.lab_mergeFeedEnabled
-                  ? 'Yes'
-                  : 'No'
+                  ? _(msg`Yes`)
+                  : _(msg`No`)
               }
               isSelected={
                 !!(
diff --git a/src/view/screens/PreferencesThreads.tsx b/src/view/screens/PreferencesThreads.tsx
index 7bd87b712..73d941932 100644
--- a/src/view/screens/PreferencesThreads.tsx
+++ b/src/view/screens/PreferencesThreads.tsx
@@ -50,7 +50,7 @@ export function PreferencesThreads({navigation}: Props) {
         styles.container,
         isTabletOrDesktop && styles.desktopContainer,
       ]}>
-      <ViewHeader title="Thread Preferences" showOnDesktop />
+      <ViewHeader title={_(msg`Thread Preferences`)} showOnDesktop />
       <View
         style={[
           styles.titleSection,
diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx
index f709c9fda..247afc316 100644
--- a/src/view/screens/PrivacyPolicy.tsx
+++ b/src/view/screens/PrivacyPolicy.tsx
@@ -9,10 +9,13 @@ import {ScrollView} from 'view/com/util/Views'
 import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'>
 export const PrivacyPolicyScreen = (_props: Props) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const setMinimalShellMode = useSetMinimalShellMode()
 
   useFocusEffect(
@@ -23,16 +26,18 @@ export const PrivacyPolicyScreen = (_props: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Privacy Policy" />
+      <ViewHeader title={_(msg`Privacy Policy`)} />
       <ScrollView style={[s.hContentRegion, pal.view]}>
         <View style={[s.p20]}>
           <Text style={pal.text}>
-            The Privacy Policy has been moved to{' '}
-            <TextLink
-              style={pal.link}
-              href="https://blueskyweb.xyz/support/privacy-policy"
-              text="blueskyweb.xyz/support/privacy-policy"
-            />
+            <Trans>
+              The Privacy Policy has been moved to{' '}
+              <TextLink
+                style={pal.link}
+                href="https://blueskyweb.xyz/support/privacy-policy"
+                text="blueskyweb.xyz/support/privacy-policy"
+              />
+            </Trans>
           </Text>
         </View>
         <View style={s.footerSpacer} />
diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx
index 62f5f1b36..3974d3a11 100644
--- a/src/view/screens/ProfileFeed.tsx
+++ b/src/view/screens/ProfileFeed.tsx
@@ -269,7 +269,7 @@ export function ProfileFeedScreenInner({
     return [
       {
         testID: 'feedHeaderDropdownToggleSavedBtn',
-        label: isSaved ? 'Remove from my feeds' : 'Add to my feeds',
+        label: isSaved ? _(msg`Remove from my feeds`) : _(msg`Add to my feeds`),
         onPress: isSavePending || isRemovePending ? undefined : onToggleSaved,
         icon: isSaved
           ? {
@@ -289,7 +289,7 @@ export function ProfileFeedScreenInner({
       },
       {
         testID: 'feedHeaderDropdownReportBtn',
-        label: 'Report feed',
+        label: _(msg`Report feed`),
         onPress: onPressReport,
         icon: {
           ios: {
@@ -301,7 +301,7 @@ export function ProfileFeedScreenInner({
       },
       {
         testID: 'feedHeaderDropdownShareBtn',
-        label: 'Share link',
+        label: _(msg`Share feed`),
         onPress: onPressShare,
         icon: {
           ios: {
@@ -319,6 +319,7 @@ export function ProfileFeedScreenInner({
     isSaved,
     isSavePending,
     isRemovePending,
+    _,
   ])
 
   const renderHeader = useCallback(() => {
diff --git a/src/view/screens/ProfileFeedLikedBy.tsx b/src/view/screens/ProfileFeedLikedBy.tsx
index 4972116f3..c8466360e 100644
--- a/src/view/screens/ProfileFeedLikedBy.tsx
+++ b/src/view/screens/ProfileFeedLikedBy.tsx
@@ -7,12 +7,15 @@ import {ViewHeader} from '../com/util/ViewHeader'
 import {PostLikedBy as PostLikedByComponent} from '../com/post-thread/PostLikedBy'
 import {makeRecordUri} from 'lib/strings/url-helpers'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
 export const ProfileFeedLikedByScreen = withAuthRequired(({route}: Props) => {
   const setMinimalShellMode = useSetMinimalShellMode()
   const {name, rkey} = route.params
   const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -22,7 +25,7 @@ export const ProfileFeedLikedByScreen = withAuthRequired(({route}: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Liked by" />
+      <ViewHeader title={_(msg`Liked by`)} />
       <PostLikedByComponent uri={uri} />
     </View>
   )
diff --git a/src/view/screens/ProfileFollowers.tsx b/src/view/screens/ProfileFollowers.tsx
index 49f55bf46..13e69541a 100644
--- a/src/view/screens/ProfileFollowers.tsx
+++ b/src/view/screens/ProfileFollowers.tsx
@@ -6,11 +6,14 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/ProfileFollowers'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollowers'>
 export const ProfileFollowersScreen = withAuthRequired(({route}: Props) => {
   const {name} = route.params
   const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -20,7 +23,7 @@ export const ProfileFollowersScreen = withAuthRequired(({route}: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Followers" />
+      <ViewHeader title={_(msg`Followers`)} />
       <ProfileFollowersComponent name={name} />
     </View>
   )
diff --git a/src/view/screens/ProfileFollows.tsx b/src/view/screens/ProfileFollows.tsx
index 4f0ff7d67..07d6eaa78 100644
--- a/src/view/screens/ProfileFollows.tsx
+++ b/src/view/screens/ProfileFollows.tsx
@@ -6,11 +6,14 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileFollows'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFollows'>
 export const ProfileFollowsScreen = withAuthRequired(({route}: Props) => {
   const {name} = route.params
   const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -20,7 +23,7 @@ export const ProfileFollowsScreen = withAuthRequired(({route}: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Following" />
+      <ViewHeader title={_(msg`Following`)} />
       <ProfileFollowsComponent name={name} />
     </View>
   )
diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx
index ec6c7f79c..b5a650643 100644
--- a/src/view/screens/ProfileList.tsx
+++ b/src/view/screens/ProfileList.tsx
@@ -268,9 +268,10 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
   const onSubscribeMute = useCallback(() => {
     openModal({
       name: 'confirm',
-      title: 'Mute these accounts?',
-      message:
-        'Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them.',
+      title: _(msg`Mute these accounts?`),
+      message: _(
+        msg`Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them.`,
+      ),
       confirmBtnText: 'Mute this List',
       async onPressConfirm() {
         try {
@@ -286,7 +287,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
         closeModal()
       },
     })
-  }, [openModal, closeModal, list, listMuteMutation])
+  }, [openModal, closeModal, list, listMuteMutation, _])
 
   const onUnsubscribeMute = useCallback(async () => {
     try {
@@ -302,9 +303,10 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
   const onSubscribeBlock = useCallback(() => {
     openModal({
       name: 'confirm',
-      title: 'Block these accounts?',
-      message:
-        'Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you.',
+      title: _(msg`Block these accounts?`),
+      message: _(
+        msg`Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you.`,
+      ),
       confirmBtnText: 'Block this List',
       async onPressConfirm() {
         try {
@@ -320,7 +322,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
         closeModal()
       },
     })
-  }, [openModal, closeModal, list, listBlockMutation])
+  }, [openModal, closeModal, list, listBlockMutation, _])
 
   const onUnsubscribeBlock = useCallback(async () => {
     try {
@@ -343,8 +345,8 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
   const onPressDelete = useCallback(() => {
     openModal({
       name: 'confirm',
-      title: 'Delete List',
-      message: 'Are you sure?',
+      title: _(msg`Delete List`),
+      message: _(msg`Are you sure?`),
       async onPressConfirm() {
         await listDeleteMutation.mutateAsync({uri: list.uri})
         Toast.show('List deleted')
@@ -355,7 +357,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
         }
       },
     })
-  }, [openModal, list, listDeleteMutation, navigation])
+  }, [openModal, list, listDeleteMutation, navigation, _])
 
   const onPressReport = useCallback(() => {
     openModal({
@@ -374,7 +376,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
     let items: DropdownItem[] = [
       {
         testID: 'listHeaderDropdownShareBtn',
-        label: 'Share',
+        label: _(msg`Share`),
         onPress: onPressShare,
         icon: {
           ios: {
@@ -389,7 +391,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
       items.push({label: 'separator'})
       items.push({
         testID: 'listHeaderDropdownEditBtn',
-        label: 'Edit List Details',
+        label: _(msg`Edit list details`),
         onPress: onPressEdit,
         icon: {
           ios: {
@@ -401,7 +403,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
       })
       items.push({
         testID: 'listHeaderDropdownDeleteBtn',
-        label: 'Delete List',
+        label: _(msg`Delete List`),
         onPress: onPressDelete,
         icon: {
           ios: {
@@ -415,7 +417,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
       items.push({label: 'separator'})
       items.push({
         testID: 'listHeaderDropdownReportBtn',
-        label: 'Report List',
+        label: _(msg`Report List`),
         onPress: onPressReport,
         icon: {
           ios: {
@@ -427,13 +429,13 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
       })
     }
     return items
-  }, [isOwner, onPressShare, onPressEdit, onPressDelete, onPressReport])
+  }, [isOwner, onPressShare, onPressEdit, onPressDelete, onPressReport, _])
 
   const subscribeDropdownItems: DropdownItem[] = useMemo(() => {
     return [
       {
         testID: 'subscribeDropdownMuteBtn',
-        label: 'Mute accounts',
+        label: _(msg`Mute accounts`),
         onPress: onSubscribeMute,
         icon: {
           ios: {
@@ -445,7 +447,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
       },
       {
         testID: 'subscribeDropdownBlockBtn',
-        label: 'Block accounts',
+        label: _(msg`Block accounts`),
         onPress: onSubscribeBlock,
         icon: {
           ios: {
@@ -456,7 +458,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
         },
       },
     ]
-  }, [onSubscribeMute, onSubscribeBlock])
+  }, [onSubscribeMute, onSubscribeBlock, _])
 
   return (
     <ProfileSubpageHeader
diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx
index e3e50ca24..4928b6745 100644
--- a/src/view/screens/SavedFeeds.tsx
+++ b/src/view/screens/SavedFeeds.tsx
@@ -9,7 +9,6 @@ import {
 import {useFocusEffect} from '@react-navigation/native'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {useQueryClient} from '@tanstack/react-query'
-
 import {track} from '#/lib/analytics/analytics'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {usePalette} from 'lib/hooks/usePalette'
@@ -27,6 +26,8 @@ import {Haptics} from 'lib/haptics'
 import {TextLink} from 'view/com/util/Link'
 import {logger} from '#/logger'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {
   usePreferencesQuery,
   usePinFeedMutation,
@@ -52,6 +53,7 @@ const HITSLOP_BOTTOM = {
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'>
 export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
   const {screen} = useAnalytics()
   const setMinimalShellMode = useSetMinimalShellMode()
@@ -71,11 +73,11 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
         pal.border,
         isTabletOrDesktop && styles.desktopContainer,
       ]}>
-      <ViewHeader title="Edit My Feeds" showOnDesktop showBorder />
+      <ViewHeader title={_(msg`Edit My Feeds`)} showOnDesktop showBorder />
       <ScrollView style={s.flex1}>
         <View style={[pal.text, pal.border, styles.title]}>
           <Text type="title" style={pal.text}>
-            Pinned Feeds
+            <Trans>Pinned Feeds</Trans>
           </Text>
         </View>
         {preferences?.feeds ? (
@@ -88,7 +90,7 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
                 styles.empty,
               ]}>
               <Text type="lg" style={[pal.text]}>
-                You don't have any pinned feeds.
+                <Trans>You don't have any pinned feeds.</Trans>
               </Text>
             </View>
           ) : (
@@ -101,7 +103,7 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
         )}
         <View style={[pal.text, pal.border, styles.title]}>
           <Text type="title" style={pal.text}>
-            Saved Feeds
+            <Trans>Saved Feeds</Trans>
           </Text>
         </View>
         {preferences?.feeds ? (
@@ -114,7 +116,7 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
                 styles.empty,
               ]}>
               <Text type="lg" style={[pal.text]}>
-                You don't have any saved feeds.
+                <Trans>You don't have any saved feeds.</Trans>
               </Text>
             </View>
           ) : (
@@ -128,15 +130,17 @@ export const SavedFeeds = withAuthRequired(function SavedFeedsImpl({}: Props) {
 
         <View style={styles.footerText}>
           <Text type="sm" style={pal.textLight}>
-            Feeds are custom algorithms that users build with a little coding
-            expertise.{' '}
-            <TextLink
-              type="sm"
-              style={pal.link}
-              href="https://github.com/bluesky-social/feed-generator"
-              text="See this guide"
-            />{' '}
-            for more information.
+            <Trans>
+              Feeds are custom algorithms that users build with a little coding
+              expertise.{' '}
+              <TextLink
+                type="sm"
+                style={pal.link}
+                href="https://github.com/bluesky-social/feed-generator"
+                text="See this guide"
+              />{' '}
+              for more information.
+            </Trans>
           </Text>
         </View>
         <View style={{height: 100}} />
diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx
index a17c0d407..0788dd79d 100644
--- a/src/view/screens/Search/Search.tsx
+++ b/src/view/screens/Search/Search.tsx
@@ -222,10 +222,10 @@ function SearchScreenPostResults({query}: {query: string}) {
     return results?.pages.flatMap(page => page.posts) || []
   }, [results])
   const items = React.useMemo(() => {
-    let items: SearchResultSlice[] = []
+    let temp: SearchResultSlice[] = []
 
     for (const post of posts) {
-      items.push({
+      temp.push({
         type: 'post',
         key: post.uri,
         post,
@@ -233,13 +233,13 @@ function SearchScreenPostResults({query}: {query: string}) {
     }
 
     if (isFetchingNextPage) {
-      items.push({
+      temp.push({
         type: 'loadingMore',
         key: 'loadingMore',
       })
     }
 
-    return items
+    return temp
   }, [posts, isFetchingNextPage])
 
   return error ? (
@@ -299,9 +299,9 @@ function SearchScreenUserResults({query}: {query: string}) {
 
   React.useEffect(() => {
     async function getResults() {
-      const results = await search({query, limit: 30})
+      const searchResults = await search({query, limit: 30})
 
-      if (results) {
+      if (searchResults) {
         setDataUpdatedAt(Date.now())
         setResults(results)
         setIsFetched(true)
@@ -314,7 +314,7 @@ function SearchScreenUserResults({query}: {query: string}) {
       setResults([])
       setIsFetched(false)
     }
-  }, [query, setDataUpdatedAt, search])
+  }, [query, setDataUpdatedAt, search, results])
 
   return isFetched ? (
     <>
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index 6c61a699b..1f7623440 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -268,7 +268,7 @@ export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
 
   return (
     <View style={[s.hContentRegion]} testID="settingsScreen">
-      <ViewHeader title="Settings" />
+      <ViewHeader title={_(msg`Settings`)} />
       <ScrollView
         style={[s.hContentRegion]}
         contentContainerStyle={isMobile && pal.viewLight}
@@ -281,7 +281,7 @@ export const SettingsScreen = withAuthRequired(function Settings({}: Props) {
             </Text>
             <View style={[styles.infoLine]}>
               <Text type="lg-medium" style={pal.text}>
-                Email:{' '}
+                <Trans>Email:</Trans>{' '}
               </Text>
               {currentAccount.emailConfirmed && (
                 <>
diff --git a/src/view/screens/Support.tsx b/src/view/screens/Support.tsx
index 7106b4136..6856f6759 100644
--- a/src/view/screens/Support.tsx
+++ b/src/view/screens/Support.tsx
@@ -10,11 +10,14 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {HELP_DESK_URL} from 'lib/constants'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'>
 export const SupportScreen = (_props: Props) => {
   const pal = usePalette('default')
   const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -24,19 +27,21 @@ export const SupportScreen = (_props: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Support" />
+      <ViewHeader title={_(msg`Support`)} />
       <CenteredView>
         <Text type="title-xl" style={[pal.text, s.p20, s.pb5]}>
-          Support
+          <Trans>Support</Trans>
         </Text>
         <Text style={[pal.text, s.p20]}>
-          The support form has been moved. If you need help, please
-          <TextLink
-            href={HELP_DESK_URL}
-            text=" click here"
-            style={pal.link}
-          />{' '}
-          or visit {HELP_DESK_URL} to get in touch with us.
+          <Trans>
+            The support form has been moved. If you need help, please
+            <TextLink
+              href={HELP_DESK_URL}
+              text=" click here"
+              style={pal.link}
+            />{' '}
+            or visit {HELP_DESK_URL} to get in touch with us.
+          </Trans>
         </Text>
       </CenteredView>
     </View>
diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx
index b7a388b65..c20890e29 100644
--- a/src/view/screens/TermsOfService.tsx
+++ b/src/view/screens/TermsOfService.tsx
@@ -9,11 +9,14 @@ import {ScrollView} from 'view/com/util/Views'
 import {usePalette} from 'lib/hooks/usePalette'
 import {s} from 'lib/styles'
 import {useSetMinimalShellMode} from '#/state/shell'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'TermsOfService'>
 export const TermsOfServiceScreen = (_props: Props) => {
   const pal = usePalette('default')
   const setMinimalShellMode = useSetMinimalShellMode()
+  const {_} = useLingui()
 
   useFocusEffect(
     React.useCallback(() => {
@@ -23,11 +26,11 @@ export const TermsOfServiceScreen = (_props: Props) => {
 
   return (
     <View>
-      <ViewHeader title="Terms of Service" />
+      <ViewHeader title={_(msg`Terms of Service`)} />
       <ScrollView style={[s.hContentRegion, pal.view]}>
         <View style={[s.p20]}>
           <Text style={pal.text}>
-            The Terms of Service have been moved to{' '}
+            <Trans>The Terms of Service have been moved to</Trans>{' '}
             <TextLink
               style={pal.link}
               href="https://blueskyweb.xyz/support/tos"