about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAnsh <anshnanda10@gmail.com>2023-11-09 10:04:16 -0800
committerGitHub <noreply@github.com>2023-11-09 10:04:16 -0800
commit4c7850f8c48a0cb3f83f33b1701a99066c6b31db (patch)
tree62313ddf74601d42c70365e0863adbfbc7c93b0e /src
parent82059b7ee138d24ff50b0f4fad0eaeac860bb78c (diff)
downloadvoidsky-4c7850f8c48a0cb3f83f33b1701a99066c6b31db.tar.zst
Internationalization & localization (#1822)
* install and setup lingui

* setup dynamic locale activation and async loading

* first pass of automated replacement of text messages

* add some more documentaton

* fix nits

* add `es` and `hi`locales for testing purposes

* make accessibilityLabel localized

* compile and extract new messages

* fix merge conflicts

* fix eslint warning

* change instructions from sending email to opening PR

* fix comments
Diffstat (limited to 'src')
-rw-r--r--src/App.web.tsx12
-rw-r--r--src/locale/i18n.ts20
-rw-r--r--src/locale/locales/cs/messages.js1
-rw-r--r--src/locale/locales/cs/messages.po1544
-rw-r--r--src/locale/locales/en/messages.js1
-rw-r--r--src/locale/locales/en/messages.po1544
-rw-r--r--src/locale/locales/es/messages.js1
-rw-r--r--src/locale/locales/es/messages.po1544
-rw-r--r--src/locale/locales/fr/messages.js1
-rw-r--r--src/locale/locales/fr/messages.po1544
-rw-r--r--src/locale/locales/hi/messages.js1
-rw-r--r--src/locale/locales/hi/messages.po1544
-rw-r--r--src/view/com/auth/SplashScreen.tsx20
-rw-r--r--src/view/com/auth/SplashScreen.web.tsx5
-rw-r--r--src/view/com/auth/create/CreateAccount.tsx17
-rw-r--r--src/view/com/auth/create/Step1.tsx19
-rw-r--r--src/view/com/auth/create/Step2.tsx31
-rw-r--r--src/view/com/auth/create/Step3.tsx11
-rw-r--r--src/view/com/auth/login/ChooseAccountForm.tsx119
-rw-r--r--src/view/com/auth/login/ForgotPasswordForm.tsx197
-rw-r--r--src/view/com/auth/login/Login.tsx888
-rw-r--r--src/view/com/auth/login/LoginForm.tsx288
-rw-r--r--src/view/com/auth/login/PasswordUpdatedForm.tsx48
-rw-r--r--src/view/com/auth/login/SetNewPasswordForm.tsx181
-rw-r--r--src/view/com/auth/login/styles.ts118
-rw-r--r--src/view/com/auth/onboarding/RecommendedFollowsItem.tsx5
-rw-r--r--src/view/com/auth/onboarding/WelcomeMobile.tsx27
-rw-r--r--src/view/com/composer/Composer.tsx23
-rw-r--r--src/view/com/composer/ExternalEmbed.tsx5
-rw-r--r--src/view/com/composer/Prompt.tsx7
-rw-r--r--src/view/com/composer/labels/LabelsBtn.tsx5
-rw-r--r--src/view/com/composer/photos/Gallery.tsx19
-rw-r--r--src/view/com/composer/photos/OpenCameraBtn.tsx5
-rw-r--r--src/view/com/composer/photos/SelectPhotoBtn.tsx5
-rw-r--r--src/view/com/composer/select-language/SelectLangBtn.tsx9
-rw-r--r--src/view/com/feeds/FeedPage.tsx11
-rw-r--r--src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx6
-rw-r--r--src/view/com/lightbox/Lightbox.web.tsx11
-rw-r--r--src/view/com/lists/ListsList.tsx5
-rw-r--r--src/view/com/modals/AddAppPasswords.tsx41
-rw-r--r--src/view/com/modals/AltImage.tsx13
-rw-r--r--src/view/com/modals/BirthDateSettings.tsx15
-rw-r--r--src/view/com/modals/ChangeEmail.tsx43
-rw-r--r--src/view/com/modals/ChangeHandle.tsx35
-rw-r--r--src/view/com/modals/Confirm.tsx7
-rw-r--r--src/view/com/modals/ContentFilteringSettings.tsx13
-rw-r--r--src/view/com/modals/CreateOrEditList.tsx31
-rw-r--r--src/view/com/modals/DeleteAccount.tsx39
-rw-r--r--src/view/com/modals/EditImage.tsx19
-rw-r--r--src/view/com/modals/EditProfile.tsx31
-rw-r--r--src/view/com/modals/InviteCodes.tsx21
-rw-r--r--src/view/com/modals/LinkWarning.tsx15
-rw-r--r--src/view/com/modals/ListAddUser.tsx11
-rw-r--r--src/view/com/modals/Repost.tsx15
-rw-r--r--src/view/com/modals/SelfLabel.tsx31
-rw-r--r--src/view/com/modals/ServerInput.tsx25
-rw-r--r--src/view/com/modals/SwitchAccount.tsx9
-rw-r--r--src/view/com/modals/UserAddRemoveLists.tsx9
-rw-r--r--src/view/com/modals/VerifyEmail.tsx27
-rw-r--r--src/view/com/modals/Waitlist.tsx25
-rw-r--r--src/view/com/modals/crop-image/CropImage.web.tsx15
-rw-r--r--src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx9
-rw-r--r--src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx11
-rw-r--r--src/view/com/modals/lang-settings/PostLanguagesSettings.tsx7
-rw-r--r--src/view/com/modals/report/InputIssueDetails.tsx11
-rw-r--r--src/view/com/modals/report/Modal.tsx15
-rw-r--r--src/view/com/modals/report/SendReportButton.tsx9
-rw-r--r--src/view/com/notifications/FeedItem.tsx14
-rw-r--r--src/view/com/pager/FeedsTabBarMobile.tsx7
-rw-r--r--src/view/com/post-thread/PostThread.tsx31
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx11
-rw-r--r--src/view/com/profile/ProfileHeader.tsx23
-rw-r--r--src/view/com/profile/ProfileSubpageHeader.tsx5
-rw-r--r--src/view/com/search/HeaderWithInput.tsx13
-rw-r--r--src/view/com/util/AccountDropdownBtn.tsx6
-rw-r--r--src/view/com/util/BottomSheetCustomBackdrop.tsx3
-rw-r--r--src/view/com/util/UserAvatar.tsx5
-rw-r--r--src/view/com/util/UserBanner.tsx5
-rw-r--r--src/view/com/util/error/ErrorMessage.tsx5
-rw-r--r--src/view/com/util/error/ErrorScreen.tsx8
-rw-r--r--src/view/com/util/forms/DropdownButton.tsx5
-rw-r--r--src/view/com/util/forms/PostDropdownBtn.tsx5
-rw-r--r--src/view/com/util/forms/SearchInput.tsx7
-rw-r--r--src/view/com/util/moderation/ContentHider.tsx5
-rw-r--r--src/view/com/util/moderation/PostAlerts.tsx7
-rw-r--r--src/view/com/util/moderation/PostHider.tsx5
-rw-r--r--src/view/com/util/moderation/ProfileHeaderAlerts.tsx7
-rw-r--r--src/view/com/util/moderation/ScreenHider.tsx21
-rw-r--r--src/view/com/util/post-ctrls/RepostButton.web.tsx5
-rw-r--r--src/view/screens/AppPasswords.tsx17
-rw-r--r--src/view/screens/Feeds.tsx31
-rw-r--r--src/view/screens/Log.tsx5
-rw-r--r--src/view/screens/PreferencesHomeFeed.tsx54
-rw-r--r--src/view/screens/PreferencesThreads.tsx31
-rw-r--r--src/view/screens/Profile.tsx11
-rw-r--r--src/view/screens/ProfileFeed.tsx20
-rw-r--r--src/view/screens/ProfileList.tsx37
-rw-r--r--src/view/screens/Settings.tsx100
-rw-r--r--src/view/shell/Drawer.tsx29
-rw-r--r--src/view/shell/bottom-bar/BottomBar.tsx13
-rw-r--r--src/view/shell/desktop/LeftNav.tsx10
-rw-r--r--src/view/shell/desktop/Search.tsx11
-rw-r--r--src/view/shell/index.web.tsx3
103 files changed, 9620 insertions, 1349 deletions
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 9e5b99a9f..ef275b392 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -16,6 +16,9 @@ import {Shell} from 'view/shell/index'
 import {ToastContainer} from 'view/com/util/Toast.web'
 import {ThemeProvider} from 'lib/ThemeContext'
 import {queryClient} from 'lib/react-query'
+import {i18n} from '@lingui/core'
+import {I18nProvider} from '@lingui/react'
+import {defaultLocale, dynamicActivate} from './locale/i18n'
 import {Provider as ShellStateProvider} from 'state/shell'
 import {Provider as ModalStateProvider} from 'state/modals'
 import {Provider as MutedThreadsProvider} from 'state/muted-threads'
@@ -34,6 +37,7 @@ const InnerApp = observer(function AppImpl() {
       setRootStore(store)
       analytics.init(store)
     })
+    dynamicActivate(defaultLocale) // async import of locale data
   }, [])
 
   // show nothing prior to init
@@ -47,9 +51,11 @@ const InnerApp = observer(function AppImpl() {
         <RootSiblingParent>
           <analytics.Provider>
             <RootStoreProvider value={rootStore}>
-              <SafeAreaProvider>
-                <Shell />
-              </SafeAreaProvider>
+              <I18nProvider i18n={i18n}>
+                <SafeAreaProvider>
+                  <Shell />
+                </SafeAreaProvider>
+              </I18nProvider>
               <ToastContainer />
             </RootStoreProvider>
           </analytics.Provider>
diff --git a/src/locale/i18n.ts b/src/locale/i18n.ts
new file mode 100644
index 000000000..9c6a017ff
--- /dev/null
+++ b/src/locale/i18n.ts
@@ -0,0 +1,20 @@
+import {i18n} from '@lingui/core'
+
+export const locales = {
+  en: 'English',
+  cs: 'Česky',
+  fr: 'Français',
+  hi: 'हिंदी',
+  es: 'Español',
+}
+export const defaultLocale = 'en'
+
+/**
+ * We do a dynamic import of just the catalog that we need
+ * @param locale any locale string
+ */
+export async function dynamicActivate(locale: string) {
+  const {messages} = await import(`./locales/${locale}/messages`)
+  i18n.load(locale, messages)
+  i18n.activate(locale)
+}
diff --git a/src/locale/locales/cs/messages.js b/src/locale/locales/cs/messages.js
new file mode 100644
index 000000000..8d85ab77c
--- /dev/null
+++ b/src/locale/locales/cs/messages.js
@@ -0,0 +1 @@
+/*eslint-disable*/module.exports={messages:JSON.parse("{\"PBodTo\":\"- end of feed -\",\"EtUMsZ\":\". This warning is only available for posts with media attached.\",\"J/hVSQ\":[[\"0\"]],\"hZQerY\":[[\"0\"],\" \",[\"purposeLabel\"],\" List\"],\"6RmyWt\":\"<0>Here is your app password.</0> Use this to sign into the other app along with your handle.\",\"AnNF5e\":\"Accessibility\",\"AeXO77\":\"Account\",\"4WY4MD\":\"Account options\",\"m16xKo\":\"Add\",\"fBBX+K\":\"Add a content warning\",\"JU3hs2\":\"Add a user to this list\",\"MPPZ54\":\"Add account\",\"LkA8jz\":\"Add alt text\",\"Z8idyM\":\"Add details\",\"AoXl11\":\"Add details to report\",\"iE6B/9\":\"Add link card\",\"EXHdP1\":\"Add link card:\",\"x6laaL\":\"Add the following DNS record to your domain:\",\"jRrQFe\":\"Adjust the number of likes a reply must have to be shown in your feed.\",\"qLa52r\":\"Adult Content\",\"sxkWRg\":\"Advanced\",\"u2HO/d\":\"ALT\",\"u/DP73\":\"Alt text\",\"0QlT7/\":\"Alt text describes images for blind and low-vision users, and helps give context to everyone.\",\"woXbjq\":[\"An email has been sent to \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"Fon2dK\":[\"An email has been sent to your previous address, \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"HZFm5R\":\"and\",\"SMmUnj\":\"App passwords\",\"aAIQg2\":\"Appearance\",\"EbvWd3\":\"Artistic or non-erotic nudity.\",\"iH8pgl\":\"Back\",\"ehOkF+\":\"Basics\",\"+gCI2a\":\"Birthday\",\"pieVBA\":\"Birthday:\",\"HFCE4A\":\"Blocked post.\",\"7A9u1j\":\"Bluesky\",\"ZHmKSm\":\"Bluesky is flexible.\",\"odLrdl\":\"Bluesky is open.\",\"/LsWK4\":\"Bluesky is public.\",\"C50OGr\":\"Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon.\",\"klVoaP\":\"Bluesky.Social\",\"qxBitM\":[\"Build version \",[\"0\"],\" \",[\"1\"]],\"rT2cV+\":\"Camera\",\"JGGrPC\":\"Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long.\",\"dEgA5A\":\"Cancel\",\"aMH9rr\":\"Cancel account deletion\",\"kc3E4R\":\"Cancel add image alt text\",\"wg4LHQ\":\"Cancel change handle\",\"hFL1Li\":\"Cancel image crop\",\"tijH8t\":\"Cancel profile editing\",\"Qe4C/d\":\"Cancel quote post\",\"5TviPn\":\"Cancel search\",\"nss3UV\":\"Cancel waitlist signup\",\"o+XJ9D\":\"Change\",\"pQco5R\":\"Change handle\",\"Q5e1U/\":\"Change Handle\",\"a3NAfL\":\"Change my email\",\"4vatyk\":\"Change Your Email\",\"/+X+/K\":\"Check your inbox for an email with the confirmation code to enter below:\",\"Rt502e\":\"Choose Service\",\"/L45sc\":\"Choose the algorithms that power your experience with custom feeds.\",\"Wk8hkn\":\"Choose your password\",\"QbvBNV\":\"Clear search query\",\"flH7u/\":\"Close alert\",\"hYmnbk\":\"Close bottom drawer\",\"47L1V1\":\"Close image\",\"l49ujN\":\"Close image viewer\",\"UryHFO\":\"Close navigation footer\",\"o8UUti\":\"Compose reply\",\"7VpPHA\":\"Confirm\",\"q8upsf\":\"Confirm Change\",\"8pNKIr\":\"Confirm content language settings\",\"tGg8Kt\":\"Confirm delete account\",\"ioZOzk\":\"Confirmation code\",\"J28zul\":\"Connecting...\",\"m8j6up\":\"Content Filtering\",\"/PlAsF\":\"Content Languages\",\"cogwXi\":\"Content Warning\",\"FG7AQv\":\"Content warnings\",\"6V3Ea3\":\"Copied\",\"he3ygx\":\"Copy\",\"7wWvgo\":\"Could not load feed\",\"8NNr/O\":\"Could not load list\",\"mpt9T+\":\"Create a new account\",\"IS0nrP\":\"Create Account\",\"6HbhpU\":\"Create new account\",\"GAD3Dx\":\"Custom domain\",\"ZQKLI1\":\"Danger Zone\",\"ZDGm40\":\"Delete account\",\"vzX5FB\":\"Delete Account\",\"gUEtxf\":\"Delete app password\",\"ktknoE\":\"Delete my account\",\"szz0+N\":\"Delete my account…\",\"u+1OHY\":\"Deleted post.\",\"Nu4oKW\":\"Description\",\"dacKHE\":\"Dev Server\",\"2ygkE8\":\"Developer Tools\",\"pbLwal\":\"Discover new feeds\",\"pfa8F0\":\"Display name\",\"0gS7M5\":\"Display Name\",\"iZ5pMB\":\"Domain verified!\",\"DPfwMq\":\"Done\",\"zT97vP\":[\"Done\",[\"extraText\"]],\"XQFMOm\":\"Edit image\",\"cLmurE\":\"Edit My Feeds\",\"bRZ5XW\":\"Edit my profile\",\"9OpVZg\":\"Edit profile\",\"QJQd1J\":\"Edit Profile\",\"Jn7kox\":\"Edit Saved Feeds\",\"O3oNi5\":\"Email\",\"ATGYL1\":\"Email address\",\"pJJ0Vp\":\"Email Updated\",\"96mted\":\"Enable this setting to only see replies between people you follow.\",\"YbIxza\":\"Enter the address of your provider:\",\"BfIgP6\":\"Enter the domain you want to use\",\"xRPn3U\":\"Enter your email address\",\"+inPGm\":\"Enter your new email address below.\",\"T0KLp4\":\"Enter your username and password\",\"0PkE20\":\"Expand alt text\",\"4yCy8i\":\"Feed offline\",\"N0CqyO\":\"Feed Preferences\",\"YirHq7\":\"Feedback\",\"2DoBvq\":\"Feeds\",\"Qzj1WT\":\"Finding similar accounts...\",\"QKSrQV\":\"Fine-tune the content you see on your home screen.\",\"r+KeyR\":\"Fine-tune the discussion threads.\",\"MKEPCY\":\"Follow\",\"NIjL2Y\":\"following\",\"y6sq5j\":\"Following\",\"p3UO/y\":\"Follows you\",\"5RhDkD\":\"For security reasons, we'll need to send a confirmation code to your email address.\",\"NJPhAO\":\"For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one.\",\"5bDfuq\":\"Forgot\",\"hEPLrs\":\"Forgot password\",\"dn8X5t\":\"Forgot Password\",\"U+kFad\":\"Gallery\",\"c3b0B0\":\"Get Started\",\"CKyk7Q\":\"Go back\",\"sr0UJD\":\"Go Back\",\"Rtp0y7\":\"Go to next\",\"Nf7oXL\":\"Handle\",\"c3XJ18\":\"Help\",\"vLyv1R\":\"Hide\",\"qdOx2q\":\"Hide user list\",\"i0qMbr\":\"Home\",\"sXZ8IU\":\"Home Feed Preferences\",\"yt7fhu\":\"Hosting provider\",\"s2xA6t\":\"Hosting provider address\",\"o+axy6\":\"I have a code\",\"wey2os\":\"I have my own domain\",\"WlEcKr\":\"If none are selected, suitable for all ages.\",\"VCk0rR\":\"Image alt text\",\"STGpNQ\":\"Image options\",\"dSKHAa\":\"Invalid username or password\",\"MFKlMB\":\"Invite\",\"F5MZVk\":\"Invite a Friend\",\"6KlkHI\":\"Invite code\",\"F75w8j\":\"Join the waitlist\",\"6iVTdm\":\"Join the waitlist.\",\"SNzppu\":\"Join Waitlist\",\"Dcq5kL\":\"Language selection\",\"GAmD3h\":\"Languages\",\"NgeSlx\":\"Learn More\",\"rj0Lke\":\"Learn more about this warning\",\"kq2ga7\":\"Leave them all unchecked to see any language.\",\"QfDITI\":\"Leaving Bluesky\",\"Esfg1M\":\"Let's get your password reset!\",\"BvSY1i\":\"Like this feed\",\"FuZWua\":\"List Avatar\",\"8mjA4F\":\"List Name\",\"h16FyT\":\"Lists\",\"ujW4FW\":\"Load more posts\",\"VkLESX\":\"Load new posts\",\"jl0AFf\":\"Local dev server\",\"cR9UpQ\":\"Login to account that is not listed\",\"2U/gDT\":\"Make sure this is where you intend to go!\",\"zucql+\":\"Menu\",\"DzmsLV\":\"Moderation\",\"3Siwmw\":\"More options\",\"Y17r45\":\"More post options\",\"Mysqyf\":\"My Birthday\",\"6MBNS/\":\"My Feeds\",\"Ha6iBv\":\"My Saved Feeds\",\"6YtxFj\":\"Name\",\"8yolS6\":\"Never lose access to your followers and data.\",\"2B7HLH\":\"New post\",\"FGrimz\":\"New Post\",\"hXzOVo\":\"Next\",\"EatZYJ\":\"Next image\",\"flmDTf\":\"No description\",\"fOlAiK\":[\"No results found for \\\"\",[\"query\"],\"\\\"\"],\"kA9DpB\":[\"No results found for \",[\"0\"]],\"ispbnl\":\"Not Applicable\",\"iDNBZe\":\"Notifications\",\"UaXeX3\":\"Okay\",\"Cqo2D+\":\"One or more images is missing alt text.\",\"M/Q2aG\":\"Open navigation\",\"M5PuNq\":\"Opens configurable language settings\",\"eSqpax\":\"Opens modal for using custom domain\",\"vYwHHI\":\"Opens moderation settings\",\"0tHyB7\":\"Opens screen with all saved feeds\",\"nmRoY/\":\"Opens the app password settings page\",\"6e9Apv\":\"Opens the home feed preferences\",\"O87Dr/\":\"Opens the storybook page\",\"G+PVmg\":\"Opens the system log page\",\"Jqb7sy\":\"Opens the threads preferences\",\"b22AVl\":\"Other account\",\"n+HLOP\":\"Other service\",\"1PKxQ7\":\"Other...\",\"8ZsakT\":\"Password\",\"DKeVgZ\":\"Password updated!\",\"VeZE5Q\":\"Pictures meant for adults.\",\"Apyknf\":\"Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.\",\"9qpQ5O\":\"Please enter a unique name for this App Password or use our randomly generated one.\",\"QJr5Xp\":\"Please enter your password as well:\",\"y28hnO\":\"Post\",\"h5RcXU\":\"Post hidden\",\"r5zLS0\":\"Post language\",\"AzCucI\":\"Post Languages\",\"tJFPmV\":\"Post not found\",\"0+DQbr\":\"Potentially Misleading Link\",\"MHk+7g\":\"Previous image\",\"x8iR7V\":\"Prioritize Your Follows\",\"vERlcd\":\"Profile\",\"MrgqOW\":\"Protect your account by verifying your email.\",\"8HFFRQ\":\"Quote post\",\"+KrAHa\":\"Quote Post\",\"WlWsdE\":\"Ratios\",\"t/YqKh\":\"Remove\",\"5ywtDz\":\"Remove image\",\"Dw/XUh\":\"Remove image preview\",\"Veu9gK\":\"Reply Filters\",\"lQWbAr\":[\"Report \",[\"collectionName\"]],\"6IcSvC\":\"Report post\",\"JOV5dR\":\"Repost or quote post\",\"bqG37Z\":\"Request Change\",\"8XIT+P\":\"Required for this provider\",\"vJgYMA\":\"Reset code\",\"xEL92I\":\"Reset onboarding state\",\"bee/Fw\":\"Reset preferences state\",\"wToeoz\":\"Resets the onboarding state\",\"nIU7qI\":\"Resets the preferences state\",\"6gRgw8\":\"Retry\",\"hAbYQa\":\"Retry change handle\",\"tfDRzk\":\"Save\",\"KV2YQQ\":\"Save alt text\",\"y3aU20\":\"Save changes\",\"IUwGEM\":\"Save Changes\",\"Xs07Tg\":\"Save handle change\",\"BckA7m\":\"Save image crop\",\"A1taO8\":\"Search\",\"CKROFy\":\"Security Step Required\",\"cNzyJW\":\"See what's next\",\"L5sM7N\":\"Select Bluesky Social\",\"o3dwub\":\"Select from an existing account\",\"GGw2AK\":\"Select service\",\"vp9yIB\":\"Send Confirmation Email\",\"65dxv8\":\"Send email\",\"i/TzEU\":\"Send Email\",\"RoafuO\":\"Send feedback\",\"4cijjm\":\"Send Report\",\"V/e7nf\":\"Set new password\",\"gwsie4\":\"Set this setting to \\\"No\\\" to hide all quote posts from your feed. Reposts will still be visible.\",\"IZjC3J\":\"Set this setting to \\\"No\\\" to hide all replies from your feed.\",\"KIgU3l\":\"Set this setting to \\\"No\\\" to hide all reposts from your feed.\",\"zaAyrz\":\"Set this setting to \\\"Yes\\\" to show replies in a threaded view. This is an experimental feature.\",\"fQV2eE\":\"Set this setting to \\\"Yes\\\" to show samples of your saved feeds in your following feed. This is an experimental feature.\",\"Tz0i8g\":\"Settings\",\"HfWHhJ\":\"Sexual activity or erotic nudity.\",\"8vETh9\":\"Show\",\"aWAdCb\":\"Show anyway\",\"NijgXr\":\"Show Posts from My Feeds\",\"T3Mt8m\":\"Show Quote Posts\",\"BlW8X/\":\"Show Replies\",\"X4GwDb\":\"Show replies by people you follow before all other replies.\",\"GiogzH\":\"Show Reposts\",\"fhY/fL\":\"Show users\",\"5lWFkC\":\"Sign in\",\"n1ekoW\":\"Sign In\",\"N9o7n5\":[\"Sign in as \",[\"0\"]],\"FT1MVS\":\"Sign in as...\",\"+UpfFC\":\"Sign into\",\"fcWrnU\":\"Sign out\",\"zU+Ro7\":\"Signed in as\",\"6Uau97\":\"Skip\",\"0o5BFH\":\"Sort Replies\",\"GH1Rgk\":\"Sort replies to the same post by:\",\"1DA6ap\":\"Square\",\"aKEHLj\":\"Staging\",\"tgEXwM\":\"Status page\",\"P5jja7\":\"Storybook\",\"EDl9kS\":\"Subscribe\",\"5z3ICN\":\"Subscribe to this list\",\"VjWeLI\":\"Switch Account\",\"fP8jTZ\":\"System log\",\"HF6Iah\":\"Tall\",\"p8Iz39\":\"Text input field\",\"G4EksE\":\"The post may have been deleted.\",\"KRYn8w\":[\"This \",[\"screenDescription\"],\" has been flagged:\"],\"lm845B\":\"This information is not shared with other users.\",\"5Pvw/O\":\"This is important in case you ever need to change your email or reset your password.\",\"sQQfZ9\":\"This is the service that keeps you online.\",\"CvX8qs\":\"This link is taking you to the following website:\",\"WKrUVy\":\"This post has been deleted.\",\"u9ThjD\":\"Thread Preferences\",\"zmXsk5\":\"Threaded Mode\",\"1x30Qt\":\"Toggle dropdown\",\"KFXQEt\":\"Transformations\",\"pi8x/S\":\"Translate\",\"KDw4GX\":\"Try again\",\"nc4Wfd\":\"Unable to contact your service. Please check your Internet connection.\",\"tuS5Jz\":\"Unblock\",\"vaz2uI\":[\"Update \",[\"displayName\"],\" in Lists\"],\"RXbEvi\":\"Updating...\",\"Vwkfp4\":\"Upload a text file to:\",\"jTdnU6\":\"Use app passwords to login to other Bluesky clients without giving full access to your account or password.\",\"CH1am9\":\"Use default provider\",\"t4Yp4Z\":\"User handle\",\"nZx9mr\":\"Username or email address\",\"Sxm8rQ\":\"Users\",\"MBOY4U\":\"Verify email\",\"Ejyv0o\":\"Verify my email\",\"9czCrB\":\"Verify My Email\",\"ibSVGR\":\"Verify New Email\",\"nHsQde\":\"View debug entry\",\"47jzzd\":\"View the avatar\",\"wK4H1r\":\"Visit Site\",\"qjBGxf\":\"We're so excited to have you join us!\",\"Mj7rl/\":[\"What is the issue with this \",[\"collectionName\"],\"?\"],\"3qn29J\":\"Which languages are used in this post?\",\"uawiGa\":\"Which languages would you like to see in your algorithmic feeds?\",\"I5S9ZE\":\"Wide\",\"y02THm\":\"Write post\",\"6ckZRB\":\"Write your reply\",\"STPj0e\":\"You can change hosting providers at any time.\",\"67nRLM\":\"You can now sign in with your new password.\",\"RkXibf\":\"You have blocked the author or you have been blocked by the author.\",\"tCLJ9E\":\"You have no lists.\",\"NDgp3i\":\"You have not created any app passwords yet. You can create one by pressing the button below.\",\"RrDyEb\":\"You will receive an email with a \\\"reset code.\\\" Enter that code here, then enter your new password.\",\"gdRnT7\":\"Your account\",\"k7hmsH\":\"Your birth date\",\"OubkcP\":\"Your email has been saved! We'll be in touch soon.\",\"z2L+/9\":\"Your email has been updated but not verified. As a next step, please verify your new email.\",\"XZlIVw\":\"Your email has not yet been verified. This is an important security step which we recommend.\",\"qv9f4I\":\"Your full handle will be\",\"lvcqqG\":\"Your hosting provider\",\"Oqt/PG\":\"Your posts, likes, and blocks are public. Mutes are private.\",\"MvWO9d\":\"Your user handle\"}")};
\ No newline at end of file
diff --git a/src/locale/locales/cs/messages.po b/src/locale/locales/cs/messages.po
new file mode 100644
index 000000000..28ad5ba4c
--- /dev/null
+++ b/src/locale/locales/cs/messages.po
@@ -0,0 +1,1544 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2023-11-05 16:01-0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: cs\n"
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+#: src/view/screens/Profile.tsx:212
+msgid "- end of feed -"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:138
+msgid ". This warning is only available for posts with media attached."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:45
+msgid "{0}"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:167
+msgid "{0} {purposeLabel} List"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:132
+msgid "<0>Here is your app password.</0> Use this to sign into the other app along with your handle."
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:299
+#: src/view/screens/Settings.tsx:363
+msgid "Accessibility"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:157
+#: src/view/screens/Settings.tsx:201
+msgid "Account"
+msgstr ""
+
+#: src/view/com/util/AccountDropdownBtn.tsx:41
+msgid "Account options"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:710
+msgid "Add"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:57
+msgid "Add a content warning"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:700
+msgid "Add a user to this list"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:313
+#: src/view/screens/Settings.tsx:322
+msgid "Add account"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:119
+#: src/view/com/composer/photos/Gallery.tsx:167
+msgid "Add alt text"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:41
+#: src/view/com/modals/report/Modal.tsx:190
+msgid "Add details"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:193
+msgid "Add details to report"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:419
+msgid "Add link card"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:422
+msgid "Add link card:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:418
+msgid "Add the following DNS record to your domain:"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:140
+msgid "Adjust the number of likes a reply must have to be shown in your feed."
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:76
+msgid "Adult Content"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:493
+msgid "Advanced"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:127
+msgid "ALT"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:315
+msgid "Alt text"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:193
+msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:112
+msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:119
+msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:238
+msgid "and"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:509
+msgid "App passwords"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:378
+msgid "Appearance"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:124
+msgid "Artistic or non-erotic nudity."
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:92
+#: src/view/com/auth/login/ChooseAccountForm.tsx:111
+#: src/view/com/auth/login/LoginForm.tsx:247
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:150
+#: src/view/com/modals/report/InputIssueDetails.tsx:45
+#: src/view/com/post-thread/PostThread.tsx:317
+#: src/view/com/post-thread/PostThread.tsx:325
+#: src/view/com/post-thread/PostThread.tsx:354
+#: src/view/com/post-thread/PostThread.tsx:362
+#: src/view/com/profile/ProfileHeader.tsx:576
+msgid "Back"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:407
+msgid "Basics"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:130
+#: src/view/com/modals/BirthDateSettings.tsx:69
+msgid "Birthday"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:228
+msgid "Birthday:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:211
+msgid "Blocked post."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:52
+#: src/view/com/auth/SplashScreen.tsx:27
+msgid "Bluesky"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:84
+msgid "Bluesky is flexible."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:73
+msgid "Bluesky is open."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:60
+msgid "Bluesky is public."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:70
+msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon."
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:78
+msgid "Bluesky.Social"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:612
+msgid "Build version {0} {1}"
+msgstr ""
+
+#: src/view/com/composer/photos/OpenCameraBtn.tsx:62
+msgid "Camera"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:199
+msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:271
+#: src/view/com/composer/Composer.tsx:274
+#: src/view/com/modals/AltImage.tsx:127
+#: src/view/com/modals/ChangeEmail.tsx:216
+#: src/view/com/modals/ChangeEmail.tsx:218
+#: src/view/com/modals/Confirm.tsx:89
+#: src/view/com/modals/CreateOrEditList.tsx:258
+#: src/view/com/modals/CreateOrEditList.tsx:263
+#: src/view/com/modals/DeleteAccount.tsx:142
+#: src/view/com/modals/DeleteAccount.tsx:215
+#: src/view/com/modals/EditImage.tsx:323
+#: src/view/com/modals/EditProfile.tsx:250
+#: src/view/com/modals/LinkWarning.tsx:90
+#: src/view/com/modals/Repost.tsx:74
+#: src/view/com/modals/UserAddRemoveLists.tsx:199
+#: src/view/com/modals/Waitlist.tsx:136
+#: src/view/com/search/HeaderWithInput.tsx:127
+#: src/view/shell/desktop/Search.tsx:93
+msgid "Cancel"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:138
+#: src/view/com/modals/DeleteAccount.tsx:211
+msgid "Cancel account deletion"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:122
+msgid "Cancel add image alt text"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:144
+msgid "Cancel change handle"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:134
+msgid "Cancel image crop"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:245
+msgid "Cancel profile editing"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:65
+msgid "Cancel quote post"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:101
+#: src/view/shell/desktop/Search.tsx:89
+msgid "Cancel search"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:132
+msgid "Cancel waitlist signup"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:222
+msgid "Change"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:517
+#: src/view/screens/Settings.tsx:526
+msgid "Change handle"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:156
+msgid "Change Handle"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:136
+msgid "Change my email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:109
+msgid "Change Your Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:155
+msgid "Check your inbox for an email with the confirmation code to enter below:"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:38
+msgid "Choose Service"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:87
+msgid "Choose the algorithms that power your experience with custom feeds."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:105
+msgid "Choose your password"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:111
+#: src/view/com/util/forms/SearchInput.tsx:73
+msgid "Clear search query"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:38
+msgid "Close alert"
+msgstr ""
+
+#: src/view/com/util/BottomSheetCustomBackdrop.tsx:33
+msgid "Close bottom drawer"
+msgstr ""
+
+#: src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx:26
+msgid "Close image"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:107
+msgid "Close image viewer"
+msgstr ""
+
+#: src/view/shell/index.web.tsx:65
+msgid "Close navigation footer"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:22
+msgid "Compose reply"
+msgstr ""
+
+#: src/view/com/modals/Confirm.tsx:76
+#: src/view/com/modals/SelfLabel.tsx:156
+#: src/view/com/modals/VerifyEmail.tsx:220
+#: src/view/screens/PreferencesHomeFeed.tsx:223
+#: src/view/screens/PreferencesThreads.tsx:128
+msgid "Confirm"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:193
+#: src/view/com/modals/ChangeEmail.tsx:195
+msgid "Confirm Change"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34
+msgid "Confirm content language settings"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:201
+msgid "Confirm delete account"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:157
+#: src/view/com/modals/DeleteAccount.tsx:168
+#: src/view/com/modals/VerifyEmail.tsx:154
+msgid "Confirmation code"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:125
+#: src/view/com/auth/login/LoginForm.tsx:266
+msgid "Connecting..."
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:42
+msgid "Content Filtering"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:68
+msgid "Content Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:68
+msgid "Content Warning"
+msgstr ""
+
+#: src/view/com/composer/labels/LabelsBtn.tsx:32
+msgid "Content warnings"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:178
+#: src/view/com/modals/InviteCodes.tsx:129
+msgid "Copied"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:171
+msgid "Copy"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:97
+msgid "Could not load feed"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:788
+msgid "Could not load list"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:42
+msgid "Create a new account"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:77
+msgid "Create Account"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:39
+msgid "Create new account"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:390
+#: src/view/com/modals/ServerInput.tsx:102
+msgid "Custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:531
+msgid "Danger Zone"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:538
+msgid "Delete account"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:75
+msgid "Delete Account"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:193
+msgid "Delete app password"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:204
+msgid "Delete my account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:548
+msgid "Delete my account…"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:203
+msgid "Deleted post."
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:209
+#: src/view/com/modals/CreateOrEditList.tsx:225
+#: src/view/com/modals/EditProfile.tsx:199
+#: src/view/com/modals/EditProfile.tsx:211
+msgid "Description"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:112
+msgid "Dev Server"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:553
+msgid "Developer Tools"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:165
+msgid "Discover new feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:193
+msgid "Display name"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:181
+msgid "Display Name"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:488
+msgid "Domain verified!"
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:77
+#: src/view/com/modals/ContentFilteringSettings.tsx:85
+#: src/view/com/modals/crop-image/CropImage.web.tsx:152
+#: src/view/com/modals/EditImage.tsx:333
+#: src/view/com/modals/ListAddUser.tsx:153
+#: src/view/com/modals/SelfLabel.tsx:159
+#: src/view/screens/PreferencesHomeFeed.tsx:226
+#: src/view/screens/PreferencesThreads.tsx:131
+msgid "Done"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:42
+msgid "Done{extraText}"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:141
+#: src/view/com/modals/EditImage.tsx:207
+msgid "Edit image"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:132
+msgid "Edit My Feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:158
+msgid "Edit my profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:373
+msgid "Edit profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:376
+msgid "Edit Profile"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:92
+msgid "Edit Saved Feeds"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:89
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:145
+#: src/view/com/modals/ChangeEmail.tsx:141
+#: src/view/com/modals/Waitlist.tsx:88
+msgid "Email"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:80
+msgid "Email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:111
+msgid "Email Updated"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:123
+msgid "Enable this setting to only see replies between people you follow."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:87
+msgid "Enter the address of your provider:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:372
+msgid "Enter the domain you want to use"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:85
+msgid "Enter your email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:117
+msgid "Enter your new email address below."
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:96
+msgid "Enter your username and password"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:151
+msgid "Expand alt text"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:301
+msgid "Feed offline"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:163
+msgid "Feed Preferences"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:365
+msgid "Feedback"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:154
+#: src/view/shell/Drawer.tsx:289
+msgid "Feeds"
+msgstr ""
+
+#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:119
+msgid "Finding similar accounts..."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:90
+msgid "Fine-tune the content you see on your home screen."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:43
+msgid "Fine-tune the discussion threads."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:459
+msgid "Follow"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:537
+msgid "following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:443
+msgid "Following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:492
+msgid "Follows you"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:99
+msgid "For security reasons, we'll need to send a confirmation code to your email address."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:192
+msgid "For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:229
+msgid "Forgot"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:226
+msgid "Forgot password"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:126
+#: src/view/com/auth/login/Login.tsx:143
+msgid "Forgot Password"
+msgstr ""
+
+#: src/view/com/composer/photos/SelectPhotoBtn.tsx:43
+msgid "Gallery"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:178
+msgid "Get Started"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:105
+#: src/view/shell/desktop/LeftNav.tsx:92
+msgid "Go back"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:106
+#: src/view/screens/ProfileFeed.tsx:111
+#: src/view/screens/ProfileList.tsx:797
+#: src/view/screens/ProfileList.tsx:802
+msgid "Go Back"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:178
+#: src/view/com/auth/login/LoginForm.tsx:276
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:165
+msgid "Go to next"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:270
+msgid "Handle"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:375
+msgid "Help"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:316
+msgid "Hide"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:308
+msgid "Hide user list"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:110
+#: src/view/shell/Drawer.tsx:240
+msgid "Home"
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:69
+#: src/view/screens/Settings.tsx:423
+msgid "Home Feed Preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:111
+msgid "Hosting provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:92
+#: src/view/com/auth/create/Step1.tsx:97
+msgid "Hosting provider address"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:203
+msgid "I have a code"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:286
+msgid "I have my own domain"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:128
+msgid "If none are selected, suitable for all ages."
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:96
+msgid "Image alt text"
+msgstr ""
+
+#: src/view/com/util/UserAvatar.tsx:300
+#: src/view/com/util/UserBanner.tsx:118
+msgid "Image options"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:109
+msgid "Invalid username or password"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:336
+msgid "Invite"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:329
+msgid "Invite a Friend"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:56
+msgid "Invite code"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:67
+msgid "Join the waitlist"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:67
+#: src/view/com/auth/create/Step2.tsx:71
+msgid "Join the waitlist."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:124
+msgid "Join Waitlist"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:97
+msgid "Language selection"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:471
+msgid "Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/PostAlerts.tsx:47
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:55
+#: src/view/com/util/moderation/ScreenHider.tsx:88
+msgid "Learn More"
+msgstr ""
+
+#: src/view/com/util/moderation/ContentHider.tsx:75
+#: src/view/com/util/moderation/PostAlerts.tsx:40
+#: src/view/com/util/moderation/PostHider.tsx:76
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:47
+#: src/view/com/util/moderation/ScreenHider.tsx:85
+msgid "Learn more about this warning"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:76
+msgid "Leave them all unchecked to see any language."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:56
+msgid "Leaving Bluesky"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:127
+#: src/view/com/auth/login/Login.tsx:144
+msgid "Let's get your password reset!"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:479
+msgid "Like this feed"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:177
+msgid "List Avatar"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:190
+msgid "List Name"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:297
+msgid "Lists"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:220
+#: src/view/com/post-thread/PostThread.tsx:228
+msgid "Load more posts"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:194
+msgid "Load new posts"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:50
+msgid "Local dev server"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:93
+msgid "Login to account that is not listed"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:70
+msgid "Make sure this is where you intend to go!"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:71
+msgid "Menu"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:487
+#: src/view/shell/Drawer.tsx:304
+msgid "Moderation"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:469
+#: src/view/screens/ProfileFeed.tsx:312
+#: src/view/screens/ProfileList.tsx:542
+msgid "More options"
+msgstr ""
+
+#: src/view/com/util/forms/PostDropdownBtn.tsx:158
+msgid "More post options"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:53
+msgid "My Birthday"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:128
+msgid "My Feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:454
+msgid "My Saved Feeds"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:162
+#: src/view/com/modals/CreateOrEditList.tsx:202
+msgid "Name"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:76
+msgid "Never lose access to your followers and data."
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:203
+#: src/view/screens/Feeds.tsx:261
+#: src/view/screens/Profile.tsx:304
+#: src/view/screens/ProfileFeed.tsx:378
+#: src/view/screens/ProfileList.tsx:210
+#: src/view/screens/ProfileList.tsx:248
+#: src/view/shell/desktop/LeftNav.tsx:229
+msgid "New post"
+msgstr ""
+
+#: src/view/shell/desktop/LeftNav.tsx:239
+msgid "New Post"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:105
+#: src/view/com/auth/login/LoginForm.tsx:279
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:158
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:168
+msgid "Next"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:137
+msgid "Next image"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:472
+#: src/view/screens/ProfileList.tsx:667
+msgid "No description"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:207
+msgid "No results found for \"{query}\""
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:140
+#: src/view/shell/desktop/Search.tsx:112
+msgid "No results found for {0}"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:136
+msgid "Not Applicable"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:178
+#: src/view/shell/Drawer.tsx:262
+msgid "Notifications"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:41
+msgid "Okay"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:334
+msgid "One or more images is missing alt text."
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:50
+msgid "Open navigation"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:463
+msgid "Opens configurable language settings"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:284
+msgid "Opens modal for using custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:482
+msgid "Opens moderation settings"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:448
+msgid "Opens screen with all saved feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:501
+msgid "Opens the app password settings page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:415
+msgid "Opens the home feed preferences"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:580
+msgid "Opens the storybook page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:560
+msgid "Opens the system log page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:432
+msgid "Opens the threads preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:98
+msgid "Other account"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:88
+msgid "Other service"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:84
+msgid "Other..."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:100
+#: src/view/com/auth/create/Step2.tsx:110
+#: src/view/com/auth/login/LoginForm.tsx:214
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:132
+#: src/view/com/modals/DeleteAccount.tsx:183
+msgid "Password"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:28
+msgid "Password updated!"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:122
+msgid "Pictures meant for adults."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:67
+msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:125
+msgid "Please enter a unique name for this App Password or use our randomly generated one."
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:172
+msgid "Please enter your password as well:"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:317
+msgid "Post"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:343
+msgid "Post hidden"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:80
+msgid "Post language"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:69
+msgid "Post Languages"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:309
+msgid "Post not found"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:51
+msgid "Potentially Misleading Link"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:123
+msgid "Previous image"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:73
+msgid "Prioritize Your Follows"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:220
+#: src/view/shell/Drawer.tsx:161
+#: src/view/shell/Drawer.tsx:325
+msgid "Profile"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:689
+msgid "Protect your account by verifying your email."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:53
+msgid "Quote post"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:57
+msgid "Quote Post"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:236
+msgid "Ratios"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:84
+msgid "Remove"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:154
+msgid "Remove image"
+msgstr ""
+
+#: src/view/com/composer/ExternalEmbed.tsx:70
+msgid "Remove image preview"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:120
+msgid "Reply Filters"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:165
+msgid "Report {collectionName}"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:37
+msgid "Report post"
+msgstr ""
+
+#: src/view/com/util/post-ctrls/RepostButton.web.tsx:69
+msgid "Repost or quote post"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:181
+#: src/view/com/modals/ChangeEmail.tsx:183
+msgid "Request Change"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:52
+msgid "Required for this provider"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:110
+msgid "Reset code"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:602
+msgid "Reset onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:592
+msgid "Reset preferences state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:600
+msgid "Resets the onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:590
+msgid "Resets the preferences state"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:114
+#: src/view/com/auth/create/CreateAccount.tsx:118
+#: src/view/com/auth/login/LoginForm.tsx:256
+#: src/view/com/auth/login/LoginForm.tsx:259
+#: src/view/com/util/error/ErrorMessage.tsx:55
+#: src/view/com/util/error/ErrorScreen.tsx:65
+msgid "Retry"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:166
+msgid "Retry change handle"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:114
+#: src/view/com/modals/BirthDateSettings.tsx:90
+#: src/view/com/modals/BirthDateSettings.tsx:93
+#: src/view/com/modals/ChangeHandle.tsx:179
+#: src/view/com/modals/CreateOrEditList.tsx:240
+#: src/view/com/modals/CreateOrEditList.tsx:248
+#: src/view/com/modals/EditProfile.tsx:225
+msgid "Save"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:105
+msgid "Save alt text"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:210
+msgid "Save changes"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:233
+msgid "Save Changes"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:176
+msgid "Save handle change"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:144
+msgid "Save image crop"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:89
+#: src/view/com/search/HeaderWithInput.tsx:101
+#: src/view/com/util/forms/SearchInput.tsx:64
+#: src/view/shell/bottom-bar/BottomBar.tsx:132
+#: src/view/shell/desktop/Search.tsx:81
+#: src/view/shell/Drawer.tsx:218
+msgid "Search"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:110
+msgid "Security Step Required"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:30
+msgid "See what's next"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:75
+msgid "Select Bluesky Social"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:115
+msgid "Select from an existing account"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:141
+msgid "Select service"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:191
+msgid "Send Confirmation Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:119
+msgid "Send email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:130
+msgid "Send Email"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:349
+#: src/view/shell/Drawer.tsx:370
+msgid "Send feedback"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:45
+msgid "Send Report"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:80
+msgid "Set new password"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:172
+msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:101
+msgid "Set this setting to \"No\" to hide all replies from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:155
+msgid "Set this setting to \"No\" to hide all reposts from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:96
+msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:191
+msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:338
+msgid "Settings"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:126
+msgid "Sexual activity or erotic nudity."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:235
+msgid "Show"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:114
+msgid "Show anyway"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:188
+msgid "Show Posts from My Feeds"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:169
+msgid "Show Quote Posts"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:98
+msgid "Show Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:76
+msgid "Show replies by people you follow before all other replies."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:152
+msgid "Show Reposts"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:337
+msgid "Show users"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:95
+#: src/view/com/auth/SplashScreen.tsx:50
+msgid "Sign in"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:53
+#: src/view/com/auth/SplashScreen.web.tsx:59
+msgid "Sign In"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:65
+msgid "Sign in as {0}"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:56
+#: src/view/com/auth/login/Login.tsx:114
+msgid "Sign in as..."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:128
+msgid "Sign into"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:71
+#: src/view/com/modals/SwitchAccount.tsx:74
+#: src/view/screens/Settings.tsx:274
+#: src/view/screens/Settings.tsx:277
+msgid "Sign out"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:245
+msgid "Signed in as"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:37
+msgid "Skip"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:51
+msgid "Sort Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:54
+msgid "Sort replies to the same post by:"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:122
+msgid "Square"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:106
+#: src/view/com/modals/ServerInput.tsx:62
+msgid "Staging"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:624
+msgid "Status page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:582
+msgid "Storybook"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:533
+msgid "Subscribe"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:529
+msgid "Subscribe to this list"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:47
+msgid "Switch Account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:562
+msgid "System log"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:112
+msgid "Tall"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:50
+msgid "Text input field"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:312
+msgid "The post may have been deleted."
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:71
+msgid "This {screenDescription} has been flagged:"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:58
+msgid "This information is not shared with other users."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:107
+msgid "This is important in case you ever need to change your email or reset your password."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:71
+msgid "This is the service that keeps you online."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:63
+msgid "This link is taking you to the following website:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:176
+msgid "This post has been deleted."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:441
+msgid "Thread Preferences"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:93
+msgid "Threaded Mode"
+msgstr ""
+
+#: src/view/com/util/forms/DropdownButton.tsx:230
+msgid "Toggle dropdown"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:271
+msgid "Transformations"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:654
+msgid "Translate"
+msgstr ""
+
+#: src/view/com/util/error/ErrorScreen.tsx:73
+msgid "Try again"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:74
+#: src/view/com/auth/login/LoginForm.tsx:113
+msgid "Unable to contact your service. Please check your Internet connection."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:386
+#: src/view/com/profile/ProfileHeader.tsx:389
+msgid "Unblock"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:185
+msgid "Update {displayName} in Lists"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:174
+msgid "Updating..."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:456
+msgid "Upload a text file to:"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:148
+msgid "Use app passwords to login to other Bluesky clients without giving full access to your account or password."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:516
+msgid "Use default provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:37
+msgid "User handle"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:168
+#: src/view/com/auth/login/LoginForm.tsx:185
+msgid "Username or email address"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:694
+msgid "Users"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:650
+msgid "Verify email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:675
+msgid "Verify my email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:684
+msgid "Verify My Email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:205
+#: src/view/com/modals/ChangeEmail.tsx:207
+msgid "Verify New Email"
+msgstr ""
+
+#: src/view/screens/Log.tsx:53
+msgid "View debug entry"
+msgstr ""
+
+#: src/view/com/profile/ProfileSubpageHeader.tsx:127
+msgid "View the avatar"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:80
+msgid "Visit Site"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:78
+msgid "We're so excited to have you join us!"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:168
+msgid "What is the issue with this {collectionName}?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:72
+msgid "Which languages are used in this post?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:71
+msgid "Which languages would you like to see in your algorithmic feeds?"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:102
+msgid "Wide"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:390
+msgid "Write post"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:31
+msgid "Write your reply"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:122
+msgid "You can change hosting providers at any time."
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:31
+msgid "You can now sign in with your new password."
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:346
+msgid "You have blocked the author or you have been blocked by the author."
+msgstr ""
+
+#: src/view/com/lists/ListsList.tsx:112
+msgid "You have no lists."
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:55
+msgid "You have not created any app passwords yet. You can create one by pressing the button below."
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:83
+msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:42
+msgid "Your account"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:121
+msgid "Your birth date"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:107
+msgid "Your email has been saved! We'll be in touch soon."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:125
+msgid "Your email has been updated but not verified. As a next step, please verify your new email."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:102
+msgid "Your email has not yet been verified. This is an important security step which we recommend."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:41
+#: src/view/com/modals/ChangeHandle.tsx:275
+msgid "Your full handle will be"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:69
+msgid "Your hosting provider"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:63
+msgid "Your posts, likes, and blocks are public. Mutes are private."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:27
+msgid "Your user handle"
+msgstr ""
diff --git a/src/locale/locales/en/messages.js b/src/locale/locales/en/messages.js
new file mode 100644
index 000000000..8d85ab77c
--- /dev/null
+++ b/src/locale/locales/en/messages.js
@@ -0,0 +1 @@
+/*eslint-disable*/module.exports={messages:JSON.parse("{\"PBodTo\":\"- end of feed -\",\"EtUMsZ\":\". This warning is only available for posts with media attached.\",\"J/hVSQ\":[[\"0\"]],\"hZQerY\":[[\"0\"],\" \",[\"purposeLabel\"],\" List\"],\"6RmyWt\":\"<0>Here is your app password.</0> Use this to sign into the other app along with your handle.\",\"AnNF5e\":\"Accessibility\",\"AeXO77\":\"Account\",\"4WY4MD\":\"Account options\",\"m16xKo\":\"Add\",\"fBBX+K\":\"Add a content warning\",\"JU3hs2\":\"Add a user to this list\",\"MPPZ54\":\"Add account\",\"LkA8jz\":\"Add alt text\",\"Z8idyM\":\"Add details\",\"AoXl11\":\"Add details to report\",\"iE6B/9\":\"Add link card\",\"EXHdP1\":\"Add link card:\",\"x6laaL\":\"Add the following DNS record to your domain:\",\"jRrQFe\":\"Adjust the number of likes a reply must have to be shown in your feed.\",\"qLa52r\":\"Adult Content\",\"sxkWRg\":\"Advanced\",\"u2HO/d\":\"ALT\",\"u/DP73\":\"Alt text\",\"0QlT7/\":\"Alt text describes images for blind and low-vision users, and helps give context to everyone.\",\"woXbjq\":[\"An email has been sent to \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"Fon2dK\":[\"An email has been sent to your previous address, \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"HZFm5R\":\"and\",\"SMmUnj\":\"App passwords\",\"aAIQg2\":\"Appearance\",\"EbvWd3\":\"Artistic or non-erotic nudity.\",\"iH8pgl\":\"Back\",\"ehOkF+\":\"Basics\",\"+gCI2a\":\"Birthday\",\"pieVBA\":\"Birthday:\",\"HFCE4A\":\"Blocked post.\",\"7A9u1j\":\"Bluesky\",\"ZHmKSm\":\"Bluesky is flexible.\",\"odLrdl\":\"Bluesky is open.\",\"/LsWK4\":\"Bluesky is public.\",\"C50OGr\":\"Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon.\",\"klVoaP\":\"Bluesky.Social\",\"qxBitM\":[\"Build version \",[\"0\"],\" \",[\"1\"]],\"rT2cV+\":\"Camera\",\"JGGrPC\":\"Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long.\",\"dEgA5A\":\"Cancel\",\"aMH9rr\":\"Cancel account deletion\",\"kc3E4R\":\"Cancel add image alt text\",\"wg4LHQ\":\"Cancel change handle\",\"hFL1Li\":\"Cancel image crop\",\"tijH8t\":\"Cancel profile editing\",\"Qe4C/d\":\"Cancel quote post\",\"5TviPn\":\"Cancel search\",\"nss3UV\":\"Cancel waitlist signup\",\"o+XJ9D\":\"Change\",\"pQco5R\":\"Change handle\",\"Q5e1U/\":\"Change Handle\",\"a3NAfL\":\"Change my email\",\"4vatyk\":\"Change Your Email\",\"/+X+/K\":\"Check your inbox for an email with the confirmation code to enter below:\",\"Rt502e\":\"Choose Service\",\"/L45sc\":\"Choose the algorithms that power your experience with custom feeds.\",\"Wk8hkn\":\"Choose your password\",\"QbvBNV\":\"Clear search query\",\"flH7u/\":\"Close alert\",\"hYmnbk\":\"Close bottom drawer\",\"47L1V1\":\"Close image\",\"l49ujN\":\"Close image viewer\",\"UryHFO\":\"Close navigation footer\",\"o8UUti\":\"Compose reply\",\"7VpPHA\":\"Confirm\",\"q8upsf\":\"Confirm Change\",\"8pNKIr\":\"Confirm content language settings\",\"tGg8Kt\":\"Confirm delete account\",\"ioZOzk\":\"Confirmation code\",\"J28zul\":\"Connecting...\",\"m8j6up\":\"Content Filtering\",\"/PlAsF\":\"Content Languages\",\"cogwXi\":\"Content Warning\",\"FG7AQv\":\"Content warnings\",\"6V3Ea3\":\"Copied\",\"he3ygx\":\"Copy\",\"7wWvgo\":\"Could not load feed\",\"8NNr/O\":\"Could not load list\",\"mpt9T+\":\"Create a new account\",\"IS0nrP\":\"Create Account\",\"6HbhpU\":\"Create new account\",\"GAD3Dx\":\"Custom domain\",\"ZQKLI1\":\"Danger Zone\",\"ZDGm40\":\"Delete account\",\"vzX5FB\":\"Delete Account\",\"gUEtxf\":\"Delete app password\",\"ktknoE\":\"Delete my account\",\"szz0+N\":\"Delete my account…\",\"u+1OHY\":\"Deleted post.\",\"Nu4oKW\":\"Description\",\"dacKHE\":\"Dev Server\",\"2ygkE8\":\"Developer Tools\",\"pbLwal\":\"Discover new feeds\",\"pfa8F0\":\"Display name\",\"0gS7M5\":\"Display Name\",\"iZ5pMB\":\"Domain verified!\",\"DPfwMq\":\"Done\",\"zT97vP\":[\"Done\",[\"extraText\"]],\"XQFMOm\":\"Edit image\",\"cLmurE\":\"Edit My Feeds\",\"bRZ5XW\":\"Edit my profile\",\"9OpVZg\":\"Edit profile\",\"QJQd1J\":\"Edit Profile\",\"Jn7kox\":\"Edit Saved Feeds\",\"O3oNi5\":\"Email\",\"ATGYL1\":\"Email address\",\"pJJ0Vp\":\"Email Updated\",\"96mted\":\"Enable this setting to only see replies between people you follow.\",\"YbIxza\":\"Enter the address of your provider:\",\"BfIgP6\":\"Enter the domain you want to use\",\"xRPn3U\":\"Enter your email address\",\"+inPGm\":\"Enter your new email address below.\",\"T0KLp4\":\"Enter your username and password\",\"0PkE20\":\"Expand alt text\",\"4yCy8i\":\"Feed offline\",\"N0CqyO\":\"Feed Preferences\",\"YirHq7\":\"Feedback\",\"2DoBvq\":\"Feeds\",\"Qzj1WT\":\"Finding similar accounts...\",\"QKSrQV\":\"Fine-tune the content you see on your home screen.\",\"r+KeyR\":\"Fine-tune the discussion threads.\",\"MKEPCY\":\"Follow\",\"NIjL2Y\":\"following\",\"y6sq5j\":\"Following\",\"p3UO/y\":\"Follows you\",\"5RhDkD\":\"For security reasons, we'll need to send a confirmation code to your email address.\",\"NJPhAO\":\"For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one.\",\"5bDfuq\":\"Forgot\",\"hEPLrs\":\"Forgot password\",\"dn8X5t\":\"Forgot Password\",\"U+kFad\":\"Gallery\",\"c3b0B0\":\"Get Started\",\"CKyk7Q\":\"Go back\",\"sr0UJD\":\"Go Back\",\"Rtp0y7\":\"Go to next\",\"Nf7oXL\":\"Handle\",\"c3XJ18\":\"Help\",\"vLyv1R\":\"Hide\",\"qdOx2q\":\"Hide user list\",\"i0qMbr\":\"Home\",\"sXZ8IU\":\"Home Feed Preferences\",\"yt7fhu\":\"Hosting provider\",\"s2xA6t\":\"Hosting provider address\",\"o+axy6\":\"I have a code\",\"wey2os\":\"I have my own domain\",\"WlEcKr\":\"If none are selected, suitable for all ages.\",\"VCk0rR\":\"Image alt text\",\"STGpNQ\":\"Image options\",\"dSKHAa\":\"Invalid username or password\",\"MFKlMB\":\"Invite\",\"F5MZVk\":\"Invite a Friend\",\"6KlkHI\":\"Invite code\",\"F75w8j\":\"Join the waitlist\",\"6iVTdm\":\"Join the waitlist.\",\"SNzppu\":\"Join Waitlist\",\"Dcq5kL\":\"Language selection\",\"GAmD3h\":\"Languages\",\"NgeSlx\":\"Learn More\",\"rj0Lke\":\"Learn more about this warning\",\"kq2ga7\":\"Leave them all unchecked to see any language.\",\"QfDITI\":\"Leaving Bluesky\",\"Esfg1M\":\"Let's get your password reset!\",\"BvSY1i\":\"Like this feed\",\"FuZWua\":\"List Avatar\",\"8mjA4F\":\"List Name\",\"h16FyT\":\"Lists\",\"ujW4FW\":\"Load more posts\",\"VkLESX\":\"Load new posts\",\"jl0AFf\":\"Local dev server\",\"cR9UpQ\":\"Login to account that is not listed\",\"2U/gDT\":\"Make sure this is where you intend to go!\",\"zucql+\":\"Menu\",\"DzmsLV\":\"Moderation\",\"3Siwmw\":\"More options\",\"Y17r45\":\"More post options\",\"Mysqyf\":\"My Birthday\",\"6MBNS/\":\"My Feeds\",\"Ha6iBv\":\"My Saved Feeds\",\"6YtxFj\":\"Name\",\"8yolS6\":\"Never lose access to your followers and data.\",\"2B7HLH\":\"New post\",\"FGrimz\":\"New Post\",\"hXzOVo\":\"Next\",\"EatZYJ\":\"Next image\",\"flmDTf\":\"No description\",\"fOlAiK\":[\"No results found for \\\"\",[\"query\"],\"\\\"\"],\"kA9DpB\":[\"No results found for \",[\"0\"]],\"ispbnl\":\"Not Applicable\",\"iDNBZe\":\"Notifications\",\"UaXeX3\":\"Okay\",\"Cqo2D+\":\"One or more images is missing alt text.\",\"M/Q2aG\":\"Open navigation\",\"M5PuNq\":\"Opens configurable language settings\",\"eSqpax\":\"Opens modal for using custom domain\",\"vYwHHI\":\"Opens moderation settings\",\"0tHyB7\":\"Opens screen with all saved feeds\",\"nmRoY/\":\"Opens the app password settings page\",\"6e9Apv\":\"Opens the home feed preferences\",\"O87Dr/\":\"Opens the storybook page\",\"G+PVmg\":\"Opens the system log page\",\"Jqb7sy\":\"Opens the threads preferences\",\"b22AVl\":\"Other account\",\"n+HLOP\":\"Other service\",\"1PKxQ7\":\"Other...\",\"8ZsakT\":\"Password\",\"DKeVgZ\":\"Password updated!\",\"VeZE5Q\":\"Pictures meant for adults.\",\"Apyknf\":\"Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.\",\"9qpQ5O\":\"Please enter a unique name for this App Password or use our randomly generated one.\",\"QJr5Xp\":\"Please enter your password as well:\",\"y28hnO\":\"Post\",\"h5RcXU\":\"Post hidden\",\"r5zLS0\":\"Post language\",\"AzCucI\":\"Post Languages\",\"tJFPmV\":\"Post not found\",\"0+DQbr\":\"Potentially Misleading Link\",\"MHk+7g\":\"Previous image\",\"x8iR7V\":\"Prioritize Your Follows\",\"vERlcd\":\"Profile\",\"MrgqOW\":\"Protect your account by verifying your email.\",\"8HFFRQ\":\"Quote post\",\"+KrAHa\":\"Quote Post\",\"WlWsdE\":\"Ratios\",\"t/YqKh\":\"Remove\",\"5ywtDz\":\"Remove image\",\"Dw/XUh\":\"Remove image preview\",\"Veu9gK\":\"Reply Filters\",\"lQWbAr\":[\"Report \",[\"collectionName\"]],\"6IcSvC\":\"Report post\",\"JOV5dR\":\"Repost or quote post\",\"bqG37Z\":\"Request Change\",\"8XIT+P\":\"Required for this provider\",\"vJgYMA\":\"Reset code\",\"xEL92I\":\"Reset onboarding state\",\"bee/Fw\":\"Reset preferences state\",\"wToeoz\":\"Resets the onboarding state\",\"nIU7qI\":\"Resets the preferences state\",\"6gRgw8\":\"Retry\",\"hAbYQa\":\"Retry change handle\",\"tfDRzk\":\"Save\",\"KV2YQQ\":\"Save alt text\",\"y3aU20\":\"Save changes\",\"IUwGEM\":\"Save Changes\",\"Xs07Tg\":\"Save handle change\",\"BckA7m\":\"Save image crop\",\"A1taO8\":\"Search\",\"CKROFy\":\"Security Step Required\",\"cNzyJW\":\"See what's next\",\"L5sM7N\":\"Select Bluesky Social\",\"o3dwub\":\"Select from an existing account\",\"GGw2AK\":\"Select service\",\"vp9yIB\":\"Send Confirmation Email\",\"65dxv8\":\"Send email\",\"i/TzEU\":\"Send Email\",\"RoafuO\":\"Send feedback\",\"4cijjm\":\"Send Report\",\"V/e7nf\":\"Set new password\",\"gwsie4\":\"Set this setting to \\\"No\\\" to hide all quote posts from your feed. Reposts will still be visible.\",\"IZjC3J\":\"Set this setting to \\\"No\\\" to hide all replies from your feed.\",\"KIgU3l\":\"Set this setting to \\\"No\\\" to hide all reposts from your feed.\",\"zaAyrz\":\"Set this setting to \\\"Yes\\\" to show replies in a threaded view. This is an experimental feature.\",\"fQV2eE\":\"Set this setting to \\\"Yes\\\" to show samples of your saved feeds in your following feed. This is an experimental feature.\",\"Tz0i8g\":\"Settings\",\"HfWHhJ\":\"Sexual activity or erotic nudity.\",\"8vETh9\":\"Show\",\"aWAdCb\":\"Show anyway\",\"NijgXr\":\"Show Posts from My Feeds\",\"T3Mt8m\":\"Show Quote Posts\",\"BlW8X/\":\"Show Replies\",\"X4GwDb\":\"Show replies by people you follow before all other replies.\",\"GiogzH\":\"Show Reposts\",\"fhY/fL\":\"Show users\",\"5lWFkC\":\"Sign in\",\"n1ekoW\":\"Sign In\",\"N9o7n5\":[\"Sign in as \",[\"0\"]],\"FT1MVS\":\"Sign in as...\",\"+UpfFC\":\"Sign into\",\"fcWrnU\":\"Sign out\",\"zU+Ro7\":\"Signed in as\",\"6Uau97\":\"Skip\",\"0o5BFH\":\"Sort Replies\",\"GH1Rgk\":\"Sort replies to the same post by:\",\"1DA6ap\":\"Square\",\"aKEHLj\":\"Staging\",\"tgEXwM\":\"Status page\",\"P5jja7\":\"Storybook\",\"EDl9kS\":\"Subscribe\",\"5z3ICN\":\"Subscribe to this list\",\"VjWeLI\":\"Switch Account\",\"fP8jTZ\":\"System log\",\"HF6Iah\":\"Tall\",\"p8Iz39\":\"Text input field\",\"G4EksE\":\"The post may have been deleted.\",\"KRYn8w\":[\"This \",[\"screenDescription\"],\" has been flagged:\"],\"lm845B\":\"This information is not shared with other users.\",\"5Pvw/O\":\"This is important in case you ever need to change your email or reset your password.\",\"sQQfZ9\":\"This is the service that keeps you online.\",\"CvX8qs\":\"This link is taking you to the following website:\",\"WKrUVy\":\"This post has been deleted.\",\"u9ThjD\":\"Thread Preferences\",\"zmXsk5\":\"Threaded Mode\",\"1x30Qt\":\"Toggle dropdown\",\"KFXQEt\":\"Transformations\",\"pi8x/S\":\"Translate\",\"KDw4GX\":\"Try again\",\"nc4Wfd\":\"Unable to contact your service. Please check your Internet connection.\",\"tuS5Jz\":\"Unblock\",\"vaz2uI\":[\"Update \",[\"displayName\"],\" in Lists\"],\"RXbEvi\":\"Updating...\",\"Vwkfp4\":\"Upload a text file to:\",\"jTdnU6\":\"Use app passwords to login to other Bluesky clients without giving full access to your account or password.\",\"CH1am9\":\"Use default provider\",\"t4Yp4Z\":\"User handle\",\"nZx9mr\":\"Username or email address\",\"Sxm8rQ\":\"Users\",\"MBOY4U\":\"Verify email\",\"Ejyv0o\":\"Verify my email\",\"9czCrB\":\"Verify My Email\",\"ibSVGR\":\"Verify New Email\",\"nHsQde\":\"View debug entry\",\"47jzzd\":\"View the avatar\",\"wK4H1r\":\"Visit Site\",\"qjBGxf\":\"We're so excited to have you join us!\",\"Mj7rl/\":[\"What is the issue with this \",[\"collectionName\"],\"?\"],\"3qn29J\":\"Which languages are used in this post?\",\"uawiGa\":\"Which languages would you like to see in your algorithmic feeds?\",\"I5S9ZE\":\"Wide\",\"y02THm\":\"Write post\",\"6ckZRB\":\"Write your reply\",\"STPj0e\":\"You can change hosting providers at any time.\",\"67nRLM\":\"You can now sign in with your new password.\",\"RkXibf\":\"You have blocked the author or you have been blocked by the author.\",\"tCLJ9E\":\"You have no lists.\",\"NDgp3i\":\"You have not created any app passwords yet. You can create one by pressing the button below.\",\"RrDyEb\":\"You will receive an email with a \\\"reset code.\\\" Enter that code here, then enter your new password.\",\"gdRnT7\":\"Your account\",\"k7hmsH\":\"Your birth date\",\"OubkcP\":\"Your email has been saved! We'll be in touch soon.\",\"z2L+/9\":\"Your email has been updated but not verified. As a next step, please verify your new email.\",\"XZlIVw\":\"Your email has not yet been verified. This is an important security step which we recommend.\",\"qv9f4I\":\"Your full handle will be\",\"lvcqqG\":\"Your hosting provider\",\"Oqt/PG\":\"Your posts, likes, and blocks are public. Mutes are private.\",\"MvWO9d\":\"Your user handle\"}")};
\ No newline at end of file
diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po
new file mode 100644
index 000000000..586303586
--- /dev/null
+++ b/src/locale/locales/en/messages.po
@@ -0,0 +1,1544 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2023-11-05 16:01-0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: en\n"
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+#: src/view/screens/Profile.tsx:212
+msgid "- end of feed -"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:138
+msgid ". This warning is only available for posts with media attached."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:45
+msgid "{0}"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:167
+msgid "{0} {purposeLabel} List"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:132
+msgid "<0>Here is your app password.</0> Use this to sign into the other app along with your handle."
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:299
+#: src/view/screens/Settings.tsx:363
+msgid "Accessibility"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:157
+#: src/view/screens/Settings.tsx:201
+msgid "Account"
+msgstr ""
+
+#: src/view/com/util/AccountDropdownBtn.tsx:41
+msgid "Account options"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:710
+msgid "Add"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:57
+msgid "Add a content warning"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:700
+msgid "Add a user to this list"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:313
+#: src/view/screens/Settings.tsx:322
+msgid "Add account"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:119
+#: src/view/com/composer/photos/Gallery.tsx:167
+msgid "Add alt text"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:41
+#: src/view/com/modals/report/Modal.tsx:190
+msgid "Add details"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:193
+msgid "Add details to report"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:419
+msgid "Add link card"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:422
+msgid "Add link card:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:418
+msgid "Add the following DNS record to your domain:"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:140
+msgid "Adjust the number of likes a reply must have to be shown in your feed."
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:76
+msgid "Adult Content"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:493
+msgid "Advanced"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:127
+msgid "ALT"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:315
+msgid "Alt text"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:193
+msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:112
+msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:119
+msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:238
+msgid "and"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:509
+msgid "App passwords"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:378
+msgid "Appearance"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:124
+msgid "Artistic or non-erotic nudity."
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:92
+#: src/view/com/auth/login/ChooseAccountForm.tsx:111
+#: src/view/com/auth/login/LoginForm.tsx:247
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:150
+#: src/view/com/modals/report/InputIssueDetails.tsx:45
+#: src/view/com/post-thread/PostThread.tsx:317
+#: src/view/com/post-thread/PostThread.tsx:325
+#: src/view/com/post-thread/PostThread.tsx:354
+#: src/view/com/post-thread/PostThread.tsx:362
+#: src/view/com/profile/ProfileHeader.tsx:576
+msgid "Back"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:407
+msgid "Basics"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:130
+#: src/view/com/modals/BirthDateSettings.tsx:69
+msgid "Birthday"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:228
+msgid "Birthday:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:211
+msgid "Blocked post."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:52
+#: src/view/com/auth/SplashScreen.tsx:27
+msgid "Bluesky"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:84
+msgid "Bluesky is flexible."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:73
+msgid "Bluesky is open."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:60
+msgid "Bluesky is public."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:70
+msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon."
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:78
+msgid "Bluesky.Social"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:612
+msgid "Build version {0} {1}"
+msgstr ""
+
+#: src/view/com/composer/photos/OpenCameraBtn.tsx:62
+msgid "Camera"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:199
+msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:271
+#: src/view/com/composer/Composer.tsx:274
+#: src/view/com/modals/AltImage.tsx:127
+#: src/view/com/modals/ChangeEmail.tsx:216
+#: src/view/com/modals/ChangeEmail.tsx:218
+#: src/view/com/modals/Confirm.tsx:89
+#: src/view/com/modals/CreateOrEditList.tsx:258
+#: src/view/com/modals/CreateOrEditList.tsx:263
+#: src/view/com/modals/DeleteAccount.tsx:142
+#: src/view/com/modals/DeleteAccount.tsx:215
+#: src/view/com/modals/EditImage.tsx:323
+#: src/view/com/modals/EditProfile.tsx:250
+#: src/view/com/modals/LinkWarning.tsx:90
+#: src/view/com/modals/Repost.tsx:74
+#: src/view/com/modals/UserAddRemoveLists.tsx:199
+#: src/view/com/modals/Waitlist.tsx:136
+#: src/view/com/search/HeaderWithInput.tsx:127
+#: src/view/shell/desktop/Search.tsx:93
+msgid "Cancel"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:138
+#: src/view/com/modals/DeleteAccount.tsx:211
+msgid "Cancel account deletion"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:122
+msgid "Cancel add image alt text"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:144
+msgid "Cancel change handle"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:134
+msgid "Cancel image crop"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:245
+msgid "Cancel profile editing"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:65
+msgid "Cancel quote post"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:101
+#: src/view/shell/desktop/Search.tsx:89
+msgid "Cancel search"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:132
+msgid "Cancel waitlist signup"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:222
+msgid "Change"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:517
+#: src/view/screens/Settings.tsx:526
+msgid "Change handle"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:156
+msgid "Change Handle"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:136
+msgid "Change my email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:109
+msgid "Change Your Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:155
+msgid "Check your inbox for an email with the confirmation code to enter below:"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:38
+msgid "Choose Service"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:87
+msgid "Choose the algorithms that power your experience with custom feeds."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:105
+msgid "Choose your password"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:111
+#: src/view/com/util/forms/SearchInput.tsx:73
+msgid "Clear search query"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:38
+msgid "Close alert"
+msgstr ""
+
+#: src/view/com/util/BottomSheetCustomBackdrop.tsx:33
+msgid "Close bottom drawer"
+msgstr ""
+
+#: src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx:26
+msgid "Close image"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:107
+msgid "Close image viewer"
+msgstr ""
+
+#: src/view/shell/index.web.tsx:65
+msgid "Close navigation footer"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:22
+msgid "Compose reply"
+msgstr ""
+
+#: src/view/com/modals/Confirm.tsx:76
+#: src/view/com/modals/SelfLabel.tsx:156
+#: src/view/com/modals/VerifyEmail.tsx:220
+#: src/view/screens/PreferencesHomeFeed.tsx:223
+#: src/view/screens/PreferencesThreads.tsx:128
+msgid "Confirm"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:193
+#: src/view/com/modals/ChangeEmail.tsx:195
+msgid "Confirm Change"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34
+msgid "Confirm content language settings"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:201
+msgid "Confirm delete account"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:157
+#: src/view/com/modals/DeleteAccount.tsx:168
+#: src/view/com/modals/VerifyEmail.tsx:154
+msgid "Confirmation code"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:125
+#: src/view/com/auth/login/LoginForm.tsx:266
+msgid "Connecting..."
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:42
+msgid "Content Filtering"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:68
+msgid "Content Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:68
+msgid "Content Warning"
+msgstr ""
+
+#: src/view/com/composer/labels/LabelsBtn.tsx:32
+msgid "Content warnings"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:178
+#: src/view/com/modals/InviteCodes.tsx:129
+msgid "Copied"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:171
+msgid "Copy"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:97
+msgid "Could not load feed"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:788
+msgid "Could not load list"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:42
+msgid "Create a new account"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:77
+msgid "Create Account"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:39
+msgid "Create new account"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:390
+#: src/view/com/modals/ServerInput.tsx:102
+msgid "Custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:531
+msgid "Danger Zone"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:538
+msgid "Delete account"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:75
+msgid "Delete Account"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:193
+msgid "Delete app password"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:204
+msgid "Delete my account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:548
+msgid "Delete my account…"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:203
+msgid "Deleted post."
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:209
+#: src/view/com/modals/CreateOrEditList.tsx:225
+#: src/view/com/modals/EditProfile.tsx:199
+#: src/view/com/modals/EditProfile.tsx:211
+msgid "Description"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:112
+msgid "Dev Server"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:553
+msgid "Developer Tools"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:165
+msgid "Discover new feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:193
+msgid "Display name"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:181
+msgid "Display Name"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:488
+msgid "Domain verified!"
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:77
+#: src/view/com/modals/ContentFilteringSettings.tsx:85
+#: src/view/com/modals/crop-image/CropImage.web.tsx:152
+#: src/view/com/modals/EditImage.tsx:333
+#: src/view/com/modals/ListAddUser.tsx:153
+#: src/view/com/modals/SelfLabel.tsx:159
+#: src/view/screens/PreferencesHomeFeed.tsx:226
+#: src/view/screens/PreferencesThreads.tsx:131
+msgid "Done"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:42
+msgid "Done{extraText}"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:141
+#: src/view/com/modals/EditImage.tsx:207
+msgid "Edit image"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:132
+msgid "Edit My Feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:158
+msgid "Edit my profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:373
+msgid "Edit profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:376
+msgid "Edit Profile"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:92
+msgid "Edit Saved Feeds"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:89
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:145
+#: src/view/com/modals/ChangeEmail.tsx:141
+#: src/view/com/modals/Waitlist.tsx:88
+msgid "Email"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:80
+msgid "Email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:111
+msgid "Email Updated"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:123
+msgid "Enable this setting to only see replies between people you follow."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:87
+msgid "Enter the address of your provider:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:372
+msgid "Enter the domain you want to use"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:85
+msgid "Enter your email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:117
+msgid "Enter your new email address below."
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:96
+msgid "Enter your username and password"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:151
+msgid "Expand alt text"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:301
+msgid "Feed offline"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:163
+msgid "Feed Preferences"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:365
+msgid "Feedback"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:154
+#: src/view/shell/Drawer.tsx:289
+msgid "Feeds"
+msgstr ""
+
+#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:119
+msgid "Finding similar accounts..."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:90
+msgid "Fine-tune the content you see on your home screen."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:43
+msgid "Fine-tune the discussion threads."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:459
+msgid "Follow"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:537
+msgid "following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:443
+msgid "Following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:492
+msgid "Follows you"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:99
+msgid "For security reasons, we'll need to send a confirmation code to your email address."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:192
+msgid "For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:229
+msgid "Forgot"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:226
+msgid "Forgot password"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:126
+#: src/view/com/auth/login/Login.tsx:143
+msgid "Forgot Password"
+msgstr ""
+
+#: src/view/com/composer/photos/SelectPhotoBtn.tsx:43
+msgid "Gallery"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:178
+msgid "Get Started"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:105
+#: src/view/shell/desktop/LeftNav.tsx:92
+msgid "Go back"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:106
+#: src/view/screens/ProfileFeed.tsx:111
+#: src/view/screens/ProfileList.tsx:797
+#: src/view/screens/ProfileList.tsx:802
+msgid "Go Back"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:178
+#: src/view/com/auth/login/LoginForm.tsx:276
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:165
+msgid "Go to next"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:270
+msgid "Handle"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:375
+msgid "Help"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:316
+msgid "Hide"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:308
+msgid "Hide user list"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:110
+#: src/view/shell/Drawer.tsx:240
+msgid "Home"
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:69
+#: src/view/screens/Settings.tsx:423
+msgid "Home Feed Preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:111
+msgid "Hosting provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:92
+#: src/view/com/auth/create/Step1.tsx:97
+msgid "Hosting provider address"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:203
+msgid "I have a code"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:286
+msgid "I have my own domain"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:128
+msgid "If none are selected, suitable for all ages."
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:96
+msgid "Image alt text"
+msgstr ""
+
+#: src/view/com/util/UserAvatar.tsx:300
+#: src/view/com/util/UserBanner.tsx:118
+msgid "Image options"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:109
+msgid "Invalid username or password"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:336
+msgid "Invite"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:329
+msgid "Invite a Friend"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:56
+msgid "Invite code"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:67
+msgid "Join the waitlist"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:67
+#: src/view/com/auth/create/Step2.tsx:71
+msgid "Join the waitlist."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:124
+msgid "Join Waitlist"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:97
+msgid "Language selection"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:471
+msgid "Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/PostAlerts.tsx:47
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:55
+#: src/view/com/util/moderation/ScreenHider.tsx:88
+msgid "Learn More"
+msgstr ""
+
+#: src/view/com/util/moderation/ContentHider.tsx:75
+#: src/view/com/util/moderation/PostAlerts.tsx:40
+#: src/view/com/util/moderation/PostHider.tsx:76
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:47
+#: src/view/com/util/moderation/ScreenHider.tsx:85
+msgid "Learn more about this warning"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:76
+msgid "Leave them all unchecked to see any language."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:56
+msgid "Leaving Bluesky"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:127
+#: src/view/com/auth/login/Login.tsx:144
+msgid "Let's get your password reset!"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:479
+msgid "Like this feed"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:177
+msgid "List Avatar"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:190
+msgid "List Name"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:297
+msgid "Lists"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:220
+#: src/view/com/post-thread/PostThread.tsx:228
+msgid "Load more posts"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:194
+msgid "Load new posts"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:50
+msgid "Local dev server"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:93
+msgid "Login to account that is not listed"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:70
+msgid "Make sure this is where you intend to go!"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:71
+msgid "Menu"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:487
+#: src/view/shell/Drawer.tsx:304
+msgid "Moderation"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:469
+#: src/view/screens/ProfileFeed.tsx:312
+#: src/view/screens/ProfileList.tsx:542
+msgid "More options"
+msgstr ""
+
+#: src/view/com/util/forms/PostDropdownBtn.tsx:158
+msgid "More post options"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:53
+msgid "My Birthday"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:128
+msgid "My Feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:454
+msgid "My Saved Feeds"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:162
+#: src/view/com/modals/CreateOrEditList.tsx:202
+msgid "Name"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:76
+msgid "Never lose access to your followers and data."
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:203
+#: src/view/screens/Feeds.tsx:261
+#: src/view/screens/Profile.tsx:304
+#: src/view/screens/ProfileFeed.tsx:378
+#: src/view/screens/ProfileList.tsx:210
+#: src/view/screens/ProfileList.tsx:248
+#: src/view/shell/desktop/LeftNav.tsx:229
+msgid "New post"
+msgstr ""
+
+#: src/view/shell/desktop/LeftNav.tsx:239
+msgid "New Post"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:105
+#: src/view/com/auth/login/LoginForm.tsx:279
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:158
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:168
+msgid "Next"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:137
+msgid "Next image"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:472
+#: src/view/screens/ProfileList.tsx:667
+msgid "No description"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:207
+msgid "No results found for \"{query}\""
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:140
+#: src/view/shell/desktop/Search.tsx:112
+msgid "No results found for {0}"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:136
+msgid "Not Applicable"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:178
+#: src/view/shell/Drawer.tsx:262
+msgid "Notifications"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:41
+msgid "Okay"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:334
+msgid "One or more images is missing alt text."
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:50
+msgid "Open navigation"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:463
+msgid "Opens configurable language settings"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:284
+msgid "Opens modal for using custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:482
+msgid "Opens moderation settings"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:448
+msgid "Opens screen with all saved feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:501
+msgid "Opens the app password settings page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:415
+msgid "Opens the home feed preferences"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:580
+msgid "Opens the storybook page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:560
+msgid "Opens the system log page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:432
+msgid "Opens the threads preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:98
+msgid "Other account"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:88
+msgid "Other service"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:84
+msgid "Other..."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:100
+#: src/view/com/auth/create/Step2.tsx:110
+#: src/view/com/auth/login/LoginForm.tsx:214
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:132
+#: src/view/com/modals/DeleteAccount.tsx:183
+msgid "Password"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:28
+msgid "Password updated!"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:122
+msgid "Pictures meant for adults."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:67
+msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:125
+msgid "Please enter a unique name for this App Password or use our randomly generated one."
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:172
+msgid "Please enter your password as well:"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:317
+msgid "Post"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:343
+msgid "Post hidden"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:80
+msgid "Post language"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:69
+msgid "Post Languages"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:309
+msgid "Post not found"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:51
+msgid "Potentially Misleading Link"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:123
+msgid "Previous image"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:73
+msgid "Prioritize Your Follows"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:220
+#: src/view/shell/Drawer.tsx:161
+#: src/view/shell/Drawer.tsx:325
+msgid "Profile"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:689
+msgid "Protect your account by verifying your email."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:53
+msgid "Quote post"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:57
+msgid "Quote Post"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:236
+msgid "Ratios"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:84
+msgid "Remove"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:154
+msgid "Remove image"
+msgstr ""
+
+#: src/view/com/composer/ExternalEmbed.tsx:70
+msgid "Remove image preview"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:120
+msgid "Reply Filters"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:165
+msgid "Report {collectionName}"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:37
+msgid "Report post"
+msgstr ""
+
+#: src/view/com/util/post-ctrls/RepostButton.web.tsx:69
+msgid "Repost or quote post"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:181
+#: src/view/com/modals/ChangeEmail.tsx:183
+msgid "Request Change"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:52
+msgid "Required for this provider"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:110
+msgid "Reset code"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:602
+msgid "Reset onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:592
+msgid "Reset preferences state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:600
+msgid "Resets the onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:590
+msgid "Resets the preferences state"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:114
+#: src/view/com/auth/create/CreateAccount.tsx:118
+#: src/view/com/auth/login/LoginForm.tsx:256
+#: src/view/com/auth/login/LoginForm.tsx:259
+#: src/view/com/util/error/ErrorMessage.tsx:55
+#: src/view/com/util/error/ErrorScreen.tsx:65
+msgid "Retry"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:166
+msgid "Retry change handle"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:114
+#: src/view/com/modals/BirthDateSettings.tsx:90
+#: src/view/com/modals/BirthDateSettings.tsx:93
+#: src/view/com/modals/ChangeHandle.tsx:179
+#: src/view/com/modals/CreateOrEditList.tsx:240
+#: src/view/com/modals/CreateOrEditList.tsx:248
+#: src/view/com/modals/EditProfile.tsx:225
+msgid "Save"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:105
+msgid "Save alt text"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:210
+msgid "Save changes"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:233
+msgid "Save Changes"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:176
+msgid "Save handle change"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:144
+msgid "Save image crop"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:89
+#: src/view/com/search/HeaderWithInput.tsx:101
+#: src/view/com/util/forms/SearchInput.tsx:64
+#: src/view/shell/bottom-bar/BottomBar.tsx:132
+#: src/view/shell/desktop/Search.tsx:81
+#: src/view/shell/Drawer.tsx:218
+msgid "Search"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:110
+msgid "Security Step Required"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:30
+msgid "See what's next"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:75
+msgid "Select Bluesky Social"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:115
+msgid "Select from an existing account"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:141
+msgid "Select service"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:191
+msgid "Send Confirmation Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:119
+msgid "Send email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:130
+msgid "Send Email"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:349
+#: src/view/shell/Drawer.tsx:370
+msgid "Send feedback"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:45
+msgid "Send Report"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:80
+msgid "Set new password"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:172
+msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:101
+msgid "Set this setting to \"No\" to hide all replies from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:155
+msgid "Set this setting to \"No\" to hide all reposts from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:96
+msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:191
+msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:338
+msgid "Settings"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:126
+msgid "Sexual activity or erotic nudity."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:235
+msgid "Show"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:114
+msgid "Show anyway"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:188
+msgid "Show Posts from My Feeds"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:169
+msgid "Show Quote Posts"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:98
+msgid "Show Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:76
+msgid "Show replies by people you follow before all other replies."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:152
+msgid "Show Reposts"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:337
+msgid "Show users"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:95
+#: src/view/com/auth/SplashScreen.tsx:50
+msgid "Sign in"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:53
+#: src/view/com/auth/SplashScreen.web.tsx:59
+msgid "Sign In"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:65
+msgid "Sign in as {0}"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:56
+#: src/view/com/auth/login/Login.tsx:114
+msgid "Sign in as..."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:128
+msgid "Sign into"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:71
+#: src/view/com/modals/SwitchAccount.tsx:74
+#: src/view/screens/Settings.tsx:274
+#: src/view/screens/Settings.tsx:277
+msgid "Sign out"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:245
+msgid "Signed in as"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:37
+msgid "Skip"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:51
+msgid "Sort Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:54
+msgid "Sort replies to the same post by:"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:122
+msgid "Square"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:106
+#: src/view/com/modals/ServerInput.tsx:62
+msgid "Staging"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:624
+msgid "Status page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:582
+msgid "Storybook"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:533
+msgid "Subscribe"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:529
+msgid "Subscribe to this list"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:47
+msgid "Switch Account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:562
+msgid "System log"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:112
+msgid "Tall"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:50
+msgid "Text input field"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:312
+msgid "The post may have been deleted."
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:71
+msgid "This {screenDescription} has been flagged:"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:58
+msgid "This information is not shared with other users."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:107
+msgid "This is important in case you ever need to change your email or reset your password."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:71
+msgid "This is the service that keeps you online."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:63
+msgid "This link is taking you to the following website:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:176
+msgid "This post has been deleted."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:441
+msgid "Thread Preferences"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:93
+msgid "Threaded Mode"
+msgstr ""
+
+#: src/view/com/util/forms/DropdownButton.tsx:230
+msgid "Toggle dropdown"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:271
+msgid "Transformations"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:654
+msgid "Translate"
+msgstr ""
+
+#: src/view/com/util/error/ErrorScreen.tsx:73
+msgid "Try again"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:74
+#: src/view/com/auth/login/LoginForm.tsx:113
+msgid "Unable to contact your service. Please check your Internet connection."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:386
+#: src/view/com/profile/ProfileHeader.tsx:389
+msgid "Unblock"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:185
+msgid "Update {displayName} in Lists"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:174
+msgid "Updating..."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:456
+msgid "Upload a text file to:"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:148
+msgid "Use app passwords to login to other Bluesky clients without giving full access to your account or password."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:516
+msgid "Use default provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:37
+msgid "User handle"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:168
+#: src/view/com/auth/login/LoginForm.tsx:185
+msgid "Username or email address"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:694
+msgid "Users"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:650
+msgid "Verify email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:675
+msgid "Verify my email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:684
+msgid "Verify My Email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:205
+#: src/view/com/modals/ChangeEmail.tsx:207
+msgid "Verify New Email"
+msgstr ""
+
+#: src/view/screens/Log.tsx:53
+msgid "View debug entry"
+msgstr ""
+
+#: src/view/com/profile/ProfileSubpageHeader.tsx:127
+msgid "View the avatar"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:80
+msgid "Visit Site"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:78
+msgid "We're so excited to have you join us!"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:168
+msgid "What is the issue with this {collectionName}?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:72
+msgid "Which languages are used in this post?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:71
+msgid "Which languages would you like to see in your algorithmic feeds?"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:102
+msgid "Wide"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:390
+msgid "Write post"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:31
+msgid "Write your reply"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:122
+msgid "You can change hosting providers at any time."
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:31
+msgid "You can now sign in with your new password."
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:346
+msgid "You have blocked the author or you have been blocked by the author."
+msgstr ""
+
+#: src/view/com/lists/ListsList.tsx:112
+msgid "You have no lists."
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:55
+msgid "You have not created any app passwords yet. You can create one by pressing the button below."
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:83
+msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:42
+msgid "Your account"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:121
+msgid "Your birth date"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:107
+msgid "Your email has been saved! We'll be in touch soon."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:125
+msgid "Your email has been updated but not verified. As a next step, please verify your new email."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:102
+msgid "Your email has not yet been verified. This is an important security step which we recommend."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:41
+#: src/view/com/modals/ChangeHandle.tsx:275
+msgid "Your full handle will be"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:69
+msgid "Your hosting provider"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:63
+msgid "Your posts, likes, and blocks are public. Mutes are private."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:27
+msgid "Your user handle"
+msgstr ""
diff --git a/src/locale/locales/es/messages.js b/src/locale/locales/es/messages.js
new file mode 100644
index 000000000..8d85ab77c
--- /dev/null
+++ b/src/locale/locales/es/messages.js
@@ -0,0 +1 @@
+/*eslint-disable*/module.exports={messages:JSON.parse("{\"PBodTo\":\"- end of feed -\",\"EtUMsZ\":\". This warning is only available for posts with media attached.\",\"J/hVSQ\":[[\"0\"]],\"hZQerY\":[[\"0\"],\" \",[\"purposeLabel\"],\" List\"],\"6RmyWt\":\"<0>Here is your app password.</0> Use this to sign into the other app along with your handle.\",\"AnNF5e\":\"Accessibility\",\"AeXO77\":\"Account\",\"4WY4MD\":\"Account options\",\"m16xKo\":\"Add\",\"fBBX+K\":\"Add a content warning\",\"JU3hs2\":\"Add a user to this list\",\"MPPZ54\":\"Add account\",\"LkA8jz\":\"Add alt text\",\"Z8idyM\":\"Add details\",\"AoXl11\":\"Add details to report\",\"iE6B/9\":\"Add link card\",\"EXHdP1\":\"Add link card:\",\"x6laaL\":\"Add the following DNS record to your domain:\",\"jRrQFe\":\"Adjust the number of likes a reply must have to be shown in your feed.\",\"qLa52r\":\"Adult Content\",\"sxkWRg\":\"Advanced\",\"u2HO/d\":\"ALT\",\"u/DP73\":\"Alt text\",\"0QlT7/\":\"Alt text describes images for blind and low-vision users, and helps give context to everyone.\",\"woXbjq\":[\"An email has been sent to \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"Fon2dK\":[\"An email has been sent to your previous address, \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"HZFm5R\":\"and\",\"SMmUnj\":\"App passwords\",\"aAIQg2\":\"Appearance\",\"EbvWd3\":\"Artistic or non-erotic nudity.\",\"iH8pgl\":\"Back\",\"ehOkF+\":\"Basics\",\"+gCI2a\":\"Birthday\",\"pieVBA\":\"Birthday:\",\"HFCE4A\":\"Blocked post.\",\"7A9u1j\":\"Bluesky\",\"ZHmKSm\":\"Bluesky is flexible.\",\"odLrdl\":\"Bluesky is open.\",\"/LsWK4\":\"Bluesky is public.\",\"C50OGr\":\"Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon.\",\"klVoaP\":\"Bluesky.Social\",\"qxBitM\":[\"Build version \",[\"0\"],\" \",[\"1\"]],\"rT2cV+\":\"Camera\",\"JGGrPC\":\"Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long.\",\"dEgA5A\":\"Cancel\",\"aMH9rr\":\"Cancel account deletion\",\"kc3E4R\":\"Cancel add image alt text\",\"wg4LHQ\":\"Cancel change handle\",\"hFL1Li\":\"Cancel image crop\",\"tijH8t\":\"Cancel profile editing\",\"Qe4C/d\":\"Cancel quote post\",\"5TviPn\":\"Cancel search\",\"nss3UV\":\"Cancel waitlist signup\",\"o+XJ9D\":\"Change\",\"pQco5R\":\"Change handle\",\"Q5e1U/\":\"Change Handle\",\"a3NAfL\":\"Change my email\",\"4vatyk\":\"Change Your Email\",\"/+X+/K\":\"Check your inbox for an email with the confirmation code to enter below:\",\"Rt502e\":\"Choose Service\",\"/L45sc\":\"Choose the algorithms that power your experience with custom feeds.\",\"Wk8hkn\":\"Choose your password\",\"QbvBNV\":\"Clear search query\",\"flH7u/\":\"Close alert\",\"hYmnbk\":\"Close bottom drawer\",\"47L1V1\":\"Close image\",\"l49ujN\":\"Close image viewer\",\"UryHFO\":\"Close navigation footer\",\"o8UUti\":\"Compose reply\",\"7VpPHA\":\"Confirm\",\"q8upsf\":\"Confirm Change\",\"8pNKIr\":\"Confirm content language settings\",\"tGg8Kt\":\"Confirm delete account\",\"ioZOzk\":\"Confirmation code\",\"J28zul\":\"Connecting...\",\"m8j6up\":\"Content Filtering\",\"/PlAsF\":\"Content Languages\",\"cogwXi\":\"Content Warning\",\"FG7AQv\":\"Content warnings\",\"6V3Ea3\":\"Copied\",\"he3ygx\":\"Copy\",\"7wWvgo\":\"Could not load feed\",\"8NNr/O\":\"Could not load list\",\"mpt9T+\":\"Create a new account\",\"IS0nrP\":\"Create Account\",\"6HbhpU\":\"Create new account\",\"GAD3Dx\":\"Custom domain\",\"ZQKLI1\":\"Danger Zone\",\"ZDGm40\":\"Delete account\",\"vzX5FB\":\"Delete Account\",\"gUEtxf\":\"Delete app password\",\"ktknoE\":\"Delete my account\",\"szz0+N\":\"Delete my account…\",\"u+1OHY\":\"Deleted post.\",\"Nu4oKW\":\"Description\",\"dacKHE\":\"Dev Server\",\"2ygkE8\":\"Developer Tools\",\"pbLwal\":\"Discover new feeds\",\"pfa8F0\":\"Display name\",\"0gS7M5\":\"Display Name\",\"iZ5pMB\":\"Domain verified!\",\"DPfwMq\":\"Done\",\"zT97vP\":[\"Done\",[\"extraText\"]],\"XQFMOm\":\"Edit image\",\"cLmurE\":\"Edit My Feeds\",\"bRZ5XW\":\"Edit my profile\",\"9OpVZg\":\"Edit profile\",\"QJQd1J\":\"Edit Profile\",\"Jn7kox\":\"Edit Saved Feeds\",\"O3oNi5\":\"Email\",\"ATGYL1\":\"Email address\",\"pJJ0Vp\":\"Email Updated\",\"96mted\":\"Enable this setting to only see replies between people you follow.\",\"YbIxza\":\"Enter the address of your provider:\",\"BfIgP6\":\"Enter the domain you want to use\",\"xRPn3U\":\"Enter your email address\",\"+inPGm\":\"Enter your new email address below.\",\"T0KLp4\":\"Enter your username and password\",\"0PkE20\":\"Expand alt text\",\"4yCy8i\":\"Feed offline\",\"N0CqyO\":\"Feed Preferences\",\"YirHq7\":\"Feedback\",\"2DoBvq\":\"Feeds\",\"Qzj1WT\":\"Finding similar accounts...\",\"QKSrQV\":\"Fine-tune the content you see on your home screen.\",\"r+KeyR\":\"Fine-tune the discussion threads.\",\"MKEPCY\":\"Follow\",\"NIjL2Y\":\"following\",\"y6sq5j\":\"Following\",\"p3UO/y\":\"Follows you\",\"5RhDkD\":\"For security reasons, we'll need to send a confirmation code to your email address.\",\"NJPhAO\":\"For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one.\",\"5bDfuq\":\"Forgot\",\"hEPLrs\":\"Forgot password\",\"dn8X5t\":\"Forgot Password\",\"U+kFad\":\"Gallery\",\"c3b0B0\":\"Get Started\",\"CKyk7Q\":\"Go back\",\"sr0UJD\":\"Go Back\",\"Rtp0y7\":\"Go to next\",\"Nf7oXL\":\"Handle\",\"c3XJ18\":\"Help\",\"vLyv1R\":\"Hide\",\"qdOx2q\":\"Hide user list\",\"i0qMbr\":\"Home\",\"sXZ8IU\":\"Home Feed Preferences\",\"yt7fhu\":\"Hosting provider\",\"s2xA6t\":\"Hosting provider address\",\"o+axy6\":\"I have a code\",\"wey2os\":\"I have my own domain\",\"WlEcKr\":\"If none are selected, suitable for all ages.\",\"VCk0rR\":\"Image alt text\",\"STGpNQ\":\"Image options\",\"dSKHAa\":\"Invalid username or password\",\"MFKlMB\":\"Invite\",\"F5MZVk\":\"Invite a Friend\",\"6KlkHI\":\"Invite code\",\"F75w8j\":\"Join the waitlist\",\"6iVTdm\":\"Join the waitlist.\",\"SNzppu\":\"Join Waitlist\",\"Dcq5kL\":\"Language selection\",\"GAmD3h\":\"Languages\",\"NgeSlx\":\"Learn More\",\"rj0Lke\":\"Learn more about this warning\",\"kq2ga7\":\"Leave them all unchecked to see any language.\",\"QfDITI\":\"Leaving Bluesky\",\"Esfg1M\":\"Let's get your password reset!\",\"BvSY1i\":\"Like this feed\",\"FuZWua\":\"List Avatar\",\"8mjA4F\":\"List Name\",\"h16FyT\":\"Lists\",\"ujW4FW\":\"Load more posts\",\"VkLESX\":\"Load new posts\",\"jl0AFf\":\"Local dev server\",\"cR9UpQ\":\"Login to account that is not listed\",\"2U/gDT\":\"Make sure this is where you intend to go!\",\"zucql+\":\"Menu\",\"DzmsLV\":\"Moderation\",\"3Siwmw\":\"More options\",\"Y17r45\":\"More post options\",\"Mysqyf\":\"My Birthday\",\"6MBNS/\":\"My Feeds\",\"Ha6iBv\":\"My Saved Feeds\",\"6YtxFj\":\"Name\",\"8yolS6\":\"Never lose access to your followers and data.\",\"2B7HLH\":\"New post\",\"FGrimz\":\"New Post\",\"hXzOVo\":\"Next\",\"EatZYJ\":\"Next image\",\"flmDTf\":\"No description\",\"fOlAiK\":[\"No results found for \\\"\",[\"query\"],\"\\\"\"],\"kA9DpB\":[\"No results found for \",[\"0\"]],\"ispbnl\":\"Not Applicable\",\"iDNBZe\":\"Notifications\",\"UaXeX3\":\"Okay\",\"Cqo2D+\":\"One or more images is missing alt text.\",\"M/Q2aG\":\"Open navigation\",\"M5PuNq\":\"Opens configurable language settings\",\"eSqpax\":\"Opens modal for using custom domain\",\"vYwHHI\":\"Opens moderation settings\",\"0tHyB7\":\"Opens screen with all saved feeds\",\"nmRoY/\":\"Opens the app password settings page\",\"6e9Apv\":\"Opens the home feed preferences\",\"O87Dr/\":\"Opens the storybook page\",\"G+PVmg\":\"Opens the system log page\",\"Jqb7sy\":\"Opens the threads preferences\",\"b22AVl\":\"Other account\",\"n+HLOP\":\"Other service\",\"1PKxQ7\":\"Other...\",\"8ZsakT\":\"Password\",\"DKeVgZ\":\"Password updated!\",\"VeZE5Q\":\"Pictures meant for adults.\",\"Apyknf\":\"Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.\",\"9qpQ5O\":\"Please enter a unique name for this App Password or use our randomly generated one.\",\"QJr5Xp\":\"Please enter your password as well:\",\"y28hnO\":\"Post\",\"h5RcXU\":\"Post hidden\",\"r5zLS0\":\"Post language\",\"AzCucI\":\"Post Languages\",\"tJFPmV\":\"Post not found\",\"0+DQbr\":\"Potentially Misleading Link\",\"MHk+7g\":\"Previous image\",\"x8iR7V\":\"Prioritize Your Follows\",\"vERlcd\":\"Profile\",\"MrgqOW\":\"Protect your account by verifying your email.\",\"8HFFRQ\":\"Quote post\",\"+KrAHa\":\"Quote Post\",\"WlWsdE\":\"Ratios\",\"t/YqKh\":\"Remove\",\"5ywtDz\":\"Remove image\",\"Dw/XUh\":\"Remove image preview\",\"Veu9gK\":\"Reply Filters\",\"lQWbAr\":[\"Report \",[\"collectionName\"]],\"6IcSvC\":\"Report post\",\"JOV5dR\":\"Repost or quote post\",\"bqG37Z\":\"Request Change\",\"8XIT+P\":\"Required for this provider\",\"vJgYMA\":\"Reset code\",\"xEL92I\":\"Reset onboarding state\",\"bee/Fw\":\"Reset preferences state\",\"wToeoz\":\"Resets the onboarding state\",\"nIU7qI\":\"Resets the preferences state\",\"6gRgw8\":\"Retry\",\"hAbYQa\":\"Retry change handle\",\"tfDRzk\":\"Save\",\"KV2YQQ\":\"Save alt text\",\"y3aU20\":\"Save changes\",\"IUwGEM\":\"Save Changes\",\"Xs07Tg\":\"Save handle change\",\"BckA7m\":\"Save image crop\",\"A1taO8\":\"Search\",\"CKROFy\":\"Security Step Required\",\"cNzyJW\":\"See what's next\",\"L5sM7N\":\"Select Bluesky Social\",\"o3dwub\":\"Select from an existing account\",\"GGw2AK\":\"Select service\",\"vp9yIB\":\"Send Confirmation Email\",\"65dxv8\":\"Send email\",\"i/TzEU\":\"Send Email\",\"RoafuO\":\"Send feedback\",\"4cijjm\":\"Send Report\",\"V/e7nf\":\"Set new password\",\"gwsie4\":\"Set this setting to \\\"No\\\" to hide all quote posts from your feed. Reposts will still be visible.\",\"IZjC3J\":\"Set this setting to \\\"No\\\" to hide all replies from your feed.\",\"KIgU3l\":\"Set this setting to \\\"No\\\" to hide all reposts from your feed.\",\"zaAyrz\":\"Set this setting to \\\"Yes\\\" to show replies in a threaded view. This is an experimental feature.\",\"fQV2eE\":\"Set this setting to \\\"Yes\\\" to show samples of your saved feeds in your following feed. This is an experimental feature.\",\"Tz0i8g\":\"Settings\",\"HfWHhJ\":\"Sexual activity or erotic nudity.\",\"8vETh9\":\"Show\",\"aWAdCb\":\"Show anyway\",\"NijgXr\":\"Show Posts from My Feeds\",\"T3Mt8m\":\"Show Quote Posts\",\"BlW8X/\":\"Show Replies\",\"X4GwDb\":\"Show replies by people you follow before all other replies.\",\"GiogzH\":\"Show Reposts\",\"fhY/fL\":\"Show users\",\"5lWFkC\":\"Sign in\",\"n1ekoW\":\"Sign In\",\"N9o7n5\":[\"Sign in as \",[\"0\"]],\"FT1MVS\":\"Sign in as...\",\"+UpfFC\":\"Sign into\",\"fcWrnU\":\"Sign out\",\"zU+Ro7\":\"Signed in as\",\"6Uau97\":\"Skip\",\"0o5BFH\":\"Sort Replies\",\"GH1Rgk\":\"Sort replies to the same post by:\",\"1DA6ap\":\"Square\",\"aKEHLj\":\"Staging\",\"tgEXwM\":\"Status page\",\"P5jja7\":\"Storybook\",\"EDl9kS\":\"Subscribe\",\"5z3ICN\":\"Subscribe to this list\",\"VjWeLI\":\"Switch Account\",\"fP8jTZ\":\"System log\",\"HF6Iah\":\"Tall\",\"p8Iz39\":\"Text input field\",\"G4EksE\":\"The post may have been deleted.\",\"KRYn8w\":[\"This \",[\"screenDescription\"],\" has been flagged:\"],\"lm845B\":\"This information is not shared with other users.\",\"5Pvw/O\":\"This is important in case you ever need to change your email or reset your password.\",\"sQQfZ9\":\"This is the service that keeps you online.\",\"CvX8qs\":\"This link is taking you to the following website:\",\"WKrUVy\":\"This post has been deleted.\",\"u9ThjD\":\"Thread Preferences\",\"zmXsk5\":\"Threaded Mode\",\"1x30Qt\":\"Toggle dropdown\",\"KFXQEt\":\"Transformations\",\"pi8x/S\":\"Translate\",\"KDw4GX\":\"Try again\",\"nc4Wfd\":\"Unable to contact your service. Please check your Internet connection.\",\"tuS5Jz\":\"Unblock\",\"vaz2uI\":[\"Update \",[\"displayName\"],\" in Lists\"],\"RXbEvi\":\"Updating...\",\"Vwkfp4\":\"Upload a text file to:\",\"jTdnU6\":\"Use app passwords to login to other Bluesky clients without giving full access to your account or password.\",\"CH1am9\":\"Use default provider\",\"t4Yp4Z\":\"User handle\",\"nZx9mr\":\"Username or email address\",\"Sxm8rQ\":\"Users\",\"MBOY4U\":\"Verify email\",\"Ejyv0o\":\"Verify my email\",\"9czCrB\":\"Verify My Email\",\"ibSVGR\":\"Verify New Email\",\"nHsQde\":\"View debug entry\",\"47jzzd\":\"View the avatar\",\"wK4H1r\":\"Visit Site\",\"qjBGxf\":\"We're so excited to have you join us!\",\"Mj7rl/\":[\"What is the issue with this \",[\"collectionName\"],\"?\"],\"3qn29J\":\"Which languages are used in this post?\",\"uawiGa\":\"Which languages would you like to see in your algorithmic feeds?\",\"I5S9ZE\":\"Wide\",\"y02THm\":\"Write post\",\"6ckZRB\":\"Write your reply\",\"STPj0e\":\"You can change hosting providers at any time.\",\"67nRLM\":\"You can now sign in with your new password.\",\"RkXibf\":\"You have blocked the author or you have been blocked by the author.\",\"tCLJ9E\":\"You have no lists.\",\"NDgp3i\":\"You have not created any app passwords yet. You can create one by pressing the button below.\",\"RrDyEb\":\"You will receive an email with a \\\"reset code.\\\" Enter that code here, then enter your new password.\",\"gdRnT7\":\"Your account\",\"k7hmsH\":\"Your birth date\",\"OubkcP\":\"Your email has been saved! We'll be in touch soon.\",\"z2L+/9\":\"Your email has been updated but not verified. As a next step, please verify your new email.\",\"XZlIVw\":\"Your email has not yet been verified. This is an important security step which we recommend.\",\"qv9f4I\":\"Your full handle will be\",\"lvcqqG\":\"Your hosting provider\",\"Oqt/PG\":\"Your posts, likes, and blocks are public. Mutes are private.\",\"MvWO9d\":\"Your user handle\"}")};
\ No newline at end of file
diff --git a/src/locale/locales/es/messages.po b/src/locale/locales/es/messages.po
new file mode 100644
index 000000000..daeb14912
--- /dev/null
+++ b/src/locale/locales/es/messages.po
@@ -0,0 +1,1544 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2023-11-06 12:28-0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: es\n"
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+#: src/view/screens/Profile.tsx:212
+msgid "- end of feed -"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:138
+msgid ". This warning is only available for posts with media attached."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:45
+msgid "{0}"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:167
+msgid "{0} {purposeLabel} List"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:132
+msgid "<0>Here is your app password.</0> Use this to sign into the other app along with your handle."
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:299
+#: src/view/screens/Settings.tsx:363
+msgid "Accessibility"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:157
+#: src/view/screens/Settings.tsx:201
+msgid "Account"
+msgstr ""
+
+#: src/view/com/util/AccountDropdownBtn.tsx:41
+msgid "Account options"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:710
+msgid "Add"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:57
+msgid "Add a content warning"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:700
+msgid "Add a user to this list"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:313
+#: src/view/screens/Settings.tsx:322
+msgid "Add account"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:119
+#: src/view/com/composer/photos/Gallery.tsx:167
+msgid "Add alt text"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:41
+#: src/view/com/modals/report/Modal.tsx:190
+msgid "Add details"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:193
+msgid "Add details to report"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:419
+msgid "Add link card"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:422
+msgid "Add link card:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:418
+msgid "Add the following DNS record to your domain:"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:140
+msgid "Adjust the number of likes a reply must have to be shown in your feed."
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:76
+msgid "Adult Content"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:493
+msgid "Advanced"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:127
+msgid "ALT"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:315
+msgid "Alt text"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:193
+msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:112
+msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:119
+msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:238
+msgid "and"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:509
+msgid "App passwords"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:378
+msgid "Appearance"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:124
+msgid "Artistic or non-erotic nudity."
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:92
+#: src/view/com/auth/login/ChooseAccountForm.tsx:111
+#: src/view/com/auth/login/LoginForm.tsx:247
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:150
+#: src/view/com/modals/report/InputIssueDetails.tsx:45
+#: src/view/com/post-thread/PostThread.tsx:317
+#: src/view/com/post-thread/PostThread.tsx:325
+#: src/view/com/post-thread/PostThread.tsx:354
+#: src/view/com/post-thread/PostThread.tsx:362
+#: src/view/com/profile/ProfileHeader.tsx:576
+msgid "Back"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:407
+msgid "Basics"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:130
+#: src/view/com/modals/BirthDateSettings.tsx:69
+msgid "Birthday"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:228
+msgid "Birthday:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:211
+msgid "Blocked post."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:52
+#: src/view/com/auth/SplashScreen.tsx:27
+msgid "Bluesky"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:84
+msgid "Bluesky is flexible."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:73
+msgid "Bluesky is open."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:60
+msgid "Bluesky is public."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:70
+msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon."
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:78
+msgid "Bluesky.Social"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:612
+msgid "Build version {0} {1}"
+msgstr ""
+
+#: src/view/com/composer/photos/OpenCameraBtn.tsx:62
+msgid "Camera"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:199
+msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:271
+#: src/view/com/composer/Composer.tsx:274
+#: src/view/com/modals/AltImage.tsx:127
+#: src/view/com/modals/ChangeEmail.tsx:216
+#: src/view/com/modals/ChangeEmail.tsx:218
+#: src/view/com/modals/Confirm.tsx:89
+#: src/view/com/modals/CreateOrEditList.tsx:258
+#: src/view/com/modals/CreateOrEditList.tsx:263
+#: src/view/com/modals/DeleteAccount.tsx:142
+#: src/view/com/modals/DeleteAccount.tsx:215
+#: src/view/com/modals/EditImage.tsx:323
+#: src/view/com/modals/EditProfile.tsx:250
+#: src/view/com/modals/LinkWarning.tsx:90
+#: src/view/com/modals/Repost.tsx:74
+#: src/view/com/modals/UserAddRemoveLists.tsx:199
+#: src/view/com/modals/Waitlist.tsx:136
+#: src/view/com/search/HeaderWithInput.tsx:127
+#: src/view/shell/desktop/Search.tsx:93
+msgid "Cancel"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:138
+#: src/view/com/modals/DeleteAccount.tsx:211
+msgid "Cancel account deletion"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:122
+msgid "Cancel add image alt text"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:144
+msgid "Cancel change handle"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:134
+msgid "Cancel image crop"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:245
+msgid "Cancel profile editing"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:65
+msgid "Cancel quote post"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:101
+#: src/view/shell/desktop/Search.tsx:89
+msgid "Cancel search"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:132
+msgid "Cancel waitlist signup"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:222
+msgid "Change"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:517
+#: src/view/screens/Settings.tsx:526
+msgid "Change handle"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:156
+msgid "Change Handle"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:136
+msgid "Change my email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:109
+msgid "Change Your Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:155
+msgid "Check your inbox for an email with the confirmation code to enter below:"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:38
+msgid "Choose Service"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:87
+msgid "Choose the algorithms that power your experience with custom feeds."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:105
+msgid "Choose your password"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:111
+#: src/view/com/util/forms/SearchInput.tsx:73
+msgid "Clear search query"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:38
+msgid "Close alert"
+msgstr ""
+
+#: src/view/com/util/BottomSheetCustomBackdrop.tsx:33
+msgid "Close bottom drawer"
+msgstr ""
+
+#: src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx:26
+msgid "Close image"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:107
+msgid "Close image viewer"
+msgstr ""
+
+#: src/view/shell/index.web.tsx:65
+msgid "Close navigation footer"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:22
+msgid "Compose reply"
+msgstr ""
+
+#: src/view/com/modals/Confirm.tsx:76
+#: src/view/com/modals/SelfLabel.tsx:156
+#: src/view/com/modals/VerifyEmail.tsx:220
+#: src/view/screens/PreferencesHomeFeed.tsx:223
+#: src/view/screens/PreferencesThreads.tsx:128
+msgid "Confirm"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:193
+#: src/view/com/modals/ChangeEmail.tsx:195
+msgid "Confirm Change"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34
+msgid "Confirm content language settings"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:201
+msgid "Confirm delete account"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:157
+#: src/view/com/modals/DeleteAccount.tsx:168
+#: src/view/com/modals/VerifyEmail.tsx:154
+msgid "Confirmation code"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:125
+#: src/view/com/auth/login/LoginForm.tsx:266
+msgid "Connecting..."
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:42
+msgid "Content Filtering"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:68
+msgid "Content Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:68
+msgid "Content Warning"
+msgstr ""
+
+#: src/view/com/composer/labels/LabelsBtn.tsx:32
+msgid "Content warnings"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:178
+#: src/view/com/modals/InviteCodes.tsx:129
+msgid "Copied"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:171
+msgid "Copy"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:97
+msgid "Could not load feed"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:788
+msgid "Could not load list"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:42
+msgid "Create a new account"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:77
+msgid "Create Account"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:39
+msgid "Create new account"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:390
+#: src/view/com/modals/ServerInput.tsx:102
+msgid "Custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:531
+msgid "Danger Zone"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:538
+msgid "Delete account"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:75
+msgid "Delete Account"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:193
+msgid "Delete app password"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:204
+msgid "Delete my account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:548
+msgid "Delete my account…"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:203
+msgid "Deleted post."
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:209
+#: src/view/com/modals/CreateOrEditList.tsx:225
+#: src/view/com/modals/EditProfile.tsx:199
+#: src/view/com/modals/EditProfile.tsx:211
+msgid "Description"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:112
+msgid "Dev Server"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:553
+msgid "Developer Tools"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:165
+msgid "Discover new feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:193
+msgid "Display name"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:181
+msgid "Display Name"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:488
+msgid "Domain verified!"
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:77
+#: src/view/com/modals/ContentFilteringSettings.tsx:85
+#: src/view/com/modals/crop-image/CropImage.web.tsx:152
+#: src/view/com/modals/EditImage.tsx:333
+#: src/view/com/modals/ListAddUser.tsx:153
+#: src/view/com/modals/SelfLabel.tsx:159
+#: src/view/screens/PreferencesHomeFeed.tsx:226
+#: src/view/screens/PreferencesThreads.tsx:131
+msgid "Done"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:42
+msgid "Done{extraText}"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:141
+#: src/view/com/modals/EditImage.tsx:207
+msgid "Edit image"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:132
+msgid "Edit My Feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:158
+msgid "Edit my profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:373
+msgid "Edit profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:376
+msgid "Edit Profile"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:92
+msgid "Edit Saved Feeds"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:89
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:145
+#: src/view/com/modals/ChangeEmail.tsx:141
+#: src/view/com/modals/Waitlist.tsx:88
+msgid "Email"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:80
+msgid "Email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:111
+msgid "Email Updated"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:123
+msgid "Enable this setting to only see replies between people you follow."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:87
+msgid "Enter the address of your provider:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:372
+msgid "Enter the domain you want to use"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:85
+msgid "Enter your email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:117
+msgid "Enter your new email address below."
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:96
+msgid "Enter your username and password"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:151
+msgid "Expand alt text"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:301
+msgid "Feed offline"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:163
+msgid "Feed Preferences"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:365
+msgid "Feedback"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:154
+#: src/view/shell/Drawer.tsx:289
+msgid "Feeds"
+msgstr ""
+
+#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:119
+msgid "Finding similar accounts..."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:90
+msgid "Fine-tune the content you see on your home screen."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:43
+msgid "Fine-tune the discussion threads."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:459
+msgid "Follow"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:537
+msgid "following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:443
+msgid "Following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:492
+msgid "Follows you"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:99
+msgid "For security reasons, we'll need to send a confirmation code to your email address."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:192
+msgid "For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:229
+msgid "Forgot"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:226
+msgid "Forgot password"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:126
+#: src/view/com/auth/login/Login.tsx:143
+msgid "Forgot Password"
+msgstr ""
+
+#: src/view/com/composer/photos/SelectPhotoBtn.tsx:43
+msgid "Gallery"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:178
+msgid "Get Started"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:105
+#: src/view/shell/desktop/LeftNav.tsx:92
+msgid "Go back"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:106
+#: src/view/screens/ProfileFeed.tsx:111
+#: src/view/screens/ProfileList.tsx:797
+#: src/view/screens/ProfileList.tsx:802
+msgid "Go Back"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:178
+#: src/view/com/auth/login/LoginForm.tsx:276
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:165
+msgid "Go to next"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:270
+msgid "Handle"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:375
+msgid "Help"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:316
+msgid "Hide"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:308
+msgid "Hide user list"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:110
+#: src/view/shell/Drawer.tsx:240
+msgid "Home"
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:69
+#: src/view/screens/Settings.tsx:423
+msgid "Home Feed Preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:111
+msgid "Hosting provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:92
+#: src/view/com/auth/create/Step1.tsx:97
+msgid "Hosting provider address"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:203
+msgid "I have a code"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:286
+msgid "I have my own domain"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:128
+msgid "If none are selected, suitable for all ages."
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:96
+msgid "Image alt text"
+msgstr ""
+
+#: src/view/com/util/UserAvatar.tsx:300
+#: src/view/com/util/UserBanner.tsx:118
+msgid "Image options"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:109
+msgid "Invalid username or password"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:336
+msgid "Invite"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:329
+msgid "Invite a Friend"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:56
+msgid "Invite code"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:67
+msgid "Join the waitlist"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:67
+#: src/view/com/auth/create/Step2.tsx:71
+msgid "Join the waitlist."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:124
+msgid "Join Waitlist"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:97
+msgid "Language selection"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:471
+msgid "Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/PostAlerts.tsx:47
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:55
+#: src/view/com/util/moderation/ScreenHider.tsx:88
+msgid "Learn More"
+msgstr ""
+
+#: src/view/com/util/moderation/ContentHider.tsx:75
+#: src/view/com/util/moderation/PostAlerts.tsx:40
+#: src/view/com/util/moderation/PostHider.tsx:76
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:47
+#: src/view/com/util/moderation/ScreenHider.tsx:85
+msgid "Learn more about this warning"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:76
+msgid "Leave them all unchecked to see any language."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:56
+msgid "Leaving Bluesky"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:127
+#: src/view/com/auth/login/Login.tsx:144
+msgid "Let's get your password reset!"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:479
+msgid "Like this feed"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:177
+msgid "List Avatar"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:190
+msgid "List Name"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:297
+msgid "Lists"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:220
+#: src/view/com/post-thread/PostThread.tsx:228
+msgid "Load more posts"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:194
+msgid "Load new posts"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:50
+msgid "Local dev server"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:93
+msgid "Login to account that is not listed"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:70
+msgid "Make sure this is where you intend to go!"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:71
+msgid "Menu"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:487
+#: src/view/shell/Drawer.tsx:304
+msgid "Moderation"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:469
+#: src/view/screens/ProfileFeed.tsx:312
+#: src/view/screens/ProfileList.tsx:542
+msgid "More options"
+msgstr ""
+
+#: src/view/com/util/forms/PostDropdownBtn.tsx:158
+msgid "More post options"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:53
+msgid "My Birthday"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:128
+msgid "My Feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:454
+msgid "My Saved Feeds"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:162
+#: src/view/com/modals/CreateOrEditList.tsx:202
+msgid "Name"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:76
+msgid "Never lose access to your followers and data."
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:203
+#: src/view/screens/Feeds.tsx:261
+#: src/view/screens/Profile.tsx:304
+#: src/view/screens/ProfileFeed.tsx:378
+#: src/view/screens/ProfileList.tsx:210
+#: src/view/screens/ProfileList.tsx:248
+#: src/view/shell/desktop/LeftNav.tsx:229
+msgid "New post"
+msgstr ""
+
+#: src/view/shell/desktop/LeftNav.tsx:239
+msgid "New Post"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:105
+#: src/view/com/auth/login/LoginForm.tsx:279
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:158
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:168
+msgid "Next"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:137
+msgid "Next image"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:472
+#: src/view/screens/ProfileList.tsx:667
+msgid "No description"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:207
+msgid "No results found for \"{query}\""
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:140
+#: src/view/shell/desktop/Search.tsx:112
+msgid "No results found for {0}"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:136
+msgid "Not Applicable"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:178
+#: src/view/shell/Drawer.tsx:262
+msgid "Notifications"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:41
+msgid "Okay"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:334
+msgid "One or more images is missing alt text."
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:50
+msgid "Open navigation"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:463
+msgid "Opens configurable language settings"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:284
+msgid "Opens modal for using custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:482
+msgid "Opens moderation settings"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:448
+msgid "Opens screen with all saved feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:501
+msgid "Opens the app password settings page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:415
+msgid "Opens the home feed preferences"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:580
+msgid "Opens the storybook page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:560
+msgid "Opens the system log page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:432
+msgid "Opens the threads preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:98
+msgid "Other account"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:88
+msgid "Other service"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:84
+msgid "Other..."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:100
+#: src/view/com/auth/create/Step2.tsx:110
+#: src/view/com/auth/login/LoginForm.tsx:214
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:132
+#: src/view/com/modals/DeleteAccount.tsx:183
+msgid "Password"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:28
+msgid "Password updated!"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:122
+msgid "Pictures meant for adults."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:67
+msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:125
+msgid "Please enter a unique name for this App Password or use our randomly generated one."
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:172
+msgid "Please enter your password as well:"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:317
+msgid "Post"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:343
+msgid "Post hidden"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:80
+msgid "Post language"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:69
+msgid "Post Languages"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:309
+msgid "Post not found"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:51
+msgid "Potentially Misleading Link"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:123
+msgid "Previous image"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:73
+msgid "Prioritize Your Follows"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:220
+#: src/view/shell/Drawer.tsx:161
+#: src/view/shell/Drawer.tsx:325
+msgid "Profile"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:689
+msgid "Protect your account by verifying your email."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:53
+msgid "Quote post"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:57
+msgid "Quote Post"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:236
+msgid "Ratios"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:84
+msgid "Remove"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:154
+msgid "Remove image"
+msgstr ""
+
+#: src/view/com/composer/ExternalEmbed.tsx:70
+msgid "Remove image preview"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:120
+msgid "Reply Filters"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:165
+msgid "Report {collectionName}"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:37
+msgid "Report post"
+msgstr ""
+
+#: src/view/com/util/post-ctrls/RepostButton.web.tsx:69
+msgid "Repost or quote post"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:181
+#: src/view/com/modals/ChangeEmail.tsx:183
+msgid "Request Change"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:52
+msgid "Required for this provider"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:110
+msgid "Reset code"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:602
+msgid "Reset onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:592
+msgid "Reset preferences state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:600
+msgid "Resets the onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:590
+msgid "Resets the preferences state"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:114
+#: src/view/com/auth/create/CreateAccount.tsx:118
+#: src/view/com/auth/login/LoginForm.tsx:256
+#: src/view/com/auth/login/LoginForm.tsx:259
+#: src/view/com/util/error/ErrorMessage.tsx:55
+#: src/view/com/util/error/ErrorScreen.tsx:65
+msgid "Retry"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:166
+msgid "Retry change handle"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:114
+#: src/view/com/modals/BirthDateSettings.tsx:90
+#: src/view/com/modals/BirthDateSettings.tsx:93
+#: src/view/com/modals/ChangeHandle.tsx:179
+#: src/view/com/modals/CreateOrEditList.tsx:240
+#: src/view/com/modals/CreateOrEditList.tsx:248
+#: src/view/com/modals/EditProfile.tsx:225
+msgid "Save"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:105
+msgid "Save alt text"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:210
+msgid "Save changes"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:233
+msgid "Save Changes"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:176
+msgid "Save handle change"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:144
+msgid "Save image crop"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:89
+#: src/view/com/search/HeaderWithInput.tsx:101
+#: src/view/com/util/forms/SearchInput.tsx:64
+#: src/view/shell/bottom-bar/BottomBar.tsx:132
+#: src/view/shell/desktop/Search.tsx:81
+#: src/view/shell/Drawer.tsx:218
+msgid "Search"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:110
+msgid "Security Step Required"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:30
+msgid "See what's next"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:75
+msgid "Select Bluesky Social"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:115
+msgid "Select from an existing account"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:141
+msgid "Select service"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:191
+msgid "Send Confirmation Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:119
+msgid "Send email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:130
+msgid "Send Email"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:349
+#: src/view/shell/Drawer.tsx:370
+msgid "Send feedback"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:45
+msgid "Send Report"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:80
+msgid "Set new password"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:172
+msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:101
+msgid "Set this setting to \"No\" to hide all replies from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:155
+msgid "Set this setting to \"No\" to hide all reposts from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:96
+msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:191
+msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:338
+msgid "Settings"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:126
+msgid "Sexual activity or erotic nudity."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:235
+msgid "Show"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:114
+msgid "Show anyway"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:188
+msgid "Show Posts from My Feeds"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:169
+msgid "Show Quote Posts"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:98
+msgid "Show Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:76
+msgid "Show replies by people you follow before all other replies."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:152
+msgid "Show Reposts"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:337
+msgid "Show users"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:95
+#: src/view/com/auth/SplashScreen.tsx:50
+msgid "Sign in"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:53
+#: src/view/com/auth/SplashScreen.web.tsx:59
+msgid "Sign In"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:65
+msgid "Sign in as {0}"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:56
+#: src/view/com/auth/login/Login.tsx:114
+msgid "Sign in as..."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:128
+msgid "Sign into"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:71
+#: src/view/com/modals/SwitchAccount.tsx:74
+#: src/view/screens/Settings.tsx:274
+#: src/view/screens/Settings.tsx:277
+msgid "Sign out"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:245
+msgid "Signed in as"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:37
+msgid "Skip"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:51
+msgid "Sort Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:54
+msgid "Sort replies to the same post by:"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:122
+msgid "Square"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:106
+#: src/view/com/modals/ServerInput.tsx:62
+msgid "Staging"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:624
+msgid "Status page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:582
+msgid "Storybook"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:533
+msgid "Subscribe"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:529
+msgid "Subscribe to this list"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:47
+msgid "Switch Account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:562
+msgid "System log"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:112
+msgid "Tall"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:50
+msgid "Text input field"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:312
+msgid "The post may have been deleted."
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:71
+msgid "This {screenDescription} has been flagged:"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:58
+msgid "This information is not shared with other users."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:107
+msgid "This is important in case you ever need to change your email or reset your password."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:71
+msgid "This is the service that keeps you online."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:63
+msgid "This link is taking you to the following website:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:176
+msgid "This post has been deleted."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:441
+msgid "Thread Preferences"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:93
+msgid "Threaded Mode"
+msgstr ""
+
+#: src/view/com/util/forms/DropdownButton.tsx:230
+msgid "Toggle dropdown"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:271
+msgid "Transformations"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:654
+msgid "Translate"
+msgstr ""
+
+#: src/view/com/util/error/ErrorScreen.tsx:73
+msgid "Try again"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:74
+#: src/view/com/auth/login/LoginForm.tsx:113
+msgid "Unable to contact your service. Please check your Internet connection."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:386
+#: src/view/com/profile/ProfileHeader.tsx:389
+msgid "Unblock"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:185
+msgid "Update {displayName} in Lists"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:174
+msgid "Updating..."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:456
+msgid "Upload a text file to:"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:148
+msgid "Use app passwords to login to other Bluesky clients without giving full access to your account or password."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:516
+msgid "Use default provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:37
+msgid "User handle"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:168
+#: src/view/com/auth/login/LoginForm.tsx:185
+msgid "Username or email address"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:694
+msgid "Users"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:650
+msgid "Verify email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:675
+msgid "Verify my email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:684
+msgid "Verify My Email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:205
+#: src/view/com/modals/ChangeEmail.tsx:207
+msgid "Verify New Email"
+msgstr ""
+
+#: src/view/screens/Log.tsx:53
+msgid "View debug entry"
+msgstr ""
+
+#: src/view/com/profile/ProfileSubpageHeader.tsx:127
+msgid "View the avatar"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:80
+msgid "Visit Site"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:78
+msgid "We're so excited to have you join us!"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:168
+msgid "What is the issue with this {collectionName}?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:72
+msgid "Which languages are used in this post?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:71
+msgid "Which languages would you like to see in your algorithmic feeds?"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:102
+msgid "Wide"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:390
+msgid "Write post"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:31
+msgid "Write your reply"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:122
+msgid "You can change hosting providers at any time."
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:31
+msgid "You can now sign in with your new password."
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:346
+msgid "You have blocked the author or you have been blocked by the author."
+msgstr ""
+
+#: src/view/com/lists/ListsList.tsx:112
+msgid "You have no lists."
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:55
+msgid "You have not created any app passwords yet. You can create one by pressing the button below."
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:83
+msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:42
+msgid "Your account"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:121
+msgid "Your birth date"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:107
+msgid "Your email has been saved! We'll be in touch soon."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:125
+msgid "Your email has been updated but not verified. As a next step, please verify your new email."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:102
+msgid "Your email has not yet been verified. This is an important security step which we recommend."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:41
+#: src/view/com/modals/ChangeHandle.tsx:275
+msgid "Your full handle will be"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:69
+msgid "Your hosting provider"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:63
+msgid "Your posts, likes, and blocks are public. Mutes are private."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:27
+msgid "Your user handle"
+msgstr ""
diff --git a/src/locale/locales/fr/messages.js b/src/locale/locales/fr/messages.js
new file mode 100644
index 000000000..8d85ab77c
--- /dev/null
+++ b/src/locale/locales/fr/messages.js
@@ -0,0 +1 @@
+/*eslint-disable*/module.exports={messages:JSON.parse("{\"PBodTo\":\"- end of feed -\",\"EtUMsZ\":\". This warning is only available for posts with media attached.\",\"J/hVSQ\":[[\"0\"]],\"hZQerY\":[[\"0\"],\" \",[\"purposeLabel\"],\" List\"],\"6RmyWt\":\"<0>Here is your app password.</0> Use this to sign into the other app along with your handle.\",\"AnNF5e\":\"Accessibility\",\"AeXO77\":\"Account\",\"4WY4MD\":\"Account options\",\"m16xKo\":\"Add\",\"fBBX+K\":\"Add a content warning\",\"JU3hs2\":\"Add a user to this list\",\"MPPZ54\":\"Add account\",\"LkA8jz\":\"Add alt text\",\"Z8idyM\":\"Add details\",\"AoXl11\":\"Add details to report\",\"iE6B/9\":\"Add link card\",\"EXHdP1\":\"Add link card:\",\"x6laaL\":\"Add the following DNS record to your domain:\",\"jRrQFe\":\"Adjust the number of likes a reply must have to be shown in your feed.\",\"qLa52r\":\"Adult Content\",\"sxkWRg\":\"Advanced\",\"u2HO/d\":\"ALT\",\"u/DP73\":\"Alt text\",\"0QlT7/\":\"Alt text describes images for blind and low-vision users, and helps give context to everyone.\",\"woXbjq\":[\"An email has been sent to \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"Fon2dK\":[\"An email has been sent to your previous address, \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"HZFm5R\":\"and\",\"SMmUnj\":\"App passwords\",\"aAIQg2\":\"Appearance\",\"EbvWd3\":\"Artistic or non-erotic nudity.\",\"iH8pgl\":\"Back\",\"ehOkF+\":\"Basics\",\"+gCI2a\":\"Birthday\",\"pieVBA\":\"Birthday:\",\"HFCE4A\":\"Blocked post.\",\"7A9u1j\":\"Bluesky\",\"ZHmKSm\":\"Bluesky is flexible.\",\"odLrdl\":\"Bluesky is open.\",\"/LsWK4\":\"Bluesky is public.\",\"C50OGr\":\"Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon.\",\"klVoaP\":\"Bluesky.Social\",\"qxBitM\":[\"Build version \",[\"0\"],\" \",[\"1\"]],\"rT2cV+\":\"Camera\",\"JGGrPC\":\"Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long.\",\"dEgA5A\":\"Cancel\",\"aMH9rr\":\"Cancel account deletion\",\"kc3E4R\":\"Cancel add image alt text\",\"wg4LHQ\":\"Cancel change handle\",\"hFL1Li\":\"Cancel image crop\",\"tijH8t\":\"Cancel profile editing\",\"Qe4C/d\":\"Cancel quote post\",\"5TviPn\":\"Cancel search\",\"nss3UV\":\"Cancel waitlist signup\",\"o+XJ9D\":\"Change\",\"pQco5R\":\"Change handle\",\"Q5e1U/\":\"Change Handle\",\"a3NAfL\":\"Change my email\",\"4vatyk\":\"Change Your Email\",\"/+X+/K\":\"Check your inbox for an email with the confirmation code to enter below:\",\"Rt502e\":\"Choose Service\",\"/L45sc\":\"Choose the algorithms that power your experience with custom feeds.\",\"Wk8hkn\":\"Choose your password\",\"QbvBNV\":\"Clear search query\",\"flH7u/\":\"Close alert\",\"hYmnbk\":\"Close bottom drawer\",\"47L1V1\":\"Close image\",\"l49ujN\":\"Close image viewer\",\"UryHFO\":\"Close navigation footer\",\"o8UUti\":\"Compose reply\",\"7VpPHA\":\"Confirm\",\"q8upsf\":\"Confirm Change\",\"8pNKIr\":\"Confirm content language settings\",\"tGg8Kt\":\"Confirm delete account\",\"ioZOzk\":\"Confirmation code\",\"J28zul\":\"Connecting...\",\"m8j6up\":\"Content Filtering\",\"/PlAsF\":\"Content Languages\",\"cogwXi\":\"Content Warning\",\"FG7AQv\":\"Content warnings\",\"6V3Ea3\":\"Copied\",\"he3ygx\":\"Copy\",\"7wWvgo\":\"Could not load feed\",\"8NNr/O\":\"Could not load list\",\"mpt9T+\":\"Create a new account\",\"IS0nrP\":\"Create Account\",\"6HbhpU\":\"Create new account\",\"GAD3Dx\":\"Custom domain\",\"ZQKLI1\":\"Danger Zone\",\"ZDGm40\":\"Delete account\",\"vzX5FB\":\"Delete Account\",\"gUEtxf\":\"Delete app password\",\"ktknoE\":\"Delete my account\",\"szz0+N\":\"Delete my account…\",\"u+1OHY\":\"Deleted post.\",\"Nu4oKW\":\"Description\",\"dacKHE\":\"Dev Server\",\"2ygkE8\":\"Developer Tools\",\"pbLwal\":\"Discover new feeds\",\"pfa8F0\":\"Display name\",\"0gS7M5\":\"Display Name\",\"iZ5pMB\":\"Domain verified!\",\"DPfwMq\":\"Done\",\"zT97vP\":[\"Done\",[\"extraText\"]],\"XQFMOm\":\"Edit image\",\"cLmurE\":\"Edit My Feeds\",\"bRZ5XW\":\"Edit my profile\",\"9OpVZg\":\"Edit profile\",\"QJQd1J\":\"Edit Profile\",\"Jn7kox\":\"Edit Saved Feeds\",\"O3oNi5\":\"Email\",\"ATGYL1\":\"Email address\",\"pJJ0Vp\":\"Email Updated\",\"96mted\":\"Enable this setting to only see replies between people you follow.\",\"YbIxza\":\"Enter the address of your provider:\",\"BfIgP6\":\"Enter the domain you want to use\",\"xRPn3U\":\"Enter your email address\",\"+inPGm\":\"Enter your new email address below.\",\"T0KLp4\":\"Enter your username and password\",\"0PkE20\":\"Expand alt text\",\"4yCy8i\":\"Feed offline\",\"N0CqyO\":\"Feed Preferences\",\"YirHq7\":\"Feedback\",\"2DoBvq\":\"Feeds\",\"Qzj1WT\":\"Finding similar accounts...\",\"QKSrQV\":\"Fine-tune the content you see on your home screen.\",\"r+KeyR\":\"Fine-tune the discussion threads.\",\"MKEPCY\":\"Follow\",\"NIjL2Y\":\"following\",\"y6sq5j\":\"Following\",\"p3UO/y\":\"Follows you\",\"5RhDkD\":\"For security reasons, we'll need to send a confirmation code to your email address.\",\"NJPhAO\":\"For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one.\",\"5bDfuq\":\"Forgot\",\"hEPLrs\":\"Forgot password\",\"dn8X5t\":\"Forgot Password\",\"U+kFad\":\"Gallery\",\"c3b0B0\":\"Get Started\",\"CKyk7Q\":\"Go back\",\"sr0UJD\":\"Go Back\",\"Rtp0y7\":\"Go to next\",\"Nf7oXL\":\"Handle\",\"c3XJ18\":\"Help\",\"vLyv1R\":\"Hide\",\"qdOx2q\":\"Hide user list\",\"i0qMbr\":\"Home\",\"sXZ8IU\":\"Home Feed Preferences\",\"yt7fhu\":\"Hosting provider\",\"s2xA6t\":\"Hosting provider address\",\"o+axy6\":\"I have a code\",\"wey2os\":\"I have my own domain\",\"WlEcKr\":\"If none are selected, suitable for all ages.\",\"VCk0rR\":\"Image alt text\",\"STGpNQ\":\"Image options\",\"dSKHAa\":\"Invalid username or password\",\"MFKlMB\":\"Invite\",\"F5MZVk\":\"Invite a Friend\",\"6KlkHI\":\"Invite code\",\"F75w8j\":\"Join the waitlist\",\"6iVTdm\":\"Join the waitlist.\",\"SNzppu\":\"Join Waitlist\",\"Dcq5kL\":\"Language selection\",\"GAmD3h\":\"Languages\",\"NgeSlx\":\"Learn More\",\"rj0Lke\":\"Learn more about this warning\",\"kq2ga7\":\"Leave them all unchecked to see any language.\",\"QfDITI\":\"Leaving Bluesky\",\"Esfg1M\":\"Let's get your password reset!\",\"BvSY1i\":\"Like this feed\",\"FuZWua\":\"List Avatar\",\"8mjA4F\":\"List Name\",\"h16FyT\":\"Lists\",\"ujW4FW\":\"Load more posts\",\"VkLESX\":\"Load new posts\",\"jl0AFf\":\"Local dev server\",\"cR9UpQ\":\"Login to account that is not listed\",\"2U/gDT\":\"Make sure this is where you intend to go!\",\"zucql+\":\"Menu\",\"DzmsLV\":\"Moderation\",\"3Siwmw\":\"More options\",\"Y17r45\":\"More post options\",\"Mysqyf\":\"My Birthday\",\"6MBNS/\":\"My Feeds\",\"Ha6iBv\":\"My Saved Feeds\",\"6YtxFj\":\"Name\",\"8yolS6\":\"Never lose access to your followers and data.\",\"2B7HLH\":\"New post\",\"FGrimz\":\"New Post\",\"hXzOVo\":\"Next\",\"EatZYJ\":\"Next image\",\"flmDTf\":\"No description\",\"fOlAiK\":[\"No results found for \\\"\",[\"query\"],\"\\\"\"],\"kA9DpB\":[\"No results found for \",[\"0\"]],\"ispbnl\":\"Not Applicable\",\"iDNBZe\":\"Notifications\",\"UaXeX3\":\"Okay\",\"Cqo2D+\":\"One or more images is missing alt text.\",\"M/Q2aG\":\"Open navigation\",\"M5PuNq\":\"Opens configurable language settings\",\"eSqpax\":\"Opens modal for using custom domain\",\"vYwHHI\":\"Opens moderation settings\",\"0tHyB7\":\"Opens screen with all saved feeds\",\"nmRoY/\":\"Opens the app password settings page\",\"6e9Apv\":\"Opens the home feed preferences\",\"O87Dr/\":\"Opens the storybook page\",\"G+PVmg\":\"Opens the system log page\",\"Jqb7sy\":\"Opens the threads preferences\",\"b22AVl\":\"Other account\",\"n+HLOP\":\"Other service\",\"1PKxQ7\":\"Other...\",\"8ZsakT\":\"Password\",\"DKeVgZ\":\"Password updated!\",\"VeZE5Q\":\"Pictures meant for adults.\",\"Apyknf\":\"Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.\",\"9qpQ5O\":\"Please enter a unique name for this App Password or use our randomly generated one.\",\"QJr5Xp\":\"Please enter your password as well:\",\"y28hnO\":\"Post\",\"h5RcXU\":\"Post hidden\",\"r5zLS0\":\"Post language\",\"AzCucI\":\"Post Languages\",\"tJFPmV\":\"Post not found\",\"0+DQbr\":\"Potentially Misleading Link\",\"MHk+7g\":\"Previous image\",\"x8iR7V\":\"Prioritize Your Follows\",\"vERlcd\":\"Profile\",\"MrgqOW\":\"Protect your account by verifying your email.\",\"8HFFRQ\":\"Quote post\",\"+KrAHa\":\"Quote Post\",\"WlWsdE\":\"Ratios\",\"t/YqKh\":\"Remove\",\"5ywtDz\":\"Remove image\",\"Dw/XUh\":\"Remove image preview\",\"Veu9gK\":\"Reply Filters\",\"lQWbAr\":[\"Report \",[\"collectionName\"]],\"6IcSvC\":\"Report post\",\"JOV5dR\":\"Repost or quote post\",\"bqG37Z\":\"Request Change\",\"8XIT+P\":\"Required for this provider\",\"vJgYMA\":\"Reset code\",\"xEL92I\":\"Reset onboarding state\",\"bee/Fw\":\"Reset preferences state\",\"wToeoz\":\"Resets the onboarding state\",\"nIU7qI\":\"Resets the preferences state\",\"6gRgw8\":\"Retry\",\"hAbYQa\":\"Retry change handle\",\"tfDRzk\":\"Save\",\"KV2YQQ\":\"Save alt text\",\"y3aU20\":\"Save changes\",\"IUwGEM\":\"Save Changes\",\"Xs07Tg\":\"Save handle change\",\"BckA7m\":\"Save image crop\",\"A1taO8\":\"Search\",\"CKROFy\":\"Security Step Required\",\"cNzyJW\":\"See what's next\",\"L5sM7N\":\"Select Bluesky Social\",\"o3dwub\":\"Select from an existing account\",\"GGw2AK\":\"Select service\",\"vp9yIB\":\"Send Confirmation Email\",\"65dxv8\":\"Send email\",\"i/TzEU\":\"Send Email\",\"RoafuO\":\"Send feedback\",\"4cijjm\":\"Send Report\",\"V/e7nf\":\"Set new password\",\"gwsie4\":\"Set this setting to \\\"No\\\" to hide all quote posts from your feed. Reposts will still be visible.\",\"IZjC3J\":\"Set this setting to \\\"No\\\" to hide all replies from your feed.\",\"KIgU3l\":\"Set this setting to \\\"No\\\" to hide all reposts from your feed.\",\"zaAyrz\":\"Set this setting to \\\"Yes\\\" to show replies in a threaded view. This is an experimental feature.\",\"fQV2eE\":\"Set this setting to \\\"Yes\\\" to show samples of your saved feeds in your following feed. This is an experimental feature.\",\"Tz0i8g\":\"Settings\",\"HfWHhJ\":\"Sexual activity or erotic nudity.\",\"8vETh9\":\"Show\",\"aWAdCb\":\"Show anyway\",\"NijgXr\":\"Show Posts from My Feeds\",\"T3Mt8m\":\"Show Quote Posts\",\"BlW8X/\":\"Show Replies\",\"X4GwDb\":\"Show replies by people you follow before all other replies.\",\"GiogzH\":\"Show Reposts\",\"fhY/fL\":\"Show users\",\"5lWFkC\":\"Sign in\",\"n1ekoW\":\"Sign In\",\"N9o7n5\":[\"Sign in as \",[\"0\"]],\"FT1MVS\":\"Sign in as...\",\"+UpfFC\":\"Sign into\",\"fcWrnU\":\"Sign out\",\"zU+Ro7\":\"Signed in as\",\"6Uau97\":\"Skip\",\"0o5BFH\":\"Sort Replies\",\"GH1Rgk\":\"Sort replies to the same post by:\",\"1DA6ap\":\"Square\",\"aKEHLj\":\"Staging\",\"tgEXwM\":\"Status page\",\"P5jja7\":\"Storybook\",\"EDl9kS\":\"Subscribe\",\"5z3ICN\":\"Subscribe to this list\",\"VjWeLI\":\"Switch Account\",\"fP8jTZ\":\"System log\",\"HF6Iah\":\"Tall\",\"p8Iz39\":\"Text input field\",\"G4EksE\":\"The post may have been deleted.\",\"KRYn8w\":[\"This \",[\"screenDescription\"],\" has been flagged:\"],\"lm845B\":\"This information is not shared with other users.\",\"5Pvw/O\":\"This is important in case you ever need to change your email or reset your password.\",\"sQQfZ9\":\"This is the service that keeps you online.\",\"CvX8qs\":\"This link is taking you to the following website:\",\"WKrUVy\":\"This post has been deleted.\",\"u9ThjD\":\"Thread Preferences\",\"zmXsk5\":\"Threaded Mode\",\"1x30Qt\":\"Toggle dropdown\",\"KFXQEt\":\"Transformations\",\"pi8x/S\":\"Translate\",\"KDw4GX\":\"Try again\",\"nc4Wfd\":\"Unable to contact your service. Please check your Internet connection.\",\"tuS5Jz\":\"Unblock\",\"vaz2uI\":[\"Update \",[\"displayName\"],\" in Lists\"],\"RXbEvi\":\"Updating...\",\"Vwkfp4\":\"Upload a text file to:\",\"jTdnU6\":\"Use app passwords to login to other Bluesky clients without giving full access to your account or password.\",\"CH1am9\":\"Use default provider\",\"t4Yp4Z\":\"User handle\",\"nZx9mr\":\"Username or email address\",\"Sxm8rQ\":\"Users\",\"MBOY4U\":\"Verify email\",\"Ejyv0o\":\"Verify my email\",\"9czCrB\":\"Verify My Email\",\"ibSVGR\":\"Verify New Email\",\"nHsQde\":\"View debug entry\",\"47jzzd\":\"View the avatar\",\"wK4H1r\":\"Visit Site\",\"qjBGxf\":\"We're so excited to have you join us!\",\"Mj7rl/\":[\"What is the issue with this \",[\"collectionName\"],\"?\"],\"3qn29J\":\"Which languages are used in this post?\",\"uawiGa\":\"Which languages would you like to see in your algorithmic feeds?\",\"I5S9ZE\":\"Wide\",\"y02THm\":\"Write post\",\"6ckZRB\":\"Write your reply\",\"STPj0e\":\"You can change hosting providers at any time.\",\"67nRLM\":\"You can now sign in with your new password.\",\"RkXibf\":\"You have blocked the author or you have been blocked by the author.\",\"tCLJ9E\":\"You have no lists.\",\"NDgp3i\":\"You have not created any app passwords yet. You can create one by pressing the button below.\",\"RrDyEb\":\"You will receive an email with a \\\"reset code.\\\" Enter that code here, then enter your new password.\",\"gdRnT7\":\"Your account\",\"k7hmsH\":\"Your birth date\",\"OubkcP\":\"Your email has been saved! We'll be in touch soon.\",\"z2L+/9\":\"Your email has been updated but not verified. As a next step, please verify your new email.\",\"XZlIVw\":\"Your email has not yet been verified. This is an important security step which we recommend.\",\"qv9f4I\":\"Your full handle will be\",\"lvcqqG\":\"Your hosting provider\",\"Oqt/PG\":\"Your posts, likes, and blocks are public. Mutes are private.\",\"MvWO9d\":\"Your user handle\"}")};
\ No newline at end of file
diff --git a/src/locale/locales/fr/messages.po b/src/locale/locales/fr/messages.po
new file mode 100644
index 000000000..c7c8b3866
--- /dev/null
+++ b/src/locale/locales/fr/messages.po
@@ -0,0 +1,1544 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2023-11-05 16:01-0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: fr\n"
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+#: src/view/screens/Profile.tsx:212
+msgid "- end of feed -"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:138
+msgid ". This warning is only available for posts with media attached."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:45
+msgid "{0}"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:167
+msgid "{0} {purposeLabel} List"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:132
+msgid "<0>Here is your app password.</0> Use this to sign into the other app along with your handle."
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:299
+#: src/view/screens/Settings.tsx:363
+msgid "Accessibility"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:157
+#: src/view/screens/Settings.tsx:201
+msgid "Account"
+msgstr ""
+
+#: src/view/com/util/AccountDropdownBtn.tsx:41
+msgid "Account options"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:710
+msgid "Add"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:57
+msgid "Add a content warning"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:700
+msgid "Add a user to this list"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:313
+#: src/view/screens/Settings.tsx:322
+msgid "Add account"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:119
+#: src/view/com/composer/photos/Gallery.tsx:167
+msgid "Add alt text"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:41
+#: src/view/com/modals/report/Modal.tsx:190
+msgid "Add details"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:193
+msgid "Add details to report"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:419
+msgid "Add link card"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:422
+msgid "Add link card:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:418
+msgid "Add the following DNS record to your domain:"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:140
+msgid "Adjust the number of likes a reply must have to be shown in your feed."
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:76
+msgid "Adult Content"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:493
+msgid "Advanced"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:127
+msgid "ALT"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:315
+msgid "Alt text"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:193
+msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:112
+msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:119
+msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:238
+msgid "and"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:509
+msgid "App passwords"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:378
+msgid "Appearance"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:124
+msgid "Artistic or non-erotic nudity."
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:92
+#: src/view/com/auth/login/ChooseAccountForm.tsx:111
+#: src/view/com/auth/login/LoginForm.tsx:247
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:150
+#: src/view/com/modals/report/InputIssueDetails.tsx:45
+#: src/view/com/post-thread/PostThread.tsx:317
+#: src/view/com/post-thread/PostThread.tsx:325
+#: src/view/com/post-thread/PostThread.tsx:354
+#: src/view/com/post-thread/PostThread.tsx:362
+#: src/view/com/profile/ProfileHeader.tsx:576
+msgid "Back"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:407
+msgid "Basics"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:130
+#: src/view/com/modals/BirthDateSettings.tsx:69
+msgid "Birthday"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:228
+msgid "Birthday:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:211
+msgid "Blocked post."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:52
+#: src/view/com/auth/SplashScreen.tsx:27
+msgid "Bluesky"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:84
+msgid "Bluesky is flexible."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:73
+msgid "Bluesky is open."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:60
+msgid "Bluesky is public."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:70
+msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon."
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:78
+msgid "Bluesky.Social"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:612
+msgid "Build version {0} {1}"
+msgstr ""
+
+#: src/view/com/composer/photos/OpenCameraBtn.tsx:62
+msgid "Camera"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:199
+msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:271
+#: src/view/com/composer/Composer.tsx:274
+#: src/view/com/modals/AltImage.tsx:127
+#: src/view/com/modals/ChangeEmail.tsx:216
+#: src/view/com/modals/ChangeEmail.tsx:218
+#: src/view/com/modals/Confirm.tsx:89
+#: src/view/com/modals/CreateOrEditList.tsx:258
+#: src/view/com/modals/CreateOrEditList.tsx:263
+#: src/view/com/modals/DeleteAccount.tsx:142
+#: src/view/com/modals/DeleteAccount.tsx:215
+#: src/view/com/modals/EditImage.tsx:323
+#: src/view/com/modals/EditProfile.tsx:250
+#: src/view/com/modals/LinkWarning.tsx:90
+#: src/view/com/modals/Repost.tsx:74
+#: src/view/com/modals/UserAddRemoveLists.tsx:199
+#: src/view/com/modals/Waitlist.tsx:136
+#: src/view/com/search/HeaderWithInput.tsx:127
+#: src/view/shell/desktop/Search.tsx:93
+msgid "Cancel"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:138
+#: src/view/com/modals/DeleteAccount.tsx:211
+msgid "Cancel account deletion"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:122
+msgid "Cancel add image alt text"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:144
+msgid "Cancel change handle"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:134
+msgid "Cancel image crop"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:245
+msgid "Cancel profile editing"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:65
+msgid "Cancel quote post"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:101
+#: src/view/shell/desktop/Search.tsx:89
+msgid "Cancel search"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:132
+msgid "Cancel waitlist signup"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:222
+msgid "Change"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:517
+#: src/view/screens/Settings.tsx:526
+msgid "Change handle"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:156
+msgid "Change Handle"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:136
+msgid "Change my email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:109
+msgid "Change Your Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:155
+msgid "Check your inbox for an email with the confirmation code to enter below:"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:38
+msgid "Choose Service"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:87
+msgid "Choose the algorithms that power your experience with custom feeds."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:105
+msgid "Choose your password"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:111
+#: src/view/com/util/forms/SearchInput.tsx:73
+msgid "Clear search query"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:38
+msgid "Close alert"
+msgstr ""
+
+#: src/view/com/util/BottomSheetCustomBackdrop.tsx:33
+msgid "Close bottom drawer"
+msgstr ""
+
+#: src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx:26
+msgid "Close image"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:107
+msgid "Close image viewer"
+msgstr ""
+
+#: src/view/shell/index.web.tsx:65
+msgid "Close navigation footer"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:22
+msgid "Compose reply"
+msgstr ""
+
+#: src/view/com/modals/Confirm.tsx:76
+#: src/view/com/modals/SelfLabel.tsx:156
+#: src/view/com/modals/VerifyEmail.tsx:220
+#: src/view/screens/PreferencesHomeFeed.tsx:223
+#: src/view/screens/PreferencesThreads.tsx:128
+msgid "Confirm"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:193
+#: src/view/com/modals/ChangeEmail.tsx:195
+msgid "Confirm Change"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34
+msgid "Confirm content language settings"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:201
+msgid "Confirm delete account"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:157
+#: src/view/com/modals/DeleteAccount.tsx:168
+#: src/view/com/modals/VerifyEmail.tsx:154
+msgid "Confirmation code"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:125
+#: src/view/com/auth/login/LoginForm.tsx:266
+msgid "Connecting..."
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:42
+msgid "Content Filtering"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:68
+msgid "Content Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:68
+msgid "Content Warning"
+msgstr ""
+
+#: src/view/com/composer/labels/LabelsBtn.tsx:32
+msgid "Content warnings"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:178
+#: src/view/com/modals/InviteCodes.tsx:129
+msgid "Copied"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:171
+msgid "Copy"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:97
+msgid "Could not load feed"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:788
+msgid "Could not load list"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:42
+msgid "Create a new account"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:77
+msgid "Create Account"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:39
+msgid "Create new account"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:390
+#: src/view/com/modals/ServerInput.tsx:102
+msgid "Custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:531
+msgid "Danger Zone"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:538
+msgid "Delete account"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:75
+msgid "Delete Account"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:193
+msgid "Delete app password"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:204
+msgid "Delete my account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:548
+msgid "Delete my account…"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:203
+msgid "Deleted post."
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:209
+#: src/view/com/modals/CreateOrEditList.tsx:225
+#: src/view/com/modals/EditProfile.tsx:199
+#: src/view/com/modals/EditProfile.tsx:211
+msgid "Description"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:112
+msgid "Dev Server"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:553
+msgid "Developer Tools"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:165
+msgid "Discover new feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:193
+msgid "Display name"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:181
+msgid "Display Name"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:488
+msgid "Domain verified!"
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:77
+#: src/view/com/modals/ContentFilteringSettings.tsx:85
+#: src/view/com/modals/crop-image/CropImage.web.tsx:152
+#: src/view/com/modals/EditImage.tsx:333
+#: src/view/com/modals/ListAddUser.tsx:153
+#: src/view/com/modals/SelfLabel.tsx:159
+#: src/view/screens/PreferencesHomeFeed.tsx:226
+#: src/view/screens/PreferencesThreads.tsx:131
+msgid "Done"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:42
+msgid "Done{extraText}"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:141
+#: src/view/com/modals/EditImage.tsx:207
+msgid "Edit image"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:132
+msgid "Edit My Feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:158
+msgid "Edit my profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:373
+msgid "Edit profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:376
+msgid "Edit Profile"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:92
+msgid "Edit Saved Feeds"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:89
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:145
+#: src/view/com/modals/ChangeEmail.tsx:141
+#: src/view/com/modals/Waitlist.tsx:88
+msgid "Email"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:80
+msgid "Email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:111
+msgid "Email Updated"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:123
+msgid "Enable this setting to only see replies between people you follow."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:87
+msgid "Enter the address of your provider:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:372
+msgid "Enter the domain you want to use"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:85
+msgid "Enter your email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:117
+msgid "Enter your new email address below."
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:96
+msgid "Enter your username and password"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:151
+msgid "Expand alt text"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:301
+msgid "Feed offline"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:163
+msgid "Feed Preferences"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:365
+msgid "Feedback"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:154
+#: src/view/shell/Drawer.tsx:289
+msgid "Feeds"
+msgstr ""
+
+#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:119
+msgid "Finding similar accounts..."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:90
+msgid "Fine-tune the content you see on your home screen."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:43
+msgid "Fine-tune the discussion threads."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:459
+msgid "Follow"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:537
+msgid "following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:443
+msgid "Following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:492
+msgid "Follows you"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:99
+msgid "For security reasons, we'll need to send a confirmation code to your email address."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:192
+msgid "For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:229
+msgid "Forgot"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:226
+msgid "Forgot password"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:126
+#: src/view/com/auth/login/Login.tsx:143
+msgid "Forgot Password"
+msgstr ""
+
+#: src/view/com/composer/photos/SelectPhotoBtn.tsx:43
+msgid "Gallery"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:178
+msgid "Get Started"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:105
+#: src/view/shell/desktop/LeftNav.tsx:92
+msgid "Go back"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:106
+#: src/view/screens/ProfileFeed.tsx:111
+#: src/view/screens/ProfileList.tsx:797
+#: src/view/screens/ProfileList.tsx:802
+msgid "Go Back"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:178
+#: src/view/com/auth/login/LoginForm.tsx:276
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:165
+msgid "Go to next"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:270
+msgid "Handle"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:375
+msgid "Help"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:316
+msgid "Hide"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:308
+msgid "Hide user list"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:110
+#: src/view/shell/Drawer.tsx:240
+msgid "Home"
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:69
+#: src/view/screens/Settings.tsx:423
+msgid "Home Feed Preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:111
+msgid "Hosting provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:92
+#: src/view/com/auth/create/Step1.tsx:97
+msgid "Hosting provider address"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:203
+msgid "I have a code"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:286
+msgid "I have my own domain"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:128
+msgid "If none are selected, suitable for all ages."
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:96
+msgid "Image alt text"
+msgstr ""
+
+#: src/view/com/util/UserAvatar.tsx:300
+#: src/view/com/util/UserBanner.tsx:118
+msgid "Image options"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:109
+msgid "Invalid username or password"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:336
+msgid "Invite"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:329
+msgid "Invite a Friend"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:56
+msgid "Invite code"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:67
+msgid "Join the waitlist"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:67
+#: src/view/com/auth/create/Step2.tsx:71
+msgid "Join the waitlist."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:124
+msgid "Join Waitlist"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:97
+msgid "Language selection"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:471
+msgid "Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/PostAlerts.tsx:47
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:55
+#: src/view/com/util/moderation/ScreenHider.tsx:88
+msgid "Learn More"
+msgstr ""
+
+#: src/view/com/util/moderation/ContentHider.tsx:75
+#: src/view/com/util/moderation/PostAlerts.tsx:40
+#: src/view/com/util/moderation/PostHider.tsx:76
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:47
+#: src/view/com/util/moderation/ScreenHider.tsx:85
+msgid "Learn more about this warning"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:76
+msgid "Leave them all unchecked to see any language."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:56
+msgid "Leaving Bluesky"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:127
+#: src/view/com/auth/login/Login.tsx:144
+msgid "Let's get your password reset!"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:479
+msgid "Like this feed"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:177
+msgid "List Avatar"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:190
+msgid "List Name"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:297
+msgid "Lists"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:220
+#: src/view/com/post-thread/PostThread.tsx:228
+msgid "Load more posts"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:194
+msgid "Load new posts"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:50
+msgid "Local dev server"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:93
+msgid "Login to account that is not listed"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:70
+msgid "Make sure this is where you intend to go!"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:71
+msgid "Menu"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:487
+#: src/view/shell/Drawer.tsx:304
+msgid "Moderation"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:469
+#: src/view/screens/ProfileFeed.tsx:312
+#: src/view/screens/ProfileList.tsx:542
+msgid "More options"
+msgstr ""
+
+#: src/view/com/util/forms/PostDropdownBtn.tsx:158
+msgid "More post options"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:53
+msgid "My Birthday"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:128
+msgid "My Feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:454
+msgid "My Saved Feeds"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:162
+#: src/view/com/modals/CreateOrEditList.tsx:202
+msgid "Name"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:76
+msgid "Never lose access to your followers and data."
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:203
+#: src/view/screens/Feeds.tsx:261
+#: src/view/screens/Profile.tsx:304
+#: src/view/screens/ProfileFeed.tsx:378
+#: src/view/screens/ProfileList.tsx:210
+#: src/view/screens/ProfileList.tsx:248
+#: src/view/shell/desktop/LeftNav.tsx:229
+msgid "New post"
+msgstr ""
+
+#: src/view/shell/desktop/LeftNav.tsx:239
+msgid "New Post"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:105
+#: src/view/com/auth/login/LoginForm.tsx:279
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:158
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:168
+msgid "Next"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:137
+msgid "Next image"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:472
+#: src/view/screens/ProfileList.tsx:667
+msgid "No description"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:207
+msgid "No results found for \"{query}\""
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:140
+#: src/view/shell/desktop/Search.tsx:112
+msgid "No results found for {0}"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:136
+msgid "Not Applicable"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:178
+#: src/view/shell/Drawer.tsx:262
+msgid "Notifications"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:41
+msgid "Okay"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:334
+msgid "One or more images is missing alt text."
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:50
+msgid "Open navigation"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:463
+msgid "Opens configurable language settings"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:284
+msgid "Opens modal for using custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:482
+msgid "Opens moderation settings"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:448
+msgid "Opens screen with all saved feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:501
+msgid "Opens the app password settings page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:415
+msgid "Opens the home feed preferences"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:580
+msgid "Opens the storybook page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:560
+msgid "Opens the system log page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:432
+msgid "Opens the threads preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:98
+msgid "Other account"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:88
+msgid "Other service"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:84
+msgid "Other..."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:100
+#: src/view/com/auth/create/Step2.tsx:110
+#: src/view/com/auth/login/LoginForm.tsx:214
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:132
+#: src/view/com/modals/DeleteAccount.tsx:183
+msgid "Password"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:28
+msgid "Password updated!"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:122
+msgid "Pictures meant for adults."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:67
+msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:125
+msgid "Please enter a unique name for this App Password or use our randomly generated one."
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:172
+msgid "Please enter your password as well:"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:317
+msgid "Post"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:343
+msgid "Post hidden"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:80
+msgid "Post language"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:69
+msgid "Post Languages"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:309
+msgid "Post not found"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:51
+msgid "Potentially Misleading Link"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:123
+msgid "Previous image"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:73
+msgid "Prioritize Your Follows"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:220
+#: src/view/shell/Drawer.tsx:161
+#: src/view/shell/Drawer.tsx:325
+msgid "Profile"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:689
+msgid "Protect your account by verifying your email."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:53
+msgid "Quote post"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:57
+msgid "Quote Post"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:236
+msgid "Ratios"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:84
+msgid "Remove"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:154
+msgid "Remove image"
+msgstr ""
+
+#: src/view/com/composer/ExternalEmbed.tsx:70
+msgid "Remove image preview"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:120
+msgid "Reply Filters"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:165
+msgid "Report {collectionName}"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:37
+msgid "Report post"
+msgstr ""
+
+#: src/view/com/util/post-ctrls/RepostButton.web.tsx:69
+msgid "Repost or quote post"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:181
+#: src/view/com/modals/ChangeEmail.tsx:183
+msgid "Request Change"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:52
+msgid "Required for this provider"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:110
+msgid "Reset code"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:602
+msgid "Reset onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:592
+msgid "Reset preferences state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:600
+msgid "Resets the onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:590
+msgid "Resets the preferences state"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:114
+#: src/view/com/auth/create/CreateAccount.tsx:118
+#: src/view/com/auth/login/LoginForm.tsx:256
+#: src/view/com/auth/login/LoginForm.tsx:259
+#: src/view/com/util/error/ErrorMessage.tsx:55
+#: src/view/com/util/error/ErrorScreen.tsx:65
+msgid "Retry"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:166
+msgid "Retry change handle"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:114
+#: src/view/com/modals/BirthDateSettings.tsx:90
+#: src/view/com/modals/BirthDateSettings.tsx:93
+#: src/view/com/modals/ChangeHandle.tsx:179
+#: src/view/com/modals/CreateOrEditList.tsx:240
+#: src/view/com/modals/CreateOrEditList.tsx:248
+#: src/view/com/modals/EditProfile.tsx:225
+msgid "Save"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:105
+msgid "Save alt text"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:210
+msgid "Save changes"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:233
+msgid "Save Changes"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:176
+msgid "Save handle change"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:144
+msgid "Save image crop"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:89
+#: src/view/com/search/HeaderWithInput.tsx:101
+#: src/view/com/util/forms/SearchInput.tsx:64
+#: src/view/shell/bottom-bar/BottomBar.tsx:132
+#: src/view/shell/desktop/Search.tsx:81
+#: src/view/shell/Drawer.tsx:218
+msgid "Search"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:110
+msgid "Security Step Required"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:30
+msgid "See what's next"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:75
+msgid "Select Bluesky Social"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:115
+msgid "Select from an existing account"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:141
+msgid "Select service"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:191
+msgid "Send Confirmation Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:119
+msgid "Send email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:130
+msgid "Send Email"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:349
+#: src/view/shell/Drawer.tsx:370
+msgid "Send feedback"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:45
+msgid "Send Report"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:80
+msgid "Set new password"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:172
+msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:101
+msgid "Set this setting to \"No\" to hide all replies from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:155
+msgid "Set this setting to \"No\" to hide all reposts from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:96
+msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:191
+msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:338
+msgid "Settings"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:126
+msgid "Sexual activity or erotic nudity."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:235
+msgid "Show"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:114
+msgid "Show anyway"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:188
+msgid "Show Posts from My Feeds"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:169
+msgid "Show Quote Posts"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:98
+msgid "Show Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:76
+msgid "Show replies by people you follow before all other replies."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:152
+msgid "Show Reposts"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:337
+msgid "Show users"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:95
+#: src/view/com/auth/SplashScreen.tsx:50
+msgid "Sign in"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:53
+#: src/view/com/auth/SplashScreen.web.tsx:59
+msgid "Sign In"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:65
+msgid "Sign in as {0}"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:56
+#: src/view/com/auth/login/Login.tsx:114
+msgid "Sign in as..."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:128
+msgid "Sign into"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:71
+#: src/view/com/modals/SwitchAccount.tsx:74
+#: src/view/screens/Settings.tsx:274
+#: src/view/screens/Settings.tsx:277
+msgid "Sign out"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:245
+msgid "Signed in as"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:37
+msgid "Skip"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:51
+msgid "Sort Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:54
+msgid "Sort replies to the same post by:"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:122
+msgid "Square"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:106
+#: src/view/com/modals/ServerInput.tsx:62
+msgid "Staging"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:624
+msgid "Status page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:582
+msgid "Storybook"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:533
+msgid "Subscribe"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:529
+msgid "Subscribe to this list"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:47
+msgid "Switch Account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:562
+msgid "System log"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:112
+msgid "Tall"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:50
+msgid "Text input field"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:312
+msgid "The post may have been deleted."
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:71
+msgid "This {screenDescription} has been flagged:"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:58
+msgid "This information is not shared with other users."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:107
+msgid "This is important in case you ever need to change your email or reset your password."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:71
+msgid "This is the service that keeps you online."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:63
+msgid "This link is taking you to the following website:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:176
+msgid "This post has been deleted."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:441
+msgid "Thread Preferences"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:93
+msgid "Threaded Mode"
+msgstr ""
+
+#: src/view/com/util/forms/DropdownButton.tsx:230
+msgid "Toggle dropdown"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:271
+msgid "Transformations"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:654
+msgid "Translate"
+msgstr ""
+
+#: src/view/com/util/error/ErrorScreen.tsx:73
+msgid "Try again"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:74
+#: src/view/com/auth/login/LoginForm.tsx:113
+msgid "Unable to contact your service. Please check your Internet connection."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:386
+#: src/view/com/profile/ProfileHeader.tsx:389
+msgid "Unblock"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:185
+msgid "Update {displayName} in Lists"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:174
+msgid "Updating..."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:456
+msgid "Upload a text file to:"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:148
+msgid "Use app passwords to login to other Bluesky clients without giving full access to your account or password."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:516
+msgid "Use default provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:37
+msgid "User handle"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:168
+#: src/view/com/auth/login/LoginForm.tsx:185
+msgid "Username or email address"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:694
+msgid "Users"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:650
+msgid "Verify email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:675
+msgid "Verify my email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:684
+msgid "Verify My Email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:205
+#: src/view/com/modals/ChangeEmail.tsx:207
+msgid "Verify New Email"
+msgstr ""
+
+#: src/view/screens/Log.tsx:53
+msgid "View debug entry"
+msgstr ""
+
+#: src/view/com/profile/ProfileSubpageHeader.tsx:127
+msgid "View the avatar"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:80
+msgid "Visit Site"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:78
+msgid "We're so excited to have you join us!"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:168
+msgid "What is the issue with this {collectionName}?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:72
+msgid "Which languages are used in this post?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:71
+msgid "Which languages would you like to see in your algorithmic feeds?"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:102
+msgid "Wide"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:390
+msgid "Write post"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:31
+msgid "Write your reply"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:122
+msgid "You can change hosting providers at any time."
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:31
+msgid "You can now sign in with your new password."
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:346
+msgid "You have blocked the author or you have been blocked by the author."
+msgstr ""
+
+#: src/view/com/lists/ListsList.tsx:112
+msgid "You have no lists."
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:55
+msgid "You have not created any app passwords yet. You can create one by pressing the button below."
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:83
+msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:42
+msgid "Your account"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:121
+msgid "Your birth date"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:107
+msgid "Your email has been saved! We'll be in touch soon."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:125
+msgid "Your email has been updated but not verified. As a next step, please verify your new email."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:102
+msgid "Your email has not yet been verified. This is an important security step which we recommend."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:41
+#: src/view/com/modals/ChangeHandle.tsx:275
+msgid "Your full handle will be"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:69
+msgid "Your hosting provider"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:63
+msgid "Your posts, likes, and blocks are public. Mutes are private."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:27
+msgid "Your user handle"
+msgstr ""
diff --git a/src/locale/locales/hi/messages.js b/src/locale/locales/hi/messages.js
new file mode 100644
index 000000000..8d85ab77c
--- /dev/null
+++ b/src/locale/locales/hi/messages.js
@@ -0,0 +1 @@
+/*eslint-disable*/module.exports={messages:JSON.parse("{\"PBodTo\":\"- end of feed -\",\"EtUMsZ\":\". This warning is only available for posts with media attached.\",\"J/hVSQ\":[[\"0\"]],\"hZQerY\":[[\"0\"],\" \",[\"purposeLabel\"],\" List\"],\"6RmyWt\":\"<0>Here is your app password.</0> Use this to sign into the other app along with your handle.\",\"AnNF5e\":\"Accessibility\",\"AeXO77\":\"Account\",\"4WY4MD\":\"Account options\",\"m16xKo\":\"Add\",\"fBBX+K\":\"Add a content warning\",\"JU3hs2\":\"Add a user to this list\",\"MPPZ54\":\"Add account\",\"LkA8jz\":\"Add alt text\",\"Z8idyM\":\"Add details\",\"AoXl11\":\"Add details to report\",\"iE6B/9\":\"Add link card\",\"EXHdP1\":\"Add link card:\",\"x6laaL\":\"Add the following DNS record to your domain:\",\"jRrQFe\":\"Adjust the number of likes a reply must have to be shown in your feed.\",\"qLa52r\":\"Adult Content\",\"sxkWRg\":\"Advanced\",\"u2HO/d\":\"ALT\",\"u/DP73\":\"Alt text\",\"0QlT7/\":\"Alt text describes images for blind and low-vision users, and helps give context to everyone.\",\"woXbjq\":[\"An email has been sent to \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"Fon2dK\":[\"An email has been sent to your previous address, \",[\"0\"],\". It includes a confirmation code which you can enter below.\"],\"HZFm5R\":\"and\",\"SMmUnj\":\"App passwords\",\"aAIQg2\":\"Appearance\",\"EbvWd3\":\"Artistic or non-erotic nudity.\",\"iH8pgl\":\"Back\",\"ehOkF+\":\"Basics\",\"+gCI2a\":\"Birthday\",\"pieVBA\":\"Birthday:\",\"HFCE4A\":\"Blocked post.\",\"7A9u1j\":\"Bluesky\",\"ZHmKSm\":\"Bluesky is flexible.\",\"odLrdl\":\"Bluesky is open.\",\"/LsWK4\":\"Bluesky is public.\",\"C50OGr\":\"Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon.\",\"klVoaP\":\"Bluesky.Social\",\"qxBitM\":[\"Build version \",[\"0\"],\" \",[\"1\"]],\"rT2cV+\":\"Camera\",\"JGGrPC\":\"Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long.\",\"dEgA5A\":\"Cancel\",\"aMH9rr\":\"Cancel account deletion\",\"kc3E4R\":\"Cancel add image alt text\",\"wg4LHQ\":\"Cancel change handle\",\"hFL1Li\":\"Cancel image crop\",\"tijH8t\":\"Cancel profile editing\",\"Qe4C/d\":\"Cancel quote post\",\"5TviPn\":\"Cancel search\",\"nss3UV\":\"Cancel waitlist signup\",\"o+XJ9D\":\"Change\",\"pQco5R\":\"Change handle\",\"Q5e1U/\":\"Change Handle\",\"a3NAfL\":\"Change my email\",\"4vatyk\":\"Change Your Email\",\"/+X+/K\":\"Check your inbox for an email with the confirmation code to enter below:\",\"Rt502e\":\"Choose Service\",\"/L45sc\":\"Choose the algorithms that power your experience with custom feeds.\",\"Wk8hkn\":\"Choose your password\",\"QbvBNV\":\"Clear search query\",\"flH7u/\":\"Close alert\",\"hYmnbk\":\"Close bottom drawer\",\"47L1V1\":\"Close image\",\"l49ujN\":\"Close image viewer\",\"UryHFO\":\"Close navigation footer\",\"o8UUti\":\"Compose reply\",\"7VpPHA\":\"Confirm\",\"q8upsf\":\"Confirm Change\",\"8pNKIr\":\"Confirm content language settings\",\"tGg8Kt\":\"Confirm delete account\",\"ioZOzk\":\"Confirmation code\",\"J28zul\":\"Connecting...\",\"m8j6up\":\"Content Filtering\",\"/PlAsF\":\"Content Languages\",\"cogwXi\":\"Content Warning\",\"FG7AQv\":\"Content warnings\",\"6V3Ea3\":\"Copied\",\"he3ygx\":\"Copy\",\"7wWvgo\":\"Could not load feed\",\"8NNr/O\":\"Could not load list\",\"mpt9T+\":\"Create a new account\",\"IS0nrP\":\"Create Account\",\"6HbhpU\":\"Create new account\",\"GAD3Dx\":\"Custom domain\",\"ZQKLI1\":\"Danger Zone\",\"ZDGm40\":\"Delete account\",\"vzX5FB\":\"Delete Account\",\"gUEtxf\":\"Delete app password\",\"ktknoE\":\"Delete my account\",\"szz0+N\":\"Delete my account…\",\"u+1OHY\":\"Deleted post.\",\"Nu4oKW\":\"Description\",\"dacKHE\":\"Dev Server\",\"2ygkE8\":\"Developer Tools\",\"pbLwal\":\"Discover new feeds\",\"pfa8F0\":\"Display name\",\"0gS7M5\":\"Display Name\",\"iZ5pMB\":\"Domain verified!\",\"DPfwMq\":\"Done\",\"zT97vP\":[\"Done\",[\"extraText\"]],\"XQFMOm\":\"Edit image\",\"cLmurE\":\"Edit My Feeds\",\"bRZ5XW\":\"Edit my profile\",\"9OpVZg\":\"Edit profile\",\"QJQd1J\":\"Edit Profile\",\"Jn7kox\":\"Edit Saved Feeds\",\"O3oNi5\":\"Email\",\"ATGYL1\":\"Email address\",\"pJJ0Vp\":\"Email Updated\",\"96mted\":\"Enable this setting to only see replies between people you follow.\",\"YbIxza\":\"Enter the address of your provider:\",\"BfIgP6\":\"Enter the domain you want to use\",\"xRPn3U\":\"Enter your email address\",\"+inPGm\":\"Enter your new email address below.\",\"T0KLp4\":\"Enter your username and password\",\"0PkE20\":\"Expand alt text\",\"4yCy8i\":\"Feed offline\",\"N0CqyO\":\"Feed Preferences\",\"YirHq7\":\"Feedback\",\"2DoBvq\":\"Feeds\",\"Qzj1WT\":\"Finding similar accounts...\",\"QKSrQV\":\"Fine-tune the content you see on your home screen.\",\"r+KeyR\":\"Fine-tune the discussion threads.\",\"MKEPCY\":\"Follow\",\"NIjL2Y\":\"following\",\"y6sq5j\":\"Following\",\"p3UO/y\":\"Follows you\",\"5RhDkD\":\"For security reasons, we'll need to send a confirmation code to your email address.\",\"NJPhAO\":\"For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one.\",\"5bDfuq\":\"Forgot\",\"hEPLrs\":\"Forgot password\",\"dn8X5t\":\"Forgot Password\",\"U+kFad\":\"Gallery\",\"c3b0B0\":\"Get Started\",\"CKyk7Q\":\"Go back\",\"sr0UJD\":\"Go Back\",\"Rtp0y7\":\"Go to next\",\"Nf7oXL\":\"Handle\",\"c3XJ18\":\"Help\",\"vLyv1R\":\"Hide\",\"qdOx2q\":\"Hide user list\",\"i0qMbr\":\"Home\",\"sXZ8IU\":\"Home Feed Preferences\",\"yt7fhu\":\"Hosting provider\",\"s2xA6t\":\"Hosting provider address\",\"o+axy6\":\"I have a code\",\"wey2os\":\"I have my own domain\",\"WlEcKr\":\"If none are selected, suitable for all ages.\",\"VCk0rR\":\"Image alt text\",\"STGpNQ\":\"Image options\",\"dSKHAa\":\"Invalid username or password\",\"MFKlMB\":\"Invite\",\"F5MZVk\":\"Invite a Friend\",\"6KlkHI\":\"Invite code\",\"F75w8j\":\"Join the waitlist\",\"6iVTdm\":\"Join the waitlist.\",\"SNzppu\":\"Join Waitlist\",\"Dcq5kL\":\"Language selection\",\"GAmD3h\":\"Languages\",\"NgeSlx\":\"Learn More\",\"rj0Lke\":\"Learn more about this warning\",\"kq2ga7\":\"Leave them all unchecked to see any language.\",\"QfDITI\":\"Leaving Bluesky\",\"Esfg1M\":\"Let's get your password reset!\",\"BvSY1i\":\"Like this feed\",\"FuZWua\":\"List Avatar\",\"8mjA4F\":\"List Name\",\"h16FyT\":\"Lists\",\"ujW4FW\":\"Load more posts\",\"VkLESX\":\"Load new posts\",\"jl0AFf\":\"Local dev server\",\"cR9UpQ\":\"Login to account that is not listed\",\"2U/gDT\":\"Make sure this is where you intend to go!\",\"zucql+\":\"Menu\",\"DzmsLV\":\"Moderation\",\"3Siwmw\":\"More options\",\"Y17r45\":\"More post options\",\"Mysqyf\":\"My Birthday\",\"6MBNS/\":\"My Feeds\",\"Ha6iBv\":\"My Saved Feeds\",\"6YtxFj\":\"Name\",\"8yolS6\":\"Never lose access to your followers and data.\",\"2B7HLH\":\"New post\",\"FGrimz\":\"New Post\",\"hXzOVo\":\"Next\",\"EatZYJ\":\"Next image\",\"flmDTf\":\"No description\",\"fOlAiK\":[\"No results found for \\\"\",[\"query\"],\"\\\"\"],\"kA9DpB\":[\"No results found for \",[\"0\"]],\"ispbnl\":\"Not Applicable\",\"iDNBZe\":\"Notifications\",\"UaXeX3\":\"Okay\",\"Cqo2D+\":\"One or more images is missing alt text.\",\"M/Q2aG\":\"Open navigation\",\"M5PuNq\":\"Opens configurable language settings\",\"eSqpax\":\"Opens modal for using custom domain\",\"vYwHHI\":\"Opens moderation settings\",\"0tHyB7\":\"Opens screen with all saved feeds\",\"nmRoY/\":\"Opens the app password settings page\",\"6e9Apv\":\"Opens the home feed preferences\",\"O87Dr/\":\"Opens the storybook page\",\"G+PVmg\":\"Opens the system log page\",\"Jqb7sy\":\"Opens the threads preferences\",\"b22AVl\":\"Other account\",\"n+HLOP\":\"Other service\",\"1PKxQ7\":\"Other...\",\"8ZsakT\":\"Password\",\"DKeVgZ\":\"Password updated!\",\"VeZE5Q\":\"Pictures meant for adults.\",\"Apyknf\":\"Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.\",\"9qpQ5O\":\"Please enter a unique name for this App Password or use our randomly generated one.\",\"QJr5Xp\":\"Please enter your password as well:\",\"y28hnO\":\"Post\",\"h5RcXU\":\"Post hidden\",\"r5zLS0\":\"Post language\",\"AzCucI\":\"Post Languages\",\"tJFPmV\":\"Post not found\",\"0+DQbr\":\"Potentially Misleading Link\",\"MHk+7g\":\"Previous image\",\"x8iR7V\":\"Prioritize Your Follows\",\"vERlcd\":\"Profile\",\"MrgqOW\":\"Protect your account by verifying your email.\",\"8HFFRQ\":\"Quote post\",\"+KrAHa\":\"Quote Post\",\"WlWsdE\":\"Ratios\",\"t/YqKh\":\"Remove\",\"5ywtDz\":\"Remove image\",\"Dw/XUh\":\"Remove image preview\",\"Veu9gK\":\"Reply Filters\",\"lQWbAr\":[\"Report \",[\"collectionName\"]],\"6IcSvC\":\"Report post\",\"JOV5dR\":\"Repost or quote post\",\"bqG37Z\":\"Request Change\",\"8XIT+P\":\"Required for this provider\",\"vJgYMA\":\"Reset code\",\"xEL92I\":\"Reset onboarding state\",\"bee/Fw\":\"Reset preferences state\",\"wToeoz\":\"Resets the onboarding state\",\"nIU7qI\":\"Resets the preferences state\",\"6gRgw8\":\"Retry\",\"hAbYQa\":\"Retry change handle\",\"tfDRzk\":\"Save\",\"KV2YQQ\":\"Save alt text\",\"y3aU20\":\"Save changes\",\"IUwGEM\":\"Save Changes\",\"Xs07Tg\":\"Save handle change\",\"BckA7m\":\"Save image crop\",\"A1taO8\":\"Search\",\"CKROFy\":\"Security Step Required\",\"cNzyJW\":\"See what's next\",\"L5sM7N\":\"Select Bluesky Social\",\"o3dwub\":\"Select from an existing account\",\"GGw2AK\":\"Select service\",\"vp9yIB\":\"Send Confirmation Email\",\"65dxv8\":\"Send email\",\"i/TzEU\":\"Send Email\",\"RoafuO\":\"Send feedback\",\"4cijjm\":\"Send Report\",\"V/e7nf\":\"Set new password\",\"gwsie4\":\"Set this setting to \\\"No\\\" to hide all quote posts from your feed. Reposts will still be visible.\",\"IZjC3J\":\"Set this setting to \\\"No\\\" to hide all replies from your feed.\",\"KIgU3l\":\"Set this setting to \\\"No\\\" to hide all reposts from your feed.\",\"zaAyrz\":\"Set this setting to \\\"Yes\\\" to show replies in a threaded view. This is an experimental feature.\",\"fQV2eE\":\"Set this setting to \\\"Yes\\\" to show samples of your saved feeds in your following feed. This is an experimental feature.\",\"Tz0i8g\":\"Settings\",\"HfWHhJ\":\"Sexual activity or erotic nudity.\",\"8vETh9\":\"Show\",\"aWAdCb\":\"Show anyway\",\"NijgXr\":\"Show Posts from My Feeds\",\"T3Mt8m\":\"Show Quote Posts\",\"BlW8X/\":\"Show Replies\",\"X4GwDb\":\"Show replies by people you follow before all other replies.\",\"GiogzH\":\"Show Reposts\",\"fhY/fL\":\"Show users\",\"5lWFkC\":\"Sign in\",\"n1ekoW\":\"Sign In\",\"N9o7n5\":[\"Sign in as \",[\"0\"]],\"FT1MVS\":\"Sign in as...\",\"+UpfFC\":\"Sign into\",\"fcWrnU\":\"Sign out\",\"zU+Ro7\":\"Signed in as\",\"6Uau97\":\"Skip\",\"0o5BFH\":\"Sort Replies\",\"GH1Rgk\":\"Sort replies to the same post by:\",\"1DA6ap\":\"Square\",\"aKEHLj\":\"Staging\",\"tgEXwM\":\"Status page\",\"P5jja7\":\"Storybook\",\"EDl9kS\":\"Subscribe\",\"5z3ICN\":\"Subscribe to this list\",\"VjWeLI\":\"Switch Account\",\"fP8jTZ\":\"System log\",\"HF6Iah\":\"Tall\",\"p8Iz39\":\"Text input field\",\"G4EksE\":\"The post may have been deleted.\",\"KRYn8w\":[\"This \",[\"screenDescription\"],\" has been flagged:\"],\"lm845B\":\"This information is not shared with other users.\",\"5Pvw/O\":\"This is important in case you ever need to change your email or reset your password.\",\"sQQfZ9\":\"This is the service that keeps you online.\",\"CvX8qs\":\"This link is taking you to the following website:\",\"WKrUVy\":\"This post has been deleted.\",\"u9ThjD\":\"Thread Preferences\",\"zmXsk5\":\"Threaded Mode\",\"1x30Qt\":\"Toggle dropdown\",\"KFXQEt\":\"Transformations\",\"pi8x/S\":\"Translate\",\"KDw4GX\":\"Try again\",\"nc4Wfd\":\"Unable to contact your service. Please check your Internet connection.\",\"tuS5Jz\":\"Unblock\",\"vaz2uI\":[\"Update \",[\"displayName\"],\" in Lists\"],\"RXbEvi\":\"Updating...\",\"Vwkfp4\":\"Upload a text file to:\",\"jTdnU6\":\"Use app passwords to login to other Bluesky clients without giving full access to your account or password.\",\"CH1am9\":\"Use default provider\",\"t4Yp4Z\":\"User handle\",\"nZx9mr\":\"Username or email address\",\"Sxm8rQ\":\"Users\",\"MBOY4U\":\"Verify email\",\"Ejyv0o\":\"Verify my email\",\"9czCrB\":\"Verify My Email\",\"ibSVGR\":\"Verify New Email\",\"nHsQde\":\"View debug entry\",\"47jzzd\":\"View the avatar\",\"wK4H1r\":\"Visit Site\",\"qjBGxf\":\"We're so excited to have you join us!\",\"Mj7rl/\":[\"What is the issue with this \",[\"collectionName\"],\"?\"],\"3qn29J\":\"Which languages are used in this post?\",\"uawiGa\":\"Which languages would you like to see in your algorithmic feeds?\",\"I5S9ZE\":\"Wide\",\"y02THm\":\"Write post\",\"6ckZRB\":\"Write your reply\",\"STPj0e\":\"You can change hosting providers at any time.\",\"67nRLM\":\"You can now sign in with your new password.\",\"RkXibf\":\"You have blocked the author or you have been blocked by the author.\",\"tCLJ9E\":\"You have no lists.\",\"NDgp3i\":\"You have not created any app passwords yet. You can create one by pressing the button below.\",\"RrDyEb\":\"You will receive an email with a \\\"reset code.\\\" Enter that code here, then enter your new password.\",\"gdRnT7\":\"Your account\",\"k7hmsH\":\"Your birth date\",\"OubkcP\":\"Your email has been saved! We'll be in touch soon.\",\"z2L+/9\":\"Your email has been updated but not verified. As a next step, please verify your new email.\",\"XZlIVw\":\"Your email has not yet been verified. This is an important security step which we recommend.\",\"qv9f4I\":\"Your full handle will be\",\"lvcqqG\":\"Your hosting provider\",\"Oqt/PG\":\"Your posts, likes, and blocks are public. Mutes are private.\",\"MvWO9d\":\"Your user handle\"}")};
\ No newline at end of file
diff --git a/src/locale/locales/hi/messages.po b/src/locale/locales/hi/messages.po
new file mode 100644
index 000000000..f3241668e
--- /dev/null
+++ b/src/locale/locales/hi/messages.po
@@ -0,0 +1,1544 @@
+msgid ""
+msgstr ""
+"POT-Creation-Date: 2023-11-06 12:28-0800\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: @lingui/cli\n"
+"Language: hi\n"
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+#: src/view/screens/Profile.tsx:212
+msgid "- end of feed -"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:138
+msgid ". This warning is only available for posts with media attached."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:45
+msgid "{0}"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:167
+msgid "{0} {purposeLabel} List"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:132
+msgid "<0>Here is your app password.</0> Use this to sign into the other app along with your handle."
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:299
+#: src/view/screens/Settings.tsx:363
+msgid "Accessibility"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:157
+#: src/view/screens/Settings.tsx:201
+msgid "Account"
+msgstr ""
+
+#: src/view/com/util/AccountDropdownBtn.tsx:41
+msgid "Account options"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:710
+msgid "Add"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:57
+msgid "Add a content warning"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:700
+msgid "Add a user to this list"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:313
+#: src/view/screens/Settings.tsx:322
+msgid "Add account"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:119
+#: src/view/com/composer/photos/Gallery.tsx:167
+msgid "Add alt text"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:41
+#: src/view/com/modals/report/Modal.tsx:190
+msgid "Add details"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:193
+msgid "Add details to report"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:419
+msgid "Add link card"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:422
+msgid "Add link card:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:418
+msgid "Add the following DNS record to your domain:"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:140
+msgid "Adjust the number of likes a reply must have to be shown in your feed."
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:76
+msgid "Adult Content"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:493
+msgid "Advanced"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:127
+msgid "ALT"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:315
+msgid "Alt text"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:193
+msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:112
+msgid "An email has been sent to {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:119
+msgid "An email has been sent to your previous address, {0}. It includes a confirmation code which you can enter below."
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:238
+msgid "and"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:509
+msgid "App passwords"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:378
+msgid "Appearance"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:124
+msgid "Artistic or non-erotic nudity."
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:92
+#: src/view/com/auth/login/ChooseAccountForm.tsx:111
+#: src/view/com/auth/login/LoginForm.tsx:247
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:150
+#: src/view/com/modals/report/InputIssueDetails.tsx:45
+#: src/view/com/post-thread/PostThread.tsx:317
+#: src/view/com/post-thread/PostThread.tsx:325
+#: src/view/com/post-thread/PostThread.tsx:354
+#: src/view/com/post-thread/PostThread.tsx:362
+#: src/view/com/profile/ProfileHeader.tsx:576
+msgid "Back"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:407
+msgid "Basics"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:130
+#: src/view/com/modals/BirthDateSettings.tsx:69
+msgid "Birthday"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:228
+msgid "Birthday:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:211
+msgid "Blocked post."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:52
+#: src/view/com/auth/SplashScreen.tsx:27
+msgid "Bluesky"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:84
+msgid "Bluesky is flexible."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:73
+msgid "Bluesky is open."
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:60
+msgid "Bluesky is public."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:70
+msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon."
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:78
+msgid "Bluesky.Social"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:612
+msgid "Build version {0} {1}"
+msgstr ""
+
+#: src/view/com/composer/photos/OpenCameraBtn.tsx:62
+msgid "Camera"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:199
+msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:271
+#: src/view/com/composer/Composer.tsx:274
+#: src/view/com/modals/AltImage.tsx:127
+#: src/view/com/modals/ChangeEmail.tsx:216
+#: src/view/com/modals/ChangeEmail.tsx:218
+#: src/view/com/modals/Confirm.tsx:89
+#: src/view/com/modals/CreateOrEditList.tsx:258
+#: src/view/com/modals/CreateOrEditList.tsx:263
+#: src/view/com/modals/DeleteAccount.tsx:142
+#: src/view/com/modals/DeleteAccount.tsx:215
+#: src/view/com/modals/EditImage.tsx:323
+#: src/view/com/modals/EditProfile.tsx:250
+#: src/view/com/modals/LinkWarning.tsx:90
+#: src/view/com/modals/Repost.tsx:74
+#: src/view/com/modals/UserAddRemoveLists.tsx:199
+#: src/view/com/modals/Waitlist.tsx:136
+#: src/view/com/search/HeaderWithInput.tsx:127
+#: src/view/shell/desktop/Search.tsx:93
+msgid "Cancel"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:138
+#: src/view/com/modals/DeleteAccount.tsx:211
+msgid "Cancel account deletion"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:122
+msgid "Cancel add image alt text"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:144
+msgid "Cancel change handle"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:134
+msgid "Cancel image crop"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:245
+msgid "Cancel profile editing"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:65
+msgid "Cancel quote post"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:101
+#: src/view/shell/desktop/Search.tsx:89
+msgid "Cancel search"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:132
+msgid "Cancel waitlist signup"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:222
+msgid "Change"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:517
+#: src/view/screens/Settings.tsx:526
+msgid "Change handle"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:156
+msgid "Change Handle"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:136
+msgid "Change my email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:109
+msgid "Change Your Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:155
+msgid "Check your inbox for an email with the confirmation code to enter below:"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:38
+msgid "Choose Service"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:87
+msgid "Choose the algorithms that power your experience with custom feeds."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:105
+msgid "Choose your password"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:111
+#: src/view/com/util/forms/SearchInput.tsx:73
+msgid "Clear search query"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:38
+msgid "Close alert"
+msgstr ""
+
+#: src/view/com/util/BottomSheetCustomBackdrop.tsx:33
+msgid "Close bottom drawer"
+msgstr ""
+
+#: src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx:26
+msgid "Close image"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:107
+msgid "Close image viewer"
+msgstr ""
+
+#: src/view/shell/index.web.tsx:65
+msgid "Close navigation footer"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:22
+msgid "Compose reply"
+msgstr ""
+
+#: src/view/com/modals/Confirm.tsx:76
+#: src/view/com/modals/SelfLabel.tsx:156
+#: src/view/com/modals/VerifyEmail.tsx:220
+#: src/view/screens/PreferencesHomeFeed.tsx:223
+#: src/view/screens/PreferencesThreads.tsx:128
+msgid "Confirm"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:193
+#: src/view/com/modals/ChangeEmail.tsx:195
+msgid "Confirm Change"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:34
+msgid "Confirm content language settings"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:201
+msgid "Confirm delete account"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:157
+#: src/view/com/modals/DeleteAccount.tsx:168
+#: src/view/com/modals/VerifyEmail.tsx:154
+msgid "Confirmation code"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:125
+#: src/view/com/auth/login/LoginForm.tsx:266
+msgid "Connecting..."
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:42
+msgid "Content Filtering"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:68
+msgid "Content Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:68
+msgid "Content Warning"
+msgstr ""
+
+#: src/view/com/composer/labels/LabelsBtn.tsx:32
+msgid "Content warnings"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:178
+#: src/view/com/modals/InviteCodes.tsx:129
+msgid "Copied"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:171
+msgid "Copy"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:97
+msgid "Could not load feed"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:788
+msgid "Could not load list"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:42
+msgid "Create a new account"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:77
+msgid "Create Account"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:39
+msgid "Create new account"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:390
+#: src/view/com/modals/ServerInput.tsx:102
+msgid "Custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:531
+msgid "Danger Zone"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:538
+msgid "Delete account"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:75
+msgid "Delete Account"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:193
+msgid "Delete app password"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:204
+msgid "Delete my account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:548
+msgid "Delete my account…"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:203
+msgid "Deleted post."
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:209
+#: src/view/com/modals/CreateOrEditList.tsx:225
+#: src/view/com/modals/EditProfile.tsx:199
+#: src/view/com/modals/EditProfile.tsx:211
+msgid "Description"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:112
+msgid "Dev Server"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:553
+msgid "Developer Tools"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:165
+msgid "Discover new feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:193
+msgid "Display name"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:181
+msgid "Display Name"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:488
+msgid "Domain verified!"
+msgstr ""
+
+#: src/view/com/modals/ContentFilteringSettings.tsx:77
+#: src/view/com/modals/ContentFilteringSettings.tsx:85
+#: src/view/com/modals/crop-image/CropImage.web.tsx:152
+#: src/view/com/modals/EditImage.tsx:333
+#: src/view/com/modals/ListAddUser.tsx:153
+#: src/view/com/modals/SelfLabel.tsx:159
+#: src/view/screens/PreferencesHomeFeed.tsx:226
+#: src/view/screens/PreferencesThreads.tsx:131
+msgid "Done"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx:42
+msgid "Done{extraText}"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:141
+#: src/view/com/modals/EditImage.tsx:207
+msgid "Edit image"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:132
+msgid "Edit My Feeds"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:158
+msgid "Edit my profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:373
+msgid "Edit profile"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:376
+msgid "Edit Profile"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:92
+msgid "Edit Saved Feeds"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:89
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:145
+#: src/view/com/modals/ChangeEmail.tsx:141
+#: src/view/com/modals/Waitlist.tsx:88
+msgid "Email"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:80
+msgid "Email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:111
+msgid "Email Updated"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:123
+msgid "Enable this setting to only see replies between people you follow."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:87
+msgid "Enter the address of your provider:"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:372
+msgid "Enter the domain you want to use"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:85
+msgid "Enter your email address"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:117
+msgid "Enter your new email address below."
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:96
+msgid "Enter your username and password"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:151
+msgid "Expand alt text"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:301
+msgid "Feed offline"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:163
+msgid "Feed Preferences"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:365
+msgid "Feedback"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:154
+#: src/view/shell/Drawer.tsx:289
+msgid "Feeds"
+msgstr ""
+
+#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:119
+msgid "Finding similar accounts..."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:90
+msgid "Fine-tune the content you see on your home screen."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:43
+msgid "Fine-tune the discussion threads."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:459
+msgid "Follow"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:537
+msgid "following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:443
+msgid "Following"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:492
+msgid "Follows you"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:99
+msgid "For security reasons, we'll need to send a confirmation code to your email address."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:192
+msgid "For security reasons, you won't be able to view this again. If you lose this password, you'll need to generate a new one."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:229
+msgid "Forgot"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:226
+msgid "Forgot password"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:126
+#: src/view/com/auth/login/Login.tsx:143
+msgid "Forgot Password"
+msgstr ""
+
+#: src/view/com/composer/photos/SelectPhotoBtn.tsx:43
+msgid "Gallery"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:178
+msgid "Get Started"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:105
+#: src/view/shell/desktop/LeftNav.tsx:92
+msgid "Go back"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:106
+#: src/view/screens/ProfileFeed.tsx:111
+#: src/view/screens/ProfileList.tsx:797
+#: src/view/screens/ProfileList.tsx:802
+msgid "Go Back"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:178
+#: src/view/com/auth/login/LoginForm.tsx:276
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:165
+msgid "Go to next"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:270
+msgid "Handle"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:375
+msgid "Help"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:316
+msgid "Hide"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:308
+msgid "Hide user list"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:110
+#: src/view/shell/Drawer.tsx:240
+msgid "Home"
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:69
+#: src/view/screens/Settings.tsx:423
+msgid "Home Feed Preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ForgotPasswordForm.tsx:111
+msgid "Hosting provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:92
+#: src/view/com/auth/create/Step1.tsx:97
+msgid "Hosting provider address"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:203
+msgid "I have a code"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:286
+msgid "I have my own domain"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:128
+msgid "If none are selected, suitable for all ages."
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:96
+msgid "Image alt text"
+msgstr ""
+
+#: src/view/com/util/UserAvatar.tsx:300
+#: src/view/com/util/UserBanner.tsx:118
+msgid "Image options"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:109
+msgid "Invalid username or password"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:336
+msgid "Invite"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:329
+msgid "Invite a Friend"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:56
+msgid "Invite code"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:67
+msgid "Join the waitlist"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:67
+#: src/view/com/auth/create/Step2.tsx:71
+msgid "Join the waitlist."
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:124
+msgid "Join Waitlist"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:97
+msgid "Language selection"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:471
+msgid "Languages"
+msgstr ""
+
+#: src/view/com/util/moderation/PostAlerts.tsx:47
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:55
+#: src/view/com/util/moderation/ScreenHider.tsx:88
+msgid "Learn More"
+msgstr ""
+
+#: src/view/com/util/moderation/ContentHider.tsx:75
+#: src/view/com/util/moderation/PostAlerts.tsx:40
+#: src/view/com/util/moderation/PostHider.tsx:76
+#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:47
+#: src/view/com/util/moderation/ScreenHider.tsx:85
+msgid "Learn more about this warning"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:76
+msgid "Leave them all unchecked to see any language."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:56
+msgid "Leaving Bluesky"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:127
+#: src/view/com/auth/login/Login.tsx:144
+msgid "Let's get your password reset!"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:479
+msgid "Like this feed"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:177
+msgid "List Avatar"
+msgstr ""
+
+#: src/view/com/modals/CreateOrEditList.tsx:190
+msgid "List Name"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:297
+msgid "Lists"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:220
+#: src/view/com/post-thread/PostThread.tsx:228
+msgid "Load more posts"
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:194
+msgid "Load new posts"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:50
+msgid "Local dev server"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:93
+msgid "Login to account that is not listed"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:70
+msgid "Make sure this is where you intend to go!"
+msgstr ""
+
+#: src/view/com/search/HeaderWithInput.tsx:71
+msgid "Menu"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:487
+#: src/view/shell/Drawer.tsx:304
+msgid "Moderation"
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:469
+#: src/view/screens/ProfileFeed.tsx:312
+#: src/view/screens/ProfileList.tsx:542
+msgid "More options"
+msgstr ""
+
+#: src/view/com/util/forms/PostDropdownBtn.tsx:158
+msgid "More post options"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:53
+msgid "My Birthday"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:128
+msgid "My Feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:454
+msgid "My Saved Feeds"
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:162
+#: src/view/com/modals/CreateOrEditList.tsx:202
+msgid "Name"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:76
+msgid "Never lose access to your followers and data."
+msgstr ""
+
+#: src/view/com/feeds/FeedPage.tsx:203
+#: src/view/screens/Feeds.tsx:261
+#: src/view/screens/Profile.tsx:304
+#: src/view/screens/ProfileFeed.tsx:378
+#: src/view/screens/ProfileList.tsx:210
+#: src/view/screens/ProfileList.tsx:248
+#: src/view/shell/desktop/LeftNav.tsx:229
+msgid "New post"
+msgstr ""
+
+#: src/view/shell/desktop/LeftNav.tsx:239
+msgid "New Post"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:105
+#: src/view/com/auth/login/LoginForm.tsx:279
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:158
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:168
+msgid "Next"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:137
+msgid "Next image"
+msgstr ""
+
+#: src/view/screens/ProfileFeed.tsx:472
+#: src/view/screens/ProfileList.tsx:667
+msgid "No description"
+msgstr ""
+
+#: src/view/screens/Feeds.tsx:207
+msgid "No results found for \"{query}\""
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:140
+#: src/view/shell/desktop/Search.tsx:112
+msgid "No results found for {0}"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:136
+msgid "Not Applicable"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:178
+#: src/view/shell/Drawer.tsx:262
+msgid "Notifications"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:41
+msgid "Okay"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:334
+msgid "One or more images is missing alt text."
+msgstr ""
+
+#: src/view/com/pager/FeedsTabBarMobile.tsx:50
+msgid "Open navigation"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:463
+msgid "Opens configurable language settings"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:284
+msgid "Opens modal for using custom domain"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:482
+msgid "Opens moderation settings"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:448
+msgid "Opens screen with all saved feeds"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:501
+msgid "Opens the app password settings page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:415
+msgid "Opens the home feed preferences"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:580
+msgid "Opens the storybook page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:560
+msgid "Opens the system log page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:432
+msgid "Opens the threads preferences"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:98
+msgid "Other account"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:88
+msgid "Other service"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:84
+msgid "Other..."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:100
+#: src/view/com/auth/create/Step2.tsx:110
+#: src/view/com/auth/login/LoginForm.tsx:214
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:132
+#: src/view/com/modals/DeleteAccount.tsx:183
+msgid "Password"
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:28
+msgid "Password updated!"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:122
+msgid "Pictures meant for adults."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:67
+msgid "Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed."
+msgstr ""
+
+#: src/view/com/modals/AddAppPasswords.tsx:125
+msgid "Please enter a unique name for this App Password or use our randomly generated one."
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:172
+msgid "Please enter your password as well:"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:317
+msgid "Post"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:343
+msgid "Post hidden"
+msgstr ""
+
+#: src/view/com/composer/select-language/SelectLangBtn.tsx:80
+msgid "Post language"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:69
+msgid "Post Languages"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:309
+msgid "Post not found"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:51
+msgid "Potentially Misleading Link"
+msgstr ""
+
+#: src/view/com/lightbox/Lightbox.web.tsx:123
+msgid "Previous image"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:73
+msgid "Prioritize Your Follows"
+msgstr ""
+
+#: src/view/shell/bottom-bar/BottomBar.tsx:220
+#: src/view/shell/Drawer.tsx:161
+#: src/view/shell/Drawer.tsx:325
+msgid "Profile"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:689
+msgid "Protect your account by verifying your email."
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:53
+msgid "Quote post"
+msgstr ""
+
+#: src/view/com/modals/Repost.tsx:57
+msgid "Quote Post"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:236
+msgid "Ratios"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:84
+msgid "Remove"
+msgstr ""
+
+#: src/view/com/composer/photos/Gallery.tsx:154
+msgid "Remove image"
+msgstr ""
+
+#: src/view/com/composer/ExternalEmbed.tsx:70
+msgid "Remove image preview"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:120
+msgid "Reply Filters"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:165
+msgid "Report {collectionName}"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:37
+msgid "Report post"
+msgstr ""
+
+#: src/view/com/util/post-ctrls/RepostButton.web.tsx:69
+msgid "Repost or quote post"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:181
+#: src/view/com/modals/ChangeEmail.tsx:183
+msgid "Request Change"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:52
+msgid "Required for this provider"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:110
+msgid "Reset code"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:602
+msgid "Reset onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:592
+msgid "Reset preferences state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:600
+msgid "Resets the onboarding state"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:590
+msgid "Resets the preferences state"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:114
+#: src/view/com/auth/create/CreateAccount.tsx:118
+#: src/view/com/auth/login/LoginForm.tsx:256
+#: src/view/com/auth/login/LoginForm.tsx:259
+#: src/view/com/util/error/ErrorMessage.tsx:55
+#: src/view/com/util/error/ErrorScreen.tsx:65
+msgid "Retry"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:166
+msgid "Retry change handle"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:114
+#: src/view/com/modals/BirthDateSettings.tsx:90
+#: src/view/com/modals/BirthDateSettings.tsx:93
+#: src/view/com/modals/ChangeHandle.tsx:179
+#: src/view/com/modals/CreateOrEditList.tsx:240
+#: src/view/com/modals/CreateOrEditList.tsx:248
+#: src/view/com/modals/EditProfile.tsx:225
+msgid "Save"
+msgstr ""
+
+#: src/view/com/modals/AltImage.tsx:105
+msgid "Save alt text"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:210
+msgid "Save changes"
+msgstr ""
+
+#: src/view/com/modals/EditProfile.tsx:233
+msgid "Save Changes"
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:176
+msgid "Save handle change"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:144
+msgid "Save image crop"
+msgstr ""
+
+#: src/view/com/modals/ListAddUser.tsx:89
+#: src/view/com/search/HeaderWithInput.tsx:101
+#: src/view/com/util/forms/SearchInput.tsx:64
+#: src/view/shell/bottom-bar/BottomBar.tsx:132
+#: src/view/shell/desktop/Search.tsx:81
+#: src/view/shell/Drawer.tsx:218
+msgid "Search"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:110
+msgid "Security Step Required"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:30
+msgid "See what's next"
+msgstr ""
+
+#: src/view/com/modals/ServerInput.tsx:75
+msgid "Select Bluesky Social"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:115
+msgid "Select from an existing account"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:141
+msgid "Select service"
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:191
+msgid "Send Confirmation Email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:119
+msgid "Send email"
+msgstr ""
+
+#: src/view/com/modals/DeleteAccount.tsx:130
+msgid "Send Email"
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:349
+#: src/view/shell/Drawer.tsx:370
+msgid "Send feedback"
+msgstr ""
+
+#: src/view/com/modals/report/SendReportButton.tsx:45
+msgid "Send Report"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:80
+msgid "Set new password"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:172
+msgid "Set this setting to \"No\" to hide all quote posts from your feed. Reposts will still be visible."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:101
+msgid "Set this setting to \"No\" to hide all replies from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:155
+msgid "Set this setting to \"No\" to hide all reposts from your feed."
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:96
+msgid "Set this setting to \"Yes\" to show replies in a threaded view. This is an experimental feature."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:191
+msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
+msgstr ""
+
+#: src/view/shell/Drawer.tsx:338
+msgid "Settings"
+msgstr ""
+
+#: src/view/com/modals/SelfLabel.tsx:126
+msgid "Sexual activity or erotic nudity."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:235
+msgid "Show"
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:114
+msgid "Show anyway"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:188
+msgid "Show Posts from My Feeds"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:169
+msgid "Show Quote Posts"
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:98
+msgid "Show Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:76
+msgid "Show replies by people you follow before all other replies."
+msgstr ""
+
+#: src/view/screens/PreferencesHomeFeed.tsx:152
+msgid "Show Reposts"
+msgstr ""
+
+#: src/view/com/notifications/FeedItem.tsx:337
+msgid "Show users"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:95
+#: src/view/com/auth/SplashScreen.tsx:50
+msgid "Sign in"
+msgstr ""
+
+#: src/view/com/auth/SplashScreen.tsx:53
+#: src/view/com/auth/SplashScreen.web.tsx:59
+msgid "Sign In"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:65
+msgid "Sign in as {0}"
+msgstr ""
+
+#: src/view/com/auth/login/ChooseAccountForm.tsx:56
+#: src/view/com/auth/login/Login.tsx:114
+msgid "Sign in as..."
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:128
+msgid "Sign into"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:71
+#: src/view/com/modals/SwitchAccount.tsx:74
+#: src/view/screens/Settings.tsx:274
+#: src/view/screens/Settings.tsx:277
+msgid "Sign out"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:245
+msgid "Signed in as"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:37
+msgid "Skip"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:51
+msgid "Sort Replies"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:54
+msgid "Sort replies to the same post by:"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:122
+msgid "Square"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:106
+#: src/view/com/modals/ServerInput.tsx:62
+msgid "Staging"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:624
+msgid "Status page"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:582
+msgid "Storybook"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:533
+msgid "Subscribe"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:529
+msgid "Subscribe to this list"
+msgstr ""
+
+#: src/view/com/modals/SwitchAccount.tsx:47
+msgid "Switch Account"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:562
+msgid "System log"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:112
+msgid "Tall"
+msgstr ""
+
+#: src/view/com/modals/report/InputIssueDetails.tsx:50
+msgid "Text input field"
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:312
+msgid "The post may have been deleted."
+msgstr ""
+
+#: src/view/com/util/moderation/ScreenHider.tsx:71
+msgid "This {screenDescription} has been flagged:"
+msgstr ""
+
+#: src/view/com/modals/BirthDateSettings.tsx:58
+msgid "This information is not shared with other users."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:107
+msgid "This is important in case you ever need to change your email or reset your password."
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:71
+msgid "This is the service that keeps you online."
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:63
+msgid "This link is taking you to the following website:"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:176
+msgid "This post has been deleted."
+msgstr ""
+
+#: src/view/screens/Settings.tsx:441
+msgid "Thread Preferences"
+msgstr ""
+
+#: src/view/screens/PreferencesThreads.tsx:93
+msgid "Threaded Mode"
+msgstr ""
+
+#: src/view/com/util/forms/DropdownButton.tsx:230
+msgid "Toggle dropdown"
+msgstr ""
+
+#: src/view/com/modals/EditImage.tsx:271
+msgid "Transformations"
+msgstr ""
+
+#: src/view/com/post-thread/PostThreadItem.tsx:654
+msgid "Translate"
+msgstr ""
+
+#: src/view/com/util/error/ErrorScreen.tsx:73
+msgid "Try again"
+msgstr ""
+
+#: src/view/com/auth/login/Login.tsx:74
+#: src/view/com/auth/login/LoginForm.tsx:113
+msgid "Unable to contact your service. Please check your Internet connection."
+msgstr ""
+
+#: src/view/com/profile/ProfileHeader.tsx:386
+#: src/view/com/profile/ProfileHeader.tsx:389
+msgid "Unblock"
+msgstr ""
+
+#: src/view/com/modals/UserAddRemoveLists.tsx:185
+msgid "Update {displayName} in Lists"
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:174
+msgid "Updating..."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:456
+msgid "Upload a text file to:"
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:148
+msgid "Use app passwords to login to other Bluesky clients without giving full access to your account or password."
+msgstr ""
+
+#: src/view/com/modals/ChangeHandle.tsx:516
+msgid "Use default provider"
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:37
+msgid "User handle"
+msgstr ""
+
+#: src/view/com/auth/login/LoginForm.tsx:168
+#: src/view/com/auth/login/LoginForm.tsx:185
+msgid "Username or email address"
+msgstr ""
+
+#: src/view/screens/ProfileList.tsx:694
+msgid "Users"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:650
+msgid "Verify email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:675
+msgid "Verify my email"
+msgstr ""
+
+#: src/view/screens/Settings.tsx:684
+msgid "Verify My Email"
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:205
+#: src/view/com/modals/ChangeEmail.tsx:207
+msgid "Verify New Email"
+msgstr ""
+
+#: src/view/screens/Log.tsx:53
+msgid "View debug entry"
+msgstr ""
+
+#: src/view/com/profile/ProfileSubpageHeader.tsx:127
+msgid "View the avatar"
+msgstr ""
+
+#: src/view/com/modals/LinkWarning.tsx:80
+msgid "Visit Site"
+msgstr ""
+
+#: src/view/com/auth/create/CreateAccount.tsx:78
+msgid "We're so excited to have you join us!"
+msgstr ""
+
+#: src/view/com/modals/report/Modal.tsx:168
+msgid "What is the issue with this {collectionName}?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:72
+msgid "Which languages are used in this post?"
+msgstr ""
+
+#: src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx:71
+msgid "Which languages would you like to see in your algorithmic feeds?"
+msgstr ""
+
+#: src/view/com/modals/crop-image/CropImage.web.tsx:102
+msgid "Wide"
+msgstr ""
+
+#: src/view/com/composer/Composer.tsx:390
+msgid "Write post"
+msgstr ""
+
+#: src/view/com/composer/Prompt.tsx:31
+msgid "Write your reply"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:122
+msgid "You can change hosting providers at any time."
+msgstr ""
+
+#: src/view/com/auth/login/PasswordUpdatedForm.tsx:31
+msgid "You can now sign in with your new password."
+msgstr ""
+
+#: src/view/com/post-thread/PostThread.tsx:346
+msgid "You have blocked the author or you have been blocked by the author."
+msgstr ""
+
+#: src/view/com/lists/ListsList.tsx:112
+msgid "You have no lists."
+msgstr ""
+
+#: src/view/screens/AppPasswords.tsx:55
+msgid "You have not created any app passwords yet. You can create one by pressing the button below."
+msgstr ""
+
+#: src/view/com/auth/login/SetNewPasswordForm.tsx:83
+msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:42
+msgid "Your account"
+msgstr ""
+
+#: src/view/com/auth/create/Step2.tsx:121
+msgid "Your birth date"
+msgstr ""
+
+#: src/view/com/modals/Waitlist.tsx:107
+msgid "Your email has been saved! We'll be in touch soon."
+msgstr ""
+
+#: src/view/com/modals/ChangeEmail.tsx:125
+msgid "Your email has been updated but not verified. As a next step, please verify your new email."
+msgstr ""
+
+#: src/view/com/modals/VerifyEmail.tsx:102
+msgid "Your email has not yet been verified. This is an important security step which we recommend."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:41
+#: src/view/com/modals/ChangeHandle.tsx:275
+msgid "Your full handle will be"
+msgstr ""
+
+#: src/view/com/auth/create/Step1.tsx:69
+msgid "Your hosting provider"
+msgstr ""
+
+#: src/view/com/auth/onboarding/WelcomeMobile.tsx:63
+msgid "Your posts, likes, and blocks are public. Mutes are private."
+msgstr ""
+
+#: src/view/com/auth/create/Step3.tsx:27
+msgid "Your user handle"
+msgstr ""
diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx
index 67453f111..05e72a2e6 100644
--- a/src/view/com/auth/SplashScreen.tsx
+++ b/src/view/com/auth/SplashScreen.tsx
@@ -5,6 +5,8 @@ import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
 import {s, colors} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {CenteredView} from '../util/Views'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const SplashScreen = ({
   onPressSignin,
@@ -14,14 +16,18 @@ export const SplashScreen = ({
   onPressCreateAccount: () => void
 }) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
+
   return (
     <CenteredView style={[styles.container, pal.view]}>
       <SafeAreaView testID="noSessionView" style={styles.container}>
         <ErrorBoundary>
           <View style={styles.hero}>
-            <Text style={[styles.title, pal.link]}>Bluesky</Text>
+            <Text style={[styles.title, pal.link]}>
+              <Trans>Bluesky</Trans>
+            </Text>
             <Text style={[styles.subtitle, pal.textLight]}>
-              See what's next
+              <Trans>See what's next</Trans>
             </Text>
           </View>
           <View testID="signinOrCreateAccount" style={styles.btns}>
@@ -30,10 +36,10 @@ export const SplashScreen = ({
               style={[styles.btn, {backgroundColor: colors.blue3}]}
               onPress={onPressCreateAccount}
               accessibilityRole="button"
-              accessibilityLabel="Create new account"
+              accessibilityLabel={_(msg`Create new account`)}
               accessibilityHint="Opens flow to create a new Bluesky account">
               <Text style={[s.white, styles.btnLabel]}>
-                Create a new account
+                <Trans>Create a new account</Trans>
               </Text>
             </TouchableOpacity>
             <TouchableOpacity
@@ -41,9 +47,11 @@ export const SplashScreen = ({
               style={[styles.btn, pal.btn]}
               onPress={onPressSignin}
               accessibilityRole="button"
-              accessibilityLabel="Sign in"
+              accessibilityLabel={_(msg`Sign in`)}
               accessibilityHint="Opens flow to sign into your existing Bluesky account">
-              <Text style={[pal.text, styles.btnLabel]}>Sign In</Text>
+              <Text style={[pal.text, styles.btnLabel]}>
+                <Trans>Sign In</Trans>
+              </Text>
             </TouchableOpacity>
           </View>
         </ErrorBoundary>
diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx
index cef9618ef..f10dc4f98 100644
--- a/src/view/com/auth/SplashScreen.web.tsx
+++ b/src/view/com/auth/SplashScreen.web.tsx
@@ -8,6 +8,7 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {CenteredView} from '../util/Views'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans} from '@lingui/macro'
 
 export const SplashScreen = ({
   onPressSignin,
@@ -54,7 +55,9 @@ export const SplashScreen = ({
               onPress={onPressSignin}
               // TODO: web accessibility
               accessibilityRole="button">
-              <Text style={[pal.text, styles.btnLabel]}>Sign In</Text>
+              <Text style={[pal.text, styles.btnLabel]}>
+                <Trans>Sign In</Trans>
+              </Text>
             </TouchableOpacity>
           </View>
         </ErrorBoundary>
diff --git a/src/view/com/auth/create/CreateAccount.tsx b/src/view/com/auth/create/CreateAccount.tsx
index c3cfb3ad3..8e2bbed85 100644
--- a/src/view/com/auth/create/CreateAccount.tsx
+++ b/src/view/com/auth/create/CreateAccount.tsx
@@ -15,6 +15,8 @@ import {s} from 'lib/styles'
 import {useStores} from 'state/index'
 import {CreateAccountModel} from 'state/models/ui/create-account'
 import {usePalette} from 'lib/hooks/usePalette'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useOnboardingDispatch} from '#/state/shell'
 
 import {Step1} from './Step1'
@@ -30,6 +32,7 @@ export const CreateAccount = observer(function CreateAccountImpl({
   const pal = usePalette('default')
   const store = useStores()
   const model = React.useMemo(() => new CreateAccountModel(store), [store])
+  const {_} = useLingui()
   const onboardingDispatch = useOnboardingDispatch()
 
   React.useEffect(() => {
@@ -73,8 +76,8 @@ export const CreateAccount = observer(function CreateAccountImpl({
   return (
     <LoggedOutLayout
       leadin={`Step ${model.step}`}
-      title="Create Account"
-      description="We're so excited to have you join us!">
+      title={_(msg`Create Account`)}
+      description={_(msg`We're so excited to have you join us!`)}>
       <ScrollView testID="createAccount" style={pal.view}>
         <KeyboardAvoidingView behavior="padding">
           <View style={styles.stepContainer}>
@@ -88,7 +91,7 @@ export const CreateAccount = observer(function CreateAccountImpl({
               testID="backBtn"
               accessibilityRole="button">
               <Text type="xl" style={pal.link}>
-                Back
+                <Trans>Back</Trans>
               </Text>
             </TouchableOpacity>
             <View style={s.flex1} />
@@ -101,7 +104,7 @@ export const CreateAccount = observer(function CreateAccountImpl({
                   <ActivityIndicator />
                 ) : (
                   <Text type="xl-bold" style={[pal.link, s.pr5]}>
-                    Next
+                    <Trans>Next</Trans>
                   </Text>
                 )}
               </TouchableOpacity>
@@ -110,18 +113,18 @@ export const CreateAccount = observer(function CreateAccountImpl({
                 testID="retryConnectBtn"
                 onPress={onPressRetryConnect}
                 accessibilityRole="button"
-                accessibilityLabel="Retry"
+                accessibilityLabel={_(msg`Retry`)}
                 accessibilityHint="Retries account creation"
                 accessibilityLiveRegion="polite">
                 <Text type="xl-bold" style={[pal.link, s.pr5]}>
-                  Retry
+                  <Trans>Retry</Trans>
                 </Text>
               </TouchableOpacity>
             ) : model.isFetchingServiceDescription ? (
               <>
                 <ActivityIndicator color="#fff" />
                 <Text type="xl" style={[pal.text, s.pr5]}>
-                  Connecting...
+                  <Trans>Connecting...</Trans>
                 </Text>
               </>
             ) : undefined}
diff --git a/src/view/com/auth/create/Step1.tsx b/src/view/com/auth/create/Step1.tsx
index cdd5cb21d..7e3ea062d 100644
--- a/src/view/com/auth/create/Step1.tsx
+++ b/src/view/com/auth/create/Step1.tsx
@@ -12,6 +12,8 @@ import {HelpTip} from '../util/HelpTip'
 import {TextInput} from '../util/TextInput'
 import {Button} from 'view/com/util/forms/Button'
 import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 import {LOCAL_DEV_SERVICE, STAGING_SERVICE, PROD_SERVICE} from 'state/index'
 import {LOGIN_INCLUDE_DEV_SERVERS} from 'lib/build-flags'
@@ -27,6 +29,7 @@ export const Step1 = observer(function Step1Impl({
 }) {
   const pal = usePalette('default')
   const [isDefaultSelected, setIsDefaultSelected] = React.useState(true)
+  const {_} = useLingui()
 
   const onPressDefault = React.useCallback(() => {
     setIsDefaultSelected(true)
@@ -63,9 +66,9 @@ export const Step1 = observer(function Step1Impl({
 
   return (
     <View>
-      <StepHeader step="1" title="Your hosting provider" />
+      <StepHeader step="1" title={_(msg`Your hosting provider`)} />
       <Text style={[pal.text, s.mb10]}>
-        This is the service that keeps you online.
+        <Trans>This is the service that keeps you online.</Trans>
       </Text>
       <Option
         testID="blueskyServerBtn"
@@ -81,17 +84,17 @@ export const Step1 = observer(function Step1Impl({
         onPress={onPressOther}>
         <View style={styles.otherForm}>
           <Text nativeID="addressProvider" style={[pal.text, s.mb5]}>
-            Enter the address of your provider:
+            <Trans>Enter the address of your provider:</Trans>
           </Text>
           <TextInput
             testID="customServerInput"
             icon="globe"
-            placeholder="Hosting provider address"
+            placeholder={_(msg`Hosting provider address`)}
             value={model.serviceUrl}
             editable
             onChange={onChangeServiceUrl}
             accessibilityHint="Input hosting provider address"
-            accessibilityLabel="Hosting provider address"
+            accessibilityLabel={_(msg`Hosting provider address`)}
             accessibilityLabelledBy="addressProvider"
           />
           {LOGIN_INCLUDE_DEV_SERVERS && (
@@ -100,13 +103,13 @@ export const Step1 = observer(function Step1Impl({
                 testID="stagingServerBtn"
                 type="default"
                 style={s.mr5}
-                label="Staging"
+                label={_(msg`Staging`)}
                 onPress={() => onDebugChangeServiceUrl(STAGING_SERVICE)}
               />
               <Button
                 testID="localDevServerBtn"
                 type="default"
-                label="Dev Server"
+                label={_(msg`Dev Server`)}
                 onPress={() => onDebugChangeServiceUrl(LOCAL_DEV_SERVICE)}
               />
             </View>
@@ -116,7 +119,7 @@ export const Step1 = observer(function Step1Impl({
       {model.error ? (
         <ErrorMessage message={model.error} style={styles.error} />
       ) : (
-        <HelpTip text="You can change hosting providers at any time." />
+        <HelpTip text={_(msg`You can change hosting providers at any time.`)} />
       )}
     </View>
   )
diff --git a/src/view/com/auth/create/Step2.tsx b/src/view/com/auth/create/Step2.tsx
index b2054150b..3cc8ae934 100644
--- a/src/view/com/auth/create/Step2.tsx
+++ b/src/view/com/auth/create/Step2.tsx
@@ -11,6 +11,8 @@ import {TextInput} from '../util/TextInput'
 import {Policies} from './Policies'
 import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
 import {isWeb} from 'platform/detection'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 /** STEP 2: Your account
@@ -28,6 +30,7 @@ export const Step2 = observer(function Step2Impl({
   model: CreateAccountModel
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {openModal} = useModalControls()
 
   const onPressWaitlist = React.useCallback(() => {
@@ -36,7 +39,7 @@ export const Step2 = observer(function Step2Impl({
 
   return (
     <View>
-      <StepHeader step="2" title="Your account" />
+      <StepHeader step="2" title={_(msg`Your account`)} />
 
       {model.isInviteCodeRequired && (
         <View style={s.pb20}>
@@ -46,11 +49,11 @@ export const Step2 = observer(function Step2Impl({
           <TextInput
             testID="inviteCodeInput"
             icon="ticket"
-            placeholder="Required for this provider"
+            placeholder={_(msg`Required for this provider`)}
             value={model.inviteCode}
             editable
             onChange={model.setInviteCode}
-            accessibilityLabel="Invite code"
+            accessibilityLabel={_(msg`Invite code`)}
             accessibilityHint="Input invite code to proceed"
           />
         </View>
@@ -61,10 +64,12 @@ export const Step2 = observer(function Step2Impl({
           Don't have an invite code?{' '}
           <TouchableWithoutFeedback
             onPress={onPressWaitlist}
-            accessibilityLabel="Join the waitlist."
+            accessibilityLabel={_(msg`Join the waitlist.`)}
             accessibilityHint="">
             <View style={styles.touchable}>
-              <Text style={pal.link}>Join the waitlist.</Text>
+              <Text style={pal.link}>
+                <Trans>Join the waitlist.</Trans>
+              </Text>
             </View>
           </TouchableWithoutFeedback>
         </Text>
@@ -72,16 +77,16 @@ export const Step2 = observer(function Step2Impl({
         <>
           <View style={s.pb20}>
             <Text type="md-medium" style={[pal.text, s.mb2]} nativeID="email">
-              Email address
+              <Trans>Email address</Trans>
             </Text>
             <TextInput
               testID="emailInput"
               icon="envelope"
-              placeholder="Enter your email address"
+              placeholder={_(msg`Enter your email address`)}
               value={model.email}
               editable
               onChange={model.setEmail}
-              accessibilityLabel="Email"
+              accessibilityLabel={_(msg`Email`)}
               accessibilityHint="Input email for Bluesky waitlist"
               accessibilityLabelledBy="email"
             />
@@ -92,17 +97,17 @@ export const Step2 = observer(function Step2Impl({
               type="md-medium"
               style={[pal.text, s.mb2]}
               nativeID="password">
-              Password
+              <Trans>Password</Trans>
             </Text>
             <TextInput
               testID="passwordInput"
               icon="lock"
-              placeholder="Choose your password"
+              placeholder={_(msg`Choose your password`)}
               value={model.password}
               editable
               secureTextEntry
               onChange={model.setPassword}
-              accessibilityLabel="Password"
+              accessibilityLabel={_(msg`Password`)}
               accessibilityHint="Set password"
               accessibilityLabelledBy="password"
             />
@@ -113,7 +118,7 @@ export const Step2 = observer(function Step2Impl({
               type="md-medium"
               style={[pal.text, s.mb2]}
               nativeID="birthDate">
-              Your birth date
+              <Trans>Your birth date</Trans>
             </Text>
             <DateInput
               testID="birthdayInput"
@@ -122,7 +127,7 @@ export const Step2 = observer(function Step2Impl({
               buttonType="default-light"
               buttonStyle={[pal.border, styles.dateInputButton]}
               buttonLabelType="lg"
-              accessibilityLabel="Birthday"
+              accessibilityLabel={_(msg`Birthday`)}
               accessibilityHint="Enter your birth date"
               accessibilityLabelledBy="birthDate"
             />
diff --git a/src/view/com/auth/create/Step3.tsx b/src/view/com/auth/create/Step3.tsx
index beb756ac1..09fba0714 100644
--- a/src/view/com/auth/create/Step3.tsx
+++ b/src/view/com/auth/create/Step3.tsx
@@ -9,6 +9,8 @@ import {TextInput} from '../util/TextInput'
 import {createFullHandle} from 'lib/strings/handles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 /** STEP 3: Your user handle
  * @field User handle
@@ -19,9 +21,10 @@ export const Step3 = observer(function Step3Impl({
   model: CreateAccountModel
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   return (
     <View>
-      <StepHeader step="3" title="Your user handle" />
+      <StepHeader step="3" title={_(msg`Your user handle`)} />
       <View style={s.pb10}>
         <TextInput
           testID="handleInput"
@@ -31,12 +34,12 @@ export const Step3 = observer(function Step3Impl({
           editable
           onChange={model.setHandle}
           // TODO: Add explicit text label
-          accessibilityLabel="User handle"
+          accessibilityLabel={_(msg`User handle`)}
           accessibilityHint="Input your user handle"
         />
         <Text type="lg" style={[pal.text, s.pl5, s.pt10]}>
-          Your full handle will be{' '}
-          <Text type="lg-bold" style={pal.text}>
+          <Trans>Your full handle will be</Trans>
+          <Text type="lg-bold" style={[pal.text, s.ml5]}>
             @{createFullHandle(model.handle, model.userDomain)}
           </Text>
         </Text>
diff --git a/src/view/com/auth/login/ChooseAccountForm.tsx b/src/view/com/auth/login/ChooseAccountForm.tsx
new file mode 100644
index 000000000..596a8e411
--- /dev/null
+++ b/src/view/com/auth/login/ChooseAccountForm.tsx
@@ -0,0 +1,119 @@
+import React from 'react'
+import {
+  ActivityIndicator,
+  ScrollView,
+  TouchableOpacity,
+  View,
+} from 'react-native'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {Text} from '../../util/text/Text'
+import {UserAvatar} from '../../util/UserAvatar'
+import {s} from 'lib/styles'
+import {RootStoreModel} from 'state/index'
+import {AccountData} from 'state/models/session'
+import {usePalette} from 'lib/hooks/usePalette'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {styles} from './styles'
+
+export const ChooseAccountForm = ({
+  store,
+  onSelectAccount,
+  onPressBack,
+}: {
+  store: RootStoreModel
+  onSelectAccount: (account?: AccountData) => void
+  onPressBack: () => void
+}) => {
+  const {track, screen} = useAnalytics()
+  const pal = usePalette('default')
+  const [isProcessing, setIsProcessing] = React.useState(false)
+  const {_} = useLingui()
+
+  React.useEffect(() => {
+    screen('Choose Account')
+  }, [screen])
+
+  const onTryAccount = async (account: AccountData) => {
+    if (account.accessJwt && account.refreshJwt) {
+      setIsProcessing(true)
+      if (await store.session.resumeSession(account)) {
+        track('Sign In', {resumedSession: true})
+        setIsProcessing(false)
+        return
+      }
+      setIsProcessing(false)
+    }
+    onSelectAccount(account)
+  }
+
+  return (
+    <ScrollView testID="chooseAccountForm" style={styles.maxHeight}>
+      <Text
+        type="2xl-medium"
+        style={[pal.text, styles.groupLabel, s.mt5, s.mb10]}>
+        <Trans>Sign in as...</Trans>
+      </Text>
+      {store.session.accounts.map(account => (
+        <TouchableOpacity
+          testID={`chooseAccountBtn-${account.handle}`}
+          key={account.did}
+          style={[pal.view, pal.border, styles.account]}
+          onPress={() => onTryAccount(account)}
+          accessibilityRole="button"
+          accessibilityLabel={_(msg`Sign in as ${account.handle}`)}
+          accessibilityHint="Double tap to sign in">
+          <View
+            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
+            <View style={s.p10}>
+              <UserAvatar avatar={account.aviUrl} size={30} />
+            </View>
+            <Text style={styles.accountText}>
+              <Text type="lg-bold" style={pal.text}>
+                {account.displayName || account.handle}{' '}
+              </Text>
+              <Text type="lg" style={[pal.textLight]}>
+                {account.handle}
+              </Text>
+            </Text>
+            <FontAwesomeIcon
+              icon="angle-right"
+              size={16}
+              style={[pal.text, s.mr10]}
+            />
+          </View>
+        </TouchableOpacity>
+      ))}
+      <TouchableOpacity
+        testID="chooseNewAccountBtn"
+        style={[pal.view, pal.border, styles.account, styles.accountLast]}
+        onPress={() => onSelectAccount(undefined)}
+        accessibilityRole="button"
+        accessibilityLabel={_(msg`Login to account that is not listed`)}
+        accessibilityHint="">
+        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
+          <Text style={[styles.accountText, styles.accountTextOther]}>
+            <Text type="lg" style={pal.text}>
+              <Trans>Other account</Trans>
+            </Text>
+          </Text>
+          <FontAwesomeIcon
+            icon="angle-right"
+            size={16}
+            style={[pal.text, s.mr10]}
+          />
+        </View>
+      </TouchableOpacity>
+      <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
+        <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
+          <Text type="xl" style={[pal.link, s.pl5]}>
+            <Trans>Back</Trans>
+          </Text>
+        </TouchableOpacity>
+        <View style={s.flex1} />
+        {isProcessing && <ActivityIndicator />}
+      </View>
+    </ScrollView>
+  )
+}
diff --git a/src/view/com/auth/login/ForgotPasswordForm.tsx b/src/view/com/auth/login/ForgotPasswordForm.tsx
new file mode 100644
index 000000000..9bfab18b5
--- /dev/null
+++ b/src/view/com/auth/login/ForgotPasswordForm.tsx
@@ -0,0 +1,197 @@
+import React, {useState, useEffect} from 'react'
+import {
+  ActivityIndicator,
+  TextInput,
+  TouchableOpacity,
+  View,
+} from 'react-native'
+import {
+  FontAwesomeIcon,
+  FontAwesomeIconStyle,
+} from '@fortawesome/react-native-fontawesome'
+import * as EmailValidator from 'email-validator'
+import {BskyAgent} from '@atproto/api'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {Text} from '../../util/text/Text'
+import {s} from 'lib/styles'
+import {toNiceDomain} from 'lib/strings/url-helpers'
+import {RootStoreModel} from 'state/index'
+import {ServiceDescription} from 'state/models/session'
+import {isNetworkError} from 'lib/strings/errors'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useTheme} from 'lib/ThemeContext'
+import {cleanError} from 'lib/strings/errors'
+import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {styles} from './styles'
+import {useModalControls} from '#/state/modals'
+
+export const ForgotPasswordForm = ({
+  error,
+  serviceUrl,
+  serviceDescription,
+  setError,
+  setServiceUrl,
+  onPressBack,
+  onEmailSent,
+}: {
+  store: RootStoreModel
+  error: string
+  serviceUrl: string
+  serviceDescription: ServiceDescription | undefined
+  setError: (v: string) => void
+  setServiceUrl: (v: string) => void
+  onPressBack: () => void
+  onEmailSent: () => void
+}) => {
+  const pal = usePalette('default')
+  const theme = useTheme()
+  const [isProcessing, setIsProcessing] = useState<boolean>(false)
+  const [email, setEmail] = useState<string>('')
+  const {screen} = useAnalytics()
+  const {_} = useLingui()
+  const {openModal} = useModalControls()
+
+  useEffect(() => {
+    screen('Signin:ForgotPassword')
+  }, [screen])
+
+  const onPressSelectService = () => {
+    openModal({
+      name: 'server-input',
+      initialService: serviceUrl,
+      onSelect: setServiceUrl,
+    })
+  }
+
+  const onPressNext = async () => {
+    if (!EmailValidator.validate(email)) {
+      return setError('Your email appears to be invalid.')
+    }
+
+    setError('')
+    setIsProcessing(true)
+
+    try {
+      const agent = new BskyAgent({service: serviceUrl})
+      await agent.com.atproto.server.requestPasswordReset({email})
+      onEmailSent()
+    } catch (e: any) {
+      const errMsg = e.toString()
+      logger.warn('Failed to request password reset', {error: e})
+      setIsProcessing(false)
+      if (isNetworkError(e)) {
+        setError(
+          'Unable to contact your service. Please check your Internet connection.',
+        )
+      } else {
+        setError(cleanError(errMsg))
+      }
+    }
+  }
+
+  return (
+    <>
+      <View>
+        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
+          <Trans>Reset password</Trans>
+        </Text>
+        <Text type="md" style={[pal.text, styles.instructions]}>
+          <Trans>
+            Enter the email you used to create your account. We'll send you a
+            "reset code" so you can set a new password.
+          </Trans>
+        </Text>
+        <View
+          testID="forgotPasswordView"
+          style={[pal.borderDark, pal.view, styles.group]}>
+          <TouchableOpacity
+            testID="forgotPasswordSelectServiceButton"
+            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}
+            onPress={onPressSelectService}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Hosting provider`)}
+            accessibilityHint="Sets hosting provider for password reset">
+            <FontAwesomeIcon
+              icon="globe"
+              style={[pal.textLight, styles.groupContentIcon]}
+            />
+            <Text style={[pal.text, styles.textInput]} numberOfLines={1}>
+              {toNiceDomain(serviceUrl)}
+            </Text>
+            <View style={[pal.btn, styles.textBtnFakeInnerBtn]}>
+              <FontAwesomeIcon
+                icon="pen"
+                size={12}
+                style={pal.text as FontAwesomeIconStyle}
+              />
+            </View>
+          </TouchableOpacity>
+          <View style={[pal.borderDark, styles.groupContent]}>
+            <FontAwesomeIcon
+              icon="envelope"
+              style={[pal.textLight, styles.groupContentIcon]}
+            />
+            <TextInput
+              testID="forgotPasswordEmail"
+              style={[pal.text, styles.textInput]}
+              placeholder="Email address"
+              placeholderTextColor={pal.colors.textLight}
+              autoCapitalize="none"
+              autoFocus
+              autoCorrect={false}
+              keyboardAppearance={theme.colorScheme}
+              value={email}
+              onChangeText={setEmail}
+              editable={!isProcessing}
+              accessibilityLabel={_(msg`Email`)}
+              accessibilityHint="Sets email for password reset"
+            />
+          </View>
+        </View>
+        {error ? (
+          <View style={styles.error}>
+            <View style={styles.errorIcon}>
+              <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
+            </View>
+            <View style={s.flex1}>
+              <Text style={[s.white, s.bold]}>{error}</Text>
+            </View>
+          </View>
+        ) : undefined}
+        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
+          <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
+            <Text type="xl" style={[pal.link, s.pl5]}>
+              <Trans>Back</Trans>
+            </Text>
+          </TouchableOpacity>
+          <View style={s.flex1} />
+          {!serviceDescription || isProcessing ? (
+            <ActivityIndicator />
+          ) : !email ? (
+            <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
+              <Trans>Next</Trans>
+            </Text>
+          ) : (
+            <TouchableOpacity
+              testID="newPasswordButton"
+              onPress={onPressNext}
+              accessibilityRole="button"
+              accessibilityLabel={_(msg`Go to next`)}
+              accessibilityHint="Navigates to the next screen">
+              <Text type="xl-bold" style={[pal.link, s.pr5]}>
+                <Trans>Next</Trans>
+              </Text>
+            </TouchableOpacity>
+          )}
+          {!serviceDescription || isProcessing ? (
+            <Text type="xl" style={[pal.textLight, s.pl10]}>
+              <Trans>Processing...</Trans>
+            </Text>
+          ) : undefined}
+        </View>
+      </View>
+    </>
+  )
+}
diff --git a/src/view/com/auth/login/Login.tsx b/src/view/com/auth/login/Login.tsx
index 24a657c66..401b7d980 100644
--- a/src/view/com/auth/login/Login.tsx
+++ b/src/view/com/auth/login/Login.tsx
@@ -1,37 +1,19 @@
-import React, {useState, useEffect, useRef} from 'react'
-import {
-  ActivityIndicator,
-  Keyboard,
-  KeyboardAvoidingView,
-  ScrollView,
-  StyleSheet,
-  TextInput,
-  TouchableOpacity,
-  View,
-} from 'react-native'
-import {
-  FontAwesomeIcon,
-  FontAwesomeIconStyle,
-} from '@fortawesome/react-native-fontawesome'
-import * as EmailValidator from 'email-validator'
-import {BskyAgent} from '@atproto/api'
+import React, {useState, useEffect} from 'react'
+import {KeyboardAvoidingView} from 'react-native'
 import {useAnalytics} from 'lib/analytics/analytics'
-import {Text} from '../../util/text/Text'
-import {UserAvatar} from '../../util/UserAvatar'
 import {LoggedOutLayout} from 'view/com/util/layouts/LoggedOutLayout'
-import {s, colors} from 'lib/styles'
-import {createFullHandle} from 'lib/strings/handles'
-import {toNiceDomain} from 'lib/strings/url-helpers'
-import {useStores, RootStoreModel, DEFAULT_SERVICE} from 'state/index'
+import {useStores, DEFAULT_SERVICE} from 'state/index'
 import {ServiceDescription} from 'state/models/session'
 import {AccountData} from 'state/models/session'
-import {isNetworkError} from 'lib/strings/errors'
 import {usePalette} from 'lib/hooks/usePalette'
-import {useTheme} from 'lib/ThemeContext'
-import {cleanError} from 'lib/strings/errors'
-import {isWeb} from 'platform/detection'
 import {logger} from '#/logger'
-import {useModalControls} from '#/state/modals'
+import {ChooseAccountForm} from './ChooseAccountForm'
+import {LoginForm} from './LoginForm'
+import {ForgotPasswordForm} from './ForgotPasswordForm'
+import {SetNewPasswordForm} from './SetNewPasswordForm'
+import {PasswordUpdatedForm} from './PasswordUpdatedForm'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 enum Forms {
   Login,
@@ -45,6 +27,7 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
   const pal = usePalette('default')
   const store = useStores()
   const {track} = useAnalytics()
+  const {_} = useLingui()
   const [error, setError] = useState<string>('')
   const [retryDescribeTrigger, setRetryDescribeTrigger] = useState<any>({})
   const [serviceUrl, setServiceUrl] = useState<string>(DEFAULT_SERVICE)
@@ -87,14 +70,16 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
           error: err,
         })
         setError(
-          'Unable to contact your service. Please check your Internet connection.',
+          _(
+            msg`Unable to contact your service. Please check your Internet connection.`,
+          ),
         )
       },
     )
     return () => {
       aborted = true
     }
-  }, [store.session, serviceUrl, retryDescribeTrigger])
+  }, [store.session, serviceUrl, retryDescribeTrigger, _])
 
   const onPressRetryConnect = () => setRetryDescribeTrigger({})
   const onPressForgotPassword = () => {
@@ -107,8 +92,8 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
       {currentForm === Forms.Login ? (
         <LoggedOutLayout
           leadin=""
-          title="Sign in"
-          description="Enter your username and password">
+          title={_(msg`Sign in`)}
+          description={_(msg`Enter your username and password`)}>
           <LoginForm
             store={store}
             error={error}
@@ -126,8 +111,8 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
       {currentForm === Forms.ChooseAccount ? (
         <LoggedOutLayout
           leadin=""
-          title="Sign in as..."
-          description="Select from an existing account">
+          title={_(msg`Sign in as...`)}
+          description={_(msg`Select from an existing account`)}>
           <ChooseAccountForm
             store={store}
             onSelectAccount={onSelectAccount}
@@ -138,8 +123,8 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
       {currentForm === Forms.ForgotPassword ? (
         <LoggedOutLayout
           leadin=""
-          title="Forgot Password"
-          description="Let's get your password reset!">
+          title={_(msg`Forgot Password`)}
+          description={_(msg`Let's get your password reset!`)}>
           <ForgotPasswordForm
             store={store}
             error={error}
@@ -155,8 +140,8 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
       {currentForm === Forms.SetNewPassword ? (
         <LoggedOutLayout
           leadin=""
-          title="Forgot Password"
-          description="Let's get your password reset!">
+          title={_(msg`Forgot Password`)}
+          description={_(msg`Let's get your password reset!`)}>
           <SetNewPasswordForm
             store={store}
             error={error}
@@ -173,830 +158,3 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
     </KeyboardAvoidingView>
   )
 }
-
-const ChooseAccountForm = ({
-  store,
-  onSelectAccount,
-  onPressBack,
-}: {
-  store: RootStoreModel
-  onSelectAccount: (account?: AccountData) => void
-  onPressBack: () => void
-}) => {
-  const {track, screen} = useAnalytics()
-  const pal = usePalette('default')
-  const [isProcessing, setIsProcessing] = React.useState(false)
-
-  React.useEffect(() => {
-    screen('Choose Account')
-  }, [screen])
-
-  const onTryAccount = async (account: AccountData) => {
-    if (account.accessJwt && account.refreshJwt) {
-      setIsProcessing(true)
-      if (await store.session.resumeSession(account)) {
-        track('Sign In', {resumedSession: true})
-        setIsProcessing(false)
-        return
-      }
-      setIsProcessing(false)
-    }
-    onSelectAccount(account)
-  }
-
-  return (
-    <ScrollView testID="chooseAccountForm" style={styles.maxHeight}>
-      <Text
-        type="2xl-medium"
-        style={[pal.text, styles.groupLabel, s.mt5, s.mb10]}>
-        Sign in as...
-      </Text>
-      {store.session.accounts.map(account => (
-        <TouchableOpacity
-          testID={`chooseAccountBtn-${account.handle}`}
-          key={account.did}
-          style={[pal.view, pal.border, styles.account]}
-          onPress={() => onTryAccount(account)}
-          accessibilityRole="button"
-          accessibilityLabel={`Sign in as ${account.handle}`}
-          accessibilityHint="Double tap to sign in">
-          <View
-            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
-            <View style={s.p10}>
-              <UserAvatar avatar={account.aviUrl} size={30} />
-            </View>
-            <Text style={styles.accountText}>
-              <Text type="lg-bold" style={pal.text}>
-                {account.displayName || account.handle}{' '}
-              </Text>
-              <Text type="lg" style={[pal.textLight]}>
-                {account.handle}
-              </Text>
-            </Text>
-            <FontAwesomeIcon
-              icon="angle-right"
-              size={16}
-              style={[pal.text, s.mr10]}
-            />
-          </View>
-        </TouchableOpacity>
-      ))}
-      <TouchableOpacity
-        testID="chooseNewAccountBtn"
-        style={[pal.view, pal.border, styles.account, styles.accountLast]}
-        onPress={() => onSelectAccount(undefined)}
-        accessibilityRole="button"
-        accessibilityLabel="Login to account that is not listed"
-        accessibilityHint="">
-        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
-          <Text style={[styles.accountText, styles.accountTextOther]}>
-            <Text type="lg" style={pal.text}>
-              Other account
-            </Text>
-          </Text>
-          <FontAwesomeIcon
-            icon="angle-right"
-            size={16}
-            style={[pal.text, s.mr10]}
-          />
-        </View>
-      </TouchableOpacity>
-      <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
-        <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
-          <Text type="xl" style={[pal.link, s.pl5]}>
-            Back
-          </Text>
-        </TouchableOpacity>
-        <View style={s.flex1} />
-        {isProcessing && <ActivityIndicator />}
-      </View>
-    </ScrollView>
-  )
-}
-
-const LoginForm = ({
-  store,
-  error,
-  serviceUrl,
-  serviceDescription,
-  initialHandle,
-  setError,
-  setServiceUrl,
-  onPressRetryConnect,
-  onPressBack,
-  onPressForgotPassword,
-}: {
-  store: RootStoreModel
-  error: string
-  serviceUrl: string
-  serviceDescription: ServiceDescription | undefined
-  initialHandle: string
-  setError: (v: string) => void
-  setServiceUrl: (v: string) => void
-  onPressRetryConnect: () => void
-  onPressBack: () => void
-  onPressForgotPassword: () => void
-}) => {
-  const {track} = useAnalytics()
-  const pal = usePalette('default')
-  const theme = useTheme()
-  const [isProcessing, setIsProcessing] = useState<boolean>(false)
-  const [identifier, setIdentifier] = useState<string>(initialHandle)
-  const [password, setPassword] = useState<string>('')
-  const passwordInputRef = useRef<TextInput>(null)
-  const {openModal} = useModalControls()
-
-  const onPressSelectService = () => {
-    openModal({
-      name: 'server-input',
-      initialService: serviceUrl,
-      onSelect: setServiceUrl,
-    })
-    Keyboard.dismiss()
-    track('Signin:PressedSelectService')
-  }
-
-  const onPressNext = async () => {
-    Keyboard.dismiss()
-    setError('')
-    setIsProcessing(true)
-
-    try {
-      // try to guess the handle if the user just gave their own username
-      let fullIdent = identifier
-      if (
-        !identifier.includes('@') && // not an email
-        !identifier.includes('.') && // not a domain
-        serviceDescription &&
-        serviceDescription.availableUserDomains.length > 0
-      ) {
-        let matched = false
-        for (const domain of serviceDescription.availableUserDomains) {
-          if (fullIdent.endsWith(domain)) {
-            matched = true
-          }
-        }
-        if (!matched) {
-          fullIdent = createFullHandle(
-            identifier,
-            serviceDescription.availableUserDomains[0],
-          )
-        }
-      }
-
-      await store.session.login({
-        service: serviceUrl,
-        identifier: fullIdent,
-        password,
-      })
-    } catch (e: any) {
-      const errMsg = e.toString()
-      logger.warn('Failed to login', {error: e})
-      setIsProcessing(false)
-      if (errMsg.includes('Authentication Required')) {
-        setError('Invalid username or password')
-      } else if (isNetworkError(e)) {
-        setError(
-          'Unable to contact your service. Please check your Internet connection.',
-        )
-      } else {
-        setError(cleanError(errMsg))
-      }
-    } finally {
-      track('Sign In', {resumedSession: false})
-    }
-  }
-
-  const isReady = !!serviceDescription && !!identifier && !!password
-  return (
-    <View testID="loginForm">
-      <Text type="sm-bold" style={[pal.text, styles.groupLabel]}>
-        Sign into
-      </Text>
-      <View style={[pal.borderDark, styles.group]}>
-        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
-          <FontAwesomeIcon
-            icon="globe"
-            style={[pal.textLight, styles.groupContentIcon]}
-          />
-          <TouchableOpacity
-            testID="loginSelectServiceButton"
-            style={styles.textBtn}
-            onPress={onPressSelectService}
-            accessibilityRole="button"
-            accessibilityLabel="Select service"
-            accessibilityHint="Sets server for the Bluesky client">
-            <Text type="xl" style={[pal.text, styles.textBtnLabel]}>
-              {toNiceDomain(serviceUrl)}
-            </Text>
-            <View style={[pal.btn, styles.textBtnFakeInnerBtn]}>
-              <FontAwesomeIcon
-                icon="pen"
-                size={12}
-                style={pal.textLight as FontAwesomeIconStyle}
-              />
-            </View>
-          </TouchableOpacity>
-        </View>
-      </View>
-      <Text type="sm-bold" style={[pal.text, styles.groupLabel]}>
-        Account
-      </Text>
-      <View style={[pal.borderDark, styles.group]}>
-        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
-          <FontAwesomeIcon
-            icon="at"
-            style={[pal.textLight, styles.groupContentIcon]}
-          />
-          <TextInput
-            testID="loginUsernameInput"
-            style={[pal.text, styles.textInput]}
-            placeholder="Username or email address"
-            placeholderTextColor={pal.colors.textLight}
-            autoCapitalize="none"
-            autoFocus
-            autoCorrect={false}
-            autoComplete="username"
-            returnKeyType="next"
-            onSubmitEditing={() => {
-              passwordInputRef.current?.focus()
-            }}
-            blurOnSubmit={false} // prevents flickering due to onSubmitEditing going to next field
-            keyboardAppearance={theme.colorScheme}
-            value={identifier}
-            onChangeText={str =>
-              setIdentifier((str || '').toLowerCase().trim())
-            }
-            editable={!isProcessing}
-            accessibilityLabel="Username or email address"
-            accessibilityHint="Input the username or email address you used at signup"
-          />
-        </View>
-        <View style={[pal.borderDark, styles.groupContent]}>
-          <FontAwesomeIcon
-            icon="lock"
-            style={[pal.textLight, styles.groupContentIcon]}
-          />
-          <TextInput
-            testID="loginPasswordInput"
-            ref={passwordInputRef}
-            style={[pal.text, styles.textInput]}
-            placeholder="Password"
-            placeholderTextColor={pal.colors.textLight}
-            autoCapitalize="none"
-            autoCorrect={false}
-            autoComplete="password"
-            returnKeyType="done"
-            enablesReturnKeyAutomatically={true}
-            keyboardAppearance={theme.colorScheme}
-            secureTextEntry={true}
-            textContentType="password"
-            clearButtonMode="while-editing"
-            value={password}
-            onChangeText={setPassword}
-            onSubmitEditing={onPressNext}
-            blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing
-            editable={!isProcessing}
-            accessibilityLabel="Password"
-            accessibilityHint={
-              identifier === ''
-                ? 'Input your password'
-                : `Input the password tied to ${identifier}`
-            }
-          />
-          <TouchableOpacity
-            testID="forgotPasswordButton"
-            style={styles.textInputInnerBtn}
-            onPress={onPressForgotPassword}
-            accessibilityRole="button"
-            accessibilityLabel="Forgot password"
-            accessibilityHint="Opens password reset form">
-            <Text style={pal.link}>Forgot</Text>
-          </TouchableOpacity>
-        </View>
-      </View>
-      {error ? (
-        <View style={styles.error}>
-          <View style={styles.errorIcon}>
-            <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
-          </View>
-          <View style={s.flex1}>
-            <Text style={[s.white, s.bold]}>{error}</Text>
-          </View>
-        </View>
-      ) : undefined}
-      <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
-        <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
-          <Text type="xl" style={[pal.link, s.pl5]}>
-            Back
-          </Text>
-        </TouchableOpacity>
-        <View style={s.flex1} />
-        {!serviceDescription && error ? (
-          <TouchableOpacity
-            testID="loginRetryButton"
-            onPress={onPressRetryConnect}
-            accessibilityRole="button"
-            accessibilityLabel="Retry"
-            accessibilityHint="Retries login">
-            <Text type="xl-bold" style={[pal.link, s.pr5]}>
-              Retry
-            </Text>
-          </TouchableOpacity>
-        ) : !serviceDescription ? (
-          <>
-            <ActivityIndicator />
-            <Text type="xl" style={[pal.textLight, s.pl10]}>
-              Connecting...
-            </Text>
-          </>
-        ) : isProcessing ? (
-          <ActivityIndicator />
-        ) : isReady ? (
-          <TouchableOpacity
-            testID="loginNextButton"
-            onPress={onPressNext}
-            accessibilityRole="button"
-            accessibilityLabel="Go to next"
-            accessibilityHint="Navigates to the next screen">
-            <Text type="xl-bold" style={[pal.link, s.pr5]}>
-              Next
-            </Text>
-          </TouchableOpacity>
-        ) : undefined}
-      </View>
-    </View>
-  )
-}
-
-const ForgotPasswordForm = ({
-  error,
-  serviceUrl,
-  serviceDescription,
-  setError,
-  setServiceUrl,
-  onPressBack,
-  onEmailSent,
-}: {
-  store: RootStoreModel
-  error: string
-  serviceUrl: string
-  serviceDescription: ServiceDescription | undefined
-  setError: (v: string) => void
-  setServiceUrl: (v: string) => void
-  onPressBack: () => void
-  onEmailSent: () => void
-}) => {
-  const pal = usePalette('default')
-  const theme = useTheme()
-  const [isProcessing, setIsProcessing] = useState<boolean>(false)
-  const [email, setEmail] = useState<string>('')
-  const {screen} = useAnalytics()
-  const {openModal} = useModalControls()
-
-  useEffect(() => {
-    screen('Signin:ForgotPassword')
-  }, [screen])
-
-  const onPressSelectService = () => {
-    openModal({
-      name: 'server-input',
-      initialService: serviceUrl,
-      onSelect: setServiceUrl,
-    })
-  }
-
-  const onPressNext = async () => {
-    if (!EmailValidator.validate(email)) {
-      return setError('Your email appears to be invalid.')
-    }
-
-    setError('')
-    setIsProcessing(true)
-
-    try {
-      const agent = new BskyAgent({service: serviceUrl})
-      await agent.com.atproto.server.requestPasswordReset({email})
-      onEmailSent()
-    } catch (e: any) {
-      const errMsg = e.toString()
-      logger.warn('Failed to request password reset', {error: e})
-      setIsProcessing(false)
-      if (isNetworkError(e)) {
-        setError(
-          'Unable to contact your service. Please check your Internet connection.',
-        )
-      } else {
-        setError(cleanError(errMsg))
-      }
-    }
-  }
-
-  return (
-    <>
-      <View>
-        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
-          Reset password
-        </Text>
-        <Text type="md" style={[pal.text, styles.instructions]}>
-          Enter the email you used to create your account. We'll send you a
-          "reset code" so you can set a new password.
-        </Text>
-        <View
-          testID="forgotPasswordView"
-          style={[pal.borderDark, pal.view, styles.group]}>
-          <TouchableOpacity
-            testID="forgotPasswordSelectServiceButton"
-            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}
-            onPress={onPressSelectService}
-            accessibilityRole="button"
-            accessibilityLabel="Hosting provider"
-            accessibilityHint="Sets hosting provider for password reset">
-            <FontAwesomeIcon
-              icon="globe"
-              style={[pal.textLight, styles.groupContentIcon]}
-            />
-            <Text style={[pal.text, styles.textInput]} numberOfLines={1}>
-              {toNiceDomain(serviceUrl)}
-            </Text>
-            <View style={[pal.btn, styles.textBtnFakeInnerBtn]}>
-              <FontAwesomeIcon
-                icon="pen"
-                size={12}
-                style={pal.text as FontAwesomeIconStyle}
-              />
-            </View>
-          </TouchableOpacity>
-          <View style={[pal.borderDark, styles.groupContent]}>
-            <FontAwesomeIcon
-              icon="envelope"
-              style={[pal.textLight, styles.groupContentIcon]}
-            />
-            <TextInput
-              testID="forgotPasswordEmail"
-              style={[pal.text, styles.textInput]}
-              placeholder="Email address"
-              placeholderTextColor={pal.colors.textLight}
-              autoCapitalize="none"
-              autoFocus
-              autoCorrect={false}
-              keyboardAppearance={theme.colorScheme}
-              value={email}
-              onChangeText={setEmail}
-              editable={!isProcessing}
-              accessibilityLabel="Email"
-              accessibilityHint="Sets email for password reset"
-            />
-          </View>
-        </View>
-        {error ? (
-          <View style={styles.error}>
-            <View style={styles.errorIcon}>
-              <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
-            </View>
-            <View style={s.flex1}>
-              <Text style={[s.white, s.bold]}>{error}</Text>
-            </View>
-          </View>
-        ) : undefined}
-        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
-          <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
-            <Text type="xl" style={[pal.link, s.pl5]}>
-              Back
-            </Text>
-          </TouchableOpacity>
-          <View style={s.flex1} />
-          {!serviceDescription || isProcessing ? (
-            <ActivityIndicator />
-          ) : !email ? (
-            <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
-              Next
-            </Text>
-          ) : (
-            <TouchableOpacity
-              testID="newPasswordButton"
-              onPress={onPressNext}
-              accessibilityRole="button"
-              accessibilityLabel="Go to next"
-              accessibilityHint="Navigates to the next screen">
-              <Text type="xl-bold" style={[pal.link, s.pr5]}>
-                Next
-              </Text>
-            </TouchableOpacity>
-          )}
-          {!serviceDescription || isProcessing ? (
-            <Text type="xl" style={[pal.textLight, s.pl10]}>
-              Processing...
-            </Text>
-          ) : undefined}
-        </View>
-      </View>
-    </>
-  )
-}
-
-const SetNewPasswordForm = ({
-  error,
-  serviceUrl,
-  setError,
-  onPressBack,
-  onPasswordSet,
-}: {
-  store: RootStoreModel
-  error: string
-  serviceUrl: string
-  setError: (v: string) => void
-  onPressBack: () => void
-  onPasswordSet: () => void
-}) => {
-  const pal = usePalette('default')
-  const theme = useTheme()
-  const {screen} = useAnalytics()
-
-  useEffect(() => {
-    screen('Signin:SetNewPasswordForm')
-  }, [screen])
-
-  const [isProcessing, setIsProcessing] = useState<boolean>(false)
-  const [resetCode, setResetCode] = useState<string>('')
-  const [password, setPassword] = useState<string>('')
-
-  const onPressNext = async () => {
-    setError('')
-    setIsProcessing(true)
-
-    try {
-      const agent = new BskyAgent({service: serviceUrl})
-      const token = resetCode.replace(/\s/g, '')
-      await agent.com.atproto.server.resetPassword({
-        token,
-        password,
-      })
-      onPasswordSet()
-    } catch (e: any) {
-      const errMsg = e.toString()
-      logger.warn('Failed to set new password', {error: e})
-      setIsProcessing(false)
-      if (isNetworkError(e)) {
-        setError(
-          'Unable to contact your service. Please check your Internet connection.',
-        )
-      } else {
-        setError(cleanError(errMsg))
-      }
-    }
-  }
-
-  return (
-    <>
-      <View>
-        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
-          Set new password
-        </Text>
-        <Text type="lg" style={[pal.text, styles.instructions]}>
-          You will receive an email with a "reset code." Enter that code here,
-          then enter your new password.
-        </Text>
-        <View
-          testID="newPasswordView"
-          style={[pal.view, pal.borderDark, styles.group]}>
-          <View
-            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
-            <FontAwesomeIcon
-              icon="ticket"
-              style={[pal.textLight, styles.groupContentIcon]}
-            />
-            <TextInput
-              testID="resetCodeInput"
-              style={[pal.text, styles.textInput]}
-              placeholder="Reset code"
-              placeholderTextColor={pal.colors.textLight}
-              autoCapitalize="none"
-              autoCorrect={false}
-              keyboardAppearance={theme.colorScheme}
-              autoFocus
-              value={resetCode}
-              onChangeText={setResetCode}
-              editable={!isProcessing}
-              accessible={true}
-              accessibilityLabel="Reset code"
-              accessibilityHint="Input code sent to your email for password reset"
-            />
-          </View>
-          <View style={[pal.borderDark, styles.groupContent]}>
-            <FontAwesomeIcon
-              icon="lock"
-              style={[pal.textLight, styles.groupContentIcon]}
-            />
-            <TextInput
-              testID="newPasswordInput"
-              style={[pal.text, styles.textInput]}
-              placeholder="New password"
-              placeholderTextColor={pal.colors.textLight}
-              autoCapitalize="none"
-              autoCorrect={false}
-              keyboardAppearance={theme.colorScheme}
-              secureTextEntry
-              value={password}
-              onChangeText={setPassword}
-              editable={!isProcessing}
-              accessible={true}
-              accessibilityLabel="Password"
-              accessibilityHint="Input new password"
-            />
-          </View>
-        </View>
-        {error ? (
-          <View style={styles.error}>
-            <View style={styles.errorIcon}>
-              <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
-            </View>
-            <View style={s.flex1}>
-              <Text style={[s.white, s.bold]}>{error}</Text>
-            </View>
-          </View>
-        ) : undefined}
-        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
-          <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
-            <Text type="xl" style={[pal.link, s.pl5]}>
-              Back
-            </Text>
-          </TouchableOpacity>
-          <View style={s.flex1} />
-          {isProcessing ? (
-            <ActivityIndicator />
-          ) : !resetCode || !password ? (
-            <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
-              Next
-            </Text>
-          ) : (
-            <TouchableOpacity
-              testID="setNewPasswordButton"
-              onPress={onPressNext}
-              accessibilityRole="button"
-              accessibilityLabel="Go to next"
-              accessibilityHint="Navigates to the next screen">
-              <Text type="xl-bold" style={[pal.link, s.pr5]}>
-                Next
-              </Text>
-            </TouchableOpacity>
-          )}
-          {isProcessing ? (
-            <Text type="xl" style={[pal.textLight, s.pl10]}>
-              Updating...
-            </Text>
-          ) : undefined}
-        </View>
-      </View>
-    </>
-  )
-}
-
-const PasswordUpdatedForm = ({onPressNext}: {onPressNext: () => void}) => {
-  const {screen} = useAnalytics()
-
-  useEffect(() => {
-    screen('Signin:PasswordUpdatedForm')
-  }, [screen])
-
-  const pal = usePalette('default')
-  return (
-    <>
-      <View>
-        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
-          Password updated!
-        </Text>
-        <Text type="lg" style={[pal.text, styles.instructions]}>
-          You can now sign in with your new password.
-        </Text>
-        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
-          <View style={s.flex1} />
-          <TouchableOpacity
-            onPress={onPressNext}
-            accessibilityRole="button"
-            accessibilityLabel="Close alert"
-            accessibilityHint="Closes password update alert">
-            <Text type="xl-bold" style={[pal.link, s.pr5]}>
-              Okay
-            </Text>
-          </TouchableOpacity>
-        </View>
-      </View>
-    </>
-  )
-}
-
-const styles = StyleSheet.create({
-  screenTitle: {
-    marginBottom: 10,
-    marginHorizontal: 20,
-  },
-  instructions: {
-    marginBottom: 20,
-    marginHorizontal: 20,
-  },
-  group: {
-    borderWidth: 1,
-    borderRadius: 10,
-    marginBottom: 20,
-    marginHorizontal: 20,
-  },
-  groupLabel: {
-    paddingHorizontal: 20,
-    paddingBottom: 5,
-  },
-  groupContent: {
-    borderTopWidth: 1,
-    flexDirection: 'row',
-    alignItems: 'center',
-  },
-  noTopBorder: {
-    borderTopWidth: 0,
-  },
-  groupContentIcon: {
-    marginLeft: 10,
-  },
-  account: {
-    borderTopWidth: 1,
-    paddingHorizontal: 20,
-    paddingVertical: 4,
-  },
-  accountLast: {
-    borderBottomWidth: 1,
-    marginBottom: 20,
-    paddingVertical: 8,
-  },
-  textInput: {
-    flex: 1,
-    width: '100%',
-    paddingVertical: 10,
-    paddingHorizontal: 12,
-    fontSize: 17,
-    letterSpacing: 0.25,
-    fontWeight: '400',
-    borderRadius: 10,
-  },
-  textInputInnerBtn: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    paddingVertical: 6,
-    paddingHorizontal: 8,
-    marginHorizontal: 6,
-  },
-  textBtn: {
-    flexDirection: 'row',
-    flex: 1,
-    alignItems: 'center',
-  },
-  textBtnLabel: {
-    flex: 1,
-    paddingVertical: 10,
-    paddingHorizontal: 12,
-  },
-  textBtnFakeInnerBtn: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    borderRadius: 6,
-    paddingVertical: 6,
-    paddingHorizontal: 8,
-    marginHorizontal: 6,
-  },
-  accountText: {
-    flex: 1,
-    flexDirection: 'row',
-    alignItems: 'baseline',
-    paddingVertical: 10,
-  },
-  accountTextOther: {
-    paddingLeft: 12,
-  },
-  error: {
-    backgroundColor: colors.red4,
-    flexDirection: 'row',
-    alignItems: 'center',
-    marginTop: -5,
-    marginHorizontal: 20,
-    marginBottom: 15,
-    borderRadius: 8,
-    paddingHorizontal: 8,
-    paddingVertical: 8,
-  },
-  errorIcon: {
-    borderWidth: 1,
-    borderColor: colors.white,
-    color: colors.white,
-    borderRadius: 30,
-    width: 16,
-    height: 16,
-    alignItems: 'center',
-    justifyContent: 'center',
-    marginRight: 5,
-  },
-  dimmed: {opacity: 0.5},
-
-  maxHeight: {
-    // @ts-ignore web only -prf
-    maxHeight: isWeb ? '100vh' : undefined,
-    height: !isWeb ? '100%' : undefined,
-  },
-})
diff --git a/src/view/com/auth/login/LoginForm.tsx b/src/view/com/auth/login/LoginForm.tsx
new file mode 100644
index 000000000..9779b939a
--- /dev/null
+++ b/src/view/com/auth/login/LoginForm.tsx
@@ -0,0 +1,288 @@
+import React, {useState, useRef} from 'react'
+import {
+  ActivityIndicator,
+  Keyboard,
+  TextInput,
+  TouchableOpacity,
+  View,
+} from 'react-native'
+import {
+  FontAwesomeIcon,
+  FontAwesomeIconStyle,
+} from '@fortawesome/react-native-fontawesome'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {Text} from '../../util/text/Text'
+import {s} from 'lib/styles'
+import {createFullHandle} from 'lib/strings/handles'
+import {toNiceDomain} from 'lib/strings/url-helpers'
+import {RootStoreModel} from 'state/index'
+import {ServiceDescription} from 'state/models/session'
+import {isNetworkError} from 'lib/strings/errors'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useTheme} from 'lib/ThemeContext'
+import {cleanError} from 'lib/strings/errors'
+import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {styles} from './styles'
+import {useLingui} from '@lingui/react'
+import {useModalControls} from '#/state/modals'
+
+export const LoginForm = ({
+  store,
+  error,
+  serviceUrl,
+  serviceDescription,
+  initialHandle,
+  setError,
+  setServiceUrl,
+  onPressRetryConnect,
+  onPressBack,
+  onPressForgotPassword,
+}: {
+  store: RootStoreModel
+  error: string
+  serviceUrl: string
+  serviceDescription: ServiceDescription | undefined
+  initialHandle: string
+  setError: (v: string) => void
+  setServiceUrl: (v: string) => void
+  onPressRetryConnect: () => void
+  onPressBack: () => void
+  onPressForgotPassword: () => void
+}) => {
+  const {track} = useAnalytics()
+  const pal = usePalette('default')
+  const theme = useTheme()
+  const [isProcessing, setIsProcessing] = useState<boolean>(false)
+  const [identifier, setIdentifier] = useState<string>(initialHandle)
+  const [password, setPassword] = useState<string>('')
+  const passwordInputRef = useRef<TextInput>(null)
+  const {_} = useLingui()
+  const {openModal} = useModalControls()
+
+  const onPressSelectService = () => {
+    openModal({
+      name: 'server-input',
+      initialService: serviceUrl,
+      onSelect: setServiceUrl,
+    })
+    Keyboard.dismiss()
+    track('Signin:PressedSelectService')
+  }
+
+  const onPressNext = async () => {
+    Keyboard.dismiss()
+    setError('')
+    setIsProcessing(true)
+
+    try {
+      // try to guess the handle if the user just gave their own username
+      let fullIdent = identifier
+      if (
+        !identifier.includes('@') && // not an email
+        !identifier.includes('.') && // not a domain
+        serviceDescription &&
+        serviceDescription.availableUserDomains.length > 0
+      ) {
+        let matched = false
+        for (const domain of serviceDescription.availableUserDomains) {
+          if (fullIdent.endsWith(domain)) {
+            matched = true
+          }
+        }
+        if (!matched) {
+          fullIdent = createFullHandle(
+            identifier,
+            serviceDescription.availableUserDomains[0],
+          )
+        }
+      }
+
+      await store.session.login({
+        service: serviceUrl,
+        identifier: fullIdent,
+        password,
+      })
+    } catch (e: any) {
+      const errMsg = e.toString()
+      logger.warn('Failed to login', {error: e})
+      setIsProcessing(false)
+      if (errMsg.includes('Authentication Required')) {
+        setError(_(msg`Invalid username or password`))
+      } else if (isNetworkError(e)) {
+        setError(
+          _(
+            msg`Unable to contact your service. Please check your Internet connection.`,
+          ),
+        )
+      } else {
+        setError(cleanError(errMsg))
+      }
+    } finally {
+      track('Sign In', {resumedSession: false})
+    }
+  }
+
+  const isReady = !!serviceDescription && !!identifier && !!password
+  return (
+    <View testID="loginForm">
+      <Text type="sm-bold" style={[pal.text, styles.groupLabel]}>
+        <Trans>Sign into</Trans>
+      </Text>
+      <View style={[pal.borderDark, styles.group]}>
+        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
+          <FontAwesomeIcon
+            icon="globe"
+            style={[pal.textLight, styles.groupContentIcon]}
+          />
+          <TouchableOpacity
+            testID="loginSelectServiceButton"
+            style={styles.textBtn}
+            onPress={onPressSelectService}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Select service`)}
+            accessibilityHint="Sets server for the Bluesky client">
+            <Text type="xl" style={[pal.text, styles.textBtnLabel]}>
+              {toNiceDomain(serviceUrl)}
+            </Text>
+            <View style={[pal.btn, styles.textBtnFakeInnerBtn]}>
+              <FontAwesomeIcon
+                icon="pen"
+                size={12}
+                style={pal.textLight as FontAwesomeIconStyle}
+              />
+            </View>
+          </TouchableOpacity>
+        </View>
+      </View>
+      <Text type="sm-bold" style={[pal.text, styles.groupLabel]}>
+        <Trans>Account</Trans>
+      </Text>
+      <View style={[pal.borderDark, styles.group]}>
+        <View style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
+          <FontAwesomeIcon
+            icon="at"
+            style={[pal.textLight, styles.groupContentIcon]}
+          />
+          <TextInput
+            testID="loginUsernameInput"
+            style={[pal.text, styles.textInput]}
+            placeholder={_(msg`Username or email address`)}
+            placeholderTextColor={pal.colors.textLight}
+            autoCapitalize="none"
+            autoFocus
+            autoCorrect={false}
+            autoComplete="username"
+            returnKeyType="next"
+            onSubmitEditing={() => {
+              passwordInputRef.current?.focus()
+            }}
+            blurOnSubmit={false} // prevents flickering due to onSubmitEditing going to next field
+            keyboardAppearance={theme.colorScheme}
+            value={identifier}
+            onChangeText={str =>
+              setIdentifier((str || '').toLowerCase().trim())
+            }
+            editable={!isProcessing}
+            accessibilityLabel={_(msg`Username or email address`)}
+            accessibilityHint="Input the username or email address you used at signup"
+          />
+        </View>
+        <View style={[pal.borderDark, styles.groupContent]}>
+          <FontAwesomeIcon
+            icon="lock"
+            style={[pal.textLight, styles.groupContentIcon]}
+          />
+          <TextInput
+            testID="loginPasswordInput"
+            ref={passwordInputRef}
+            style={[pal.text, styles.textInput]}
+            placeholder="Password"
+            placeholderTextColor={pal.colors.textLight}
+            autoCapitalize="none"
+            autoCorrect={false}
+            autoComplete="password"
+            returnKeyType="done"
+            enablesReturnKeyAutomatically={true}
+            keyboardAppearance={theme.colorScheme}
+            secureTextEntry={true}
+            textContentType="password"
+            clearButtonMode="while-editing"
+            value={password}
+            onChangeText={setPassword}
+            onSubmitEditing={onPressNext}
+            blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing
+            editable={!isProcessing}
+            accessibilityLabel={_(msg`Password`)}
+            accessibilityHint={
+              identifier === ''
+                ? 'Input your password'
+                : `Input the password tied to ${identifier}`
+            }
+          />
+          <TouchableOpacity
+            testID="forgotPasswordButton"
+            style={styles.textInputInnerBtn}
+            onPress={onPressForgotPassword}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Forgot password`)}
+            accessibilityHint="Opens password reset form">
+            <Text style={pal.link}>
+              <Trans>Forgot</Trans>
+            </Text>
+          </TouchableOpacity>
+        </View>
+      </View>
+      {error ? (
+        <View style={styles.error}>
+          <View style={styles.errorIcon}>
+            <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
+          </View>
+          <View style={s.flex1}>
+            <Text style={[s.white, s.bold]}>{error}</Text>
+          </View>
+        </View>
+      ) : undefined}
+      <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
+        <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
+          <Text type="xl" style={[pal.link, s.pl5]}>
+            <Trans>Back</Trans>
+          </Text>
+        </TouchableOpacity>
+        <View style={s.flex1} />
+        {!serviceDescription && error ? (
+          <TouchableOpacity
+            testID="loginRetryButton"
+            onPress={onPressRetryConnect}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Retry`)}
+            accessibilityHint="Retries login">
+            <Text type="xl-bold" style={[pal.link, s.pr5]}>
+              <Trans>Retry</Trans>
+            </Text>
+          </TouchableOpacity>
+        ) : !serviceDescription ? (
+          <>
+            <ActivityIndicator />
+            <Text type="xl" style={[pal.textLight, s.pl10]}>
+              <Trans>Connecting...</Trans>
+            </Text>
+          </>
+        ) : isProcessing ? (
+          <ActivityIndicator />
+        ) : isReady ? (
+          <TouchableOpacity
+            testID="loginNextButton"
+            onPress={onPressNext}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Go to next`)}
+            accessibilityHint="Navigates to the next screen">
+            <Text type="xl-bold" style={[pal.link, s.pr5]}>
+              <Trans>Next</Trans>
+            </Text>
+          </TouchableOpacity>
+        ) : undefined}
+      </View>
+    </View>
+  )
+}
diff --git a/src/view/com/auth/login/PasswordUpdatedForm.tsx b/src/view/com/auth/login/PasswordUpdatedForm.tsx
new file mode 100644
index 000000000..1e07588a9
--- /dev/null
+++ b/src/view/com/auth/login/PasswordUpdatedForm.tsx
@@ -0,0 +1,48 @@
+import React, {useEffect} from 'react'
+import {TouchableOpacity, View} from 'react-native'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {Text} from '../../util/text/Text'
+import {s} from 'lib/styles'
+import {usePalette} from 'lib/hooks/usePalette'
+import {styles} from './styles'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+export const PasswordUpdatedForm = ({
+  onPressNext,
+}: {
+  onPressNext: () => void
+}) => {
+  const {screen} = useAnalytics()
+  const pal = usePalette('default')
+  const {_} = useLingui()
+
+  useEffect(() => {
+    screen('Signin:PasswordUpdatedForm')
+  }, [screen])
+
+  return (
+    <>
+      <View>
+        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
+          <Trans>Password updated!</Trans>
+        </Text>
+        <Text type="lg" style={[pal.text, styles.instructions]}>
+          <Trans>You can now sign in with your new password.</Trans>
+        </Text>
+        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
+          <View style={s.flex1} />
+          <TouchableOpacity
+            onPress={onPressNext}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Close alert`)}
+            accessibilityHint="Closes password update alert">
+            <Text type="xl-bold" style={[pal.link, s.pr5]}>
+              <Trans>Okay</Trans>
+            </Text>
+          </TouchableOpacity>
+        </View>
+      </View>
+    </>
+  )
+}
diff --git a/src/view/com/auth/login/SetNewPasswordForm.tsx b/src/view/com/auth/login/SetNewPasswordForm.tsx
new file mode 100644
index 000000000..04eaa2842
--- /dev/null
+++ b/src/view/com/auth/login/SetNewPasswordForm.tsx
@@ -0,0 +1,181 @@
+import React, {useState, useEffect} from 'react'
+import {
+  ActivityIndicator,
+  TextInput,
+  TouchableOpacity,
+  View,
+} from 'react-native'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {BskyAgent} from '@atproto/api'
+import {useAnalytics} from 'lib/analytics/analytics'
+import {Text} from '../../util/text/Text'
+import {s} from 'lib/styles'
+import {RootStoreModel} from 'state/index'
+import {isNetworkError} from 'lib/strings/errors'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useTheme} from 'lib/ThemeContext'
+import {cleanError} from 'lib/strings/errors'
+import {logger} from '#/logger'
+import {styles} from './styles'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+export const SetNewPasswordForm = ({
+  error,
+  serviceUrl,
+  setError,
+  onPressBack,
+  onPasswordSet,
+}: {
+  store: RootStoreModel
+  error: string
+  serviceUrl: string
+  setError: (v: string) => void
+  onPressBack: () => void
+  onPasswordSet: () => void
+}) => {
+  const pal = usePalette('default')
+  const theme = useTheme()
+  const {screen} = useAnalytics()
+  const {_} = useLingui()
+
+  useEffect(() => {
+    screen('Signin:SetNewPasswordForm')
+  }, [screen])
+
+  const [isProcessing, setIsProcessing] = useState<boolean>(false)
+  const [resetCode, setResetCode] = useState<string>('')
+  const [password, setPassword] = useState<string>('')
+
+  const onPressNext = async () => {
+    setError('')
+    setIsProcessing(true)
+
+    try {
+      const agent = new BskyAgent({service: serviceUrl})
+      const token = resetCode.replace(/\s/g, '')
+      await agent.com.atproto.server.resetPassword({
+        token,
+        password,
+      })
+      onPasswordSet()
+    } catch (e: any) {
+      const errMsg = e.toString()
+      logger.warn('Failed to set new password', {error: e})
+      setIsProcessing(false)
+      if (isNetworkError(e)) {
+        setError(
+          'Unable to contact your service. Please check your Internet connection.',
+        )
+      } else {
+        setError(cleanError(errMsg))
+      }
+    }
+  }
+
+  return (
+    <>
+      <View>
+        <Text type="title-lg" style={[pal.text, styles.screenTitle]}>
+          <Trans>Set new password</Trans>
+        </Text>
+        <Text type="lg" style={[pal.text, styles.instructions]}>
+          <Trans>
+            You will receive an email with a "reset code." Enter that code here,
+            then enter your new password.
+          </Trans>
+        </Text>
+        <View
+          testID="newPasswordView"
+          style={[pal.view, pal.borderDark, styles.group]}>
+          <View
+            style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
+            <FontAwesomeIcon
+              icon="ticket"
+              style={[pal.textLight, styles.groupContentIcon]}
+            />
+            <TextInput
+              testID="resetCodeInput"
+              style={[pal.text, styles.textInput]}
+              placeholder="Reset code"
+              placeholderTextColor={pal.colors.textLight}
+              autoCapitalize="none"
+              autoCorrect={false}
+              keyboardAppearance={theme.colorScheme}
+              autoFocus
+              value={resetCode}
+              onChangeText={setResetCode}
+              editable={!isProcessing}
+              accessible={true}
+              accessibilityLabel={_(msg`Reset code`)}
+              accessibilityHint="Input code sent to your email for password reset"
+            />
+          </View>
+          <View style={[pal.borderDark, styles.groupContent]}>
+            <FontAwesomeIcon
+              icon="lock"
+              style={[pal.textLight, styles.groupContentIcon]}
+            />
+            <TextInput
+              testID="newPasswordInput"
+              style={[pal.text, styles.textInput]}
+              placeholder="New password"
+              placeholderTextColor={pal.colors.textLight}
+              autoCapitalize="none"
+              autoCorrect={false}
+              keyboardAppearance={theme.colorScheme}
+              secureTextEntry
+              value={password}
+              onChangeText={setPassword}
+              editable={!isProcessing}
+              accessible={true}
+              accessibilityLabel={_(msg`Password`)}
+              accessibilityHint="Input new password"
+            />
+          </View>
+        </View>
+        {error ? (
+          <View style={styles.error}>
+            <View style={styles.errorIcon}>
+              <FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
+            </View>
+            <View style={s.flex1}>
+              <Text style={[s.white, s.bold]}>{error}</Text>
+            </View>
+          </View>
+        ) : undefined}
+        <View style={[s.flexRow, s.alignCenter, s.pl20, s.pr20]}>
+          <TouchableOpacity onPress={onPressBack} accessibilityRole="button">
+            <Text type="xl" style={[pal.link, s.pl5]}>
+              <Trans>Back</Trans>
+            </Text>
+          </TouchableOpacity>
+          <View style={s.flex1} />
+          {isProcessing ? (
+            <ActivityIndicator />
+          ) : !resetCode || !password ? (
+            <Text type="xl-bold" style={[pal.link, s.pr5, styles.dimmed]}>
+              <Trans>Next</Trans>
+            </Text>
+          ) : (
+            <TouchableOpacity
+              testID="setNewPasswordButton"
+              onPress={onPressNext}
+              accessibilityRole="button"
+              accessibilityLabel={_(msg`Go to next`)}
+              accessibilityHint="Navigates to the next screen">
+              <Text type="xl-bold" style={[pal.link, s.pr5]}>
+                <Trans>Next</Trans>
+              </Text>
+            </TouchableOpacity>
+          )}
+          {isProcessing ? (
+            <Text type="xl" style={[pal.textLight, s.pl10]}>
+              <Trans>Updating...</Trans>
+            </Text>
+          ) : undefined}
+        </View>
+      </View>
+    </>
+  )
+}
diff --git a/src/view/com/auth/login/styles.ts b/src/view/com/auth/login/styles.ts
new file mode 100644
index 000000000..9dccc2803
--- /dev/null
+++ b/src/view/com/auth/login/styles.ts
@@ -0,0 +1,118 @@
+import {StyleSheet} from 'react-native'
+import {colors} from 'lib/styles'
+import {isWeb} from '#/platform/detection'
+
+export const styles = StyleSheet.create({
+  screenTitle: {
+    marginBottom: 10,
+    marginHorizontal: 20,
+  },
+  instructions: {
+    marginBottom: 20,
+    marginHorizontal: 20,
+  },
+  group: {
+    borderWidth: 1,
+    borderRadius: 10,
+    marginBottom: 20,
+    marginHorizontal: 20,
+  },
+  groupLabel: {
+    paddingHorizontal: 20,
+    paddingBottom: 5,
+  },
+  groupContent: {
+    borderTopWidth: 1,
+    flexDirection: 'row',
+    alignItems: 'center',
+  },
+  noTopBorder: {
+    borderTopWidth: 0,
+  },
+  groupContentIcon: {
+    marginLeft: 10,
+  },
+  account: {
+    borderTopWidth: 1,
+    paddingHorizontal: 20,
+    paddingVertical: 4,
+  },
+  accountLast: {
+    borderBottomWidth: 1,
+    marginBottom: 20,
+    paddingVertical: 8,
+  },
+  textInput: {
+    flex: 1,
+    width: '100%',
+    paddingVertical: 10,
+    paddingHorizontal: 12,
+    fontSize: 17,
+    letterSpacing: 0.25,
+    fontWeight: '400',
+    borderRadius: 10,
+  },
+  textInputInnerBtn: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    paddingVertical: 6,
+    paddingHorizontal: 8,
+    marginHorizontal: 6,
+  },
+  textBtn: {
+    flexDirection: 'row',
+    flex: 1,
+    alignItems: 'center',
+  },
+  textBtnLabel: {
+    flex: 1,
+    paddingVertical: 10,
+    paddingHorizontal: 12,
+  },
+  textBtnFakeInnerBtn: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    borderRadius: 6,
+    paddingVertical: 6,
+    paddingHorizontal: 8,
+    marginHorizontal: 6,
+  },
+  accountText: {
+    flex: 1,
+    flexDirection: 'row',
+    alignItems: 'baseline',
+    paddingVertical: 10,
+  },
+  accountTextOther: {
+    paddingLeft: 12,
+  },
+  error: {
+    backgroundColor: colors.red4,
+    flexDirection: 'row',
+    alignItems: 'center',
+    marginTop: -5,
+    marginHorizontal: 20,
+    marginBottom: 15,
+    borderRadius: 8,
+    paddingHorizontal: 8,
+    paddingVertical: 8,
+  },
+  errorIcon: {
+    borderWidth: 1,
+    borderColor: colors.white,
+    color: colors.white,
+    borderRadius: 30,
+    width: 16,
+    height: 16,
+    alignItems: 'center',
+    justifyContent: 'center',
+    marginRight: 5,
+  },
+  dimmed: {opacity: 0.5},
+
+  maxHeight: {
+    // @ts-ignore web only -prf
+    maxHeight: isWeb ? '100vh' : undefined,
+    height: !isWeb ? '100%' : undefined,
+  },
+})
diff --git a/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx b/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx
index f672372b8..7ec78bd7f 100644
--- a/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx
+++ b/src/view/com/auth/onboarding/RecommendedFollowsItem.tsx
@@ -14,6 +14,7 @@ import {Text} from 'view/com/util/text/Text'
 import Animated, {FadeInRight} from 'react-native-reanimated'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {useAnalytics} from 'lib/analytics/analytics'
+import {Trans} from '@lingui/macro'
 
 type Props = {
   item: SuggestedActor
@@ -115,7 +116,9 @@ export const ProfileCard = observer(function ProfileCardImpl({
       {addingMoreSuggestions ? (
         <View style={styles.addingMoreContainer}>
           <ActivityIndicator size="small" color={pal.colors.text} />
-          <Text style={[pal.text]}>Finding similar accounts...</Text>
+          <Text style={[pal.text]}>
+            <Trans>Finding similar accounts...</Trans>
+          </Text>
         </View>
       ) : null}
     </View>
diff --git a/src/view/com/auth/onboarding/WelcomeMobile.tsx b/src/view/com/auth/onboarding/WelcomeMobile.tsx
index 1f0a64370..ef70a1fe3 100644
--- a/src/view/com/auth/onboarding/WelcomeMobile.tsx
+++ b/src/view/com/auth/onboarding/WelcomeMobile.tsx
@@ -7,6 +7,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {Button} from 'view/com/util/forms/Button'
 import {observer} from 'mobx-react-lite'
 import {ViewHeader} from 'view/com/util/ViewHeader'
+import {Trans} from '@lingui/macro'
 
 type Props = {
   next: () => void
@@ -32,7 +33,9 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
               accessibilityRole="button"
               style={[s.flexRow, s.alignCenter]}
               onPress={skip}>
-              <Text style={[pal.link]}>Skip</Text>
+              <Text style={[pal.link]}>
+                <Trans>Skip</Trans>
+              </Text>
               <FontAwesomeIcon
                 icon={'chevron-right'}
                 size={14}
@@ -45,17 +48,21 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
       <View>
         <Text style={[pal.text, styles.title]}>
           Welcome to{' '}
-          <Text style={[pal.text, pal.link, styles.title]}>Bluesky</Text>
+          <Text style={[pal.text, pal.link, styles.title]}>
+            <Trans>Bluesky</Trans>
+          </Text>
         </Text>
         <View style={styles.spacer} />
         <View style={[styles.row]}>
           <FontAwesomeIcon icon={'globe'} size={36} color={pal.colors.link} />
           <View style={[styles.rowText]}>
             <Text type="lg-bold" style={[pal.text]}>
-              Bluesky is public.
+              <Trans>Bluesky is public.</Trans>
             </Text>
             <Text type="lg-thin" style={[pal.text, s.pt2]}>
-              Your posts, likes, and blocks are public. Mutes are private.
+              <Trans>
+                Your posts, likes, and blocks are public. Mutes are private.
+              </Trans>
             </Text>
           </View>
         </View>
@@ -63,10 +70,10 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
           <FontAwesomeIcon icon={'at'} size={36} color={pal.colors.link} />
           <View style={[styles.rowText]}>
             <Text type="lg-bold" style={[pal.text]}>
-              Bluesky is open.
+              <Trans>Bluesky is open.</Trans>
             </Text>
             <Text type="lg-thin" style={[pal.text, s.pt2]}>
-              Never lose access to your followers and data.
+              <Trans>Never lose access to your followers and data.</Trans>
             </Text>
           </View>
         </View>
@@ -74,11 +81,13 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
           <FontAwesomeIcon icon={'gear'} size={36} color={pal.colors.link} />
           <View style={[styles.rowText]}>
             <Text type="lg-bold" style={[pal.text]}>
-              Bluesky is flexible.
+              <Trans>Bluesky is flexible.</Trans>
             </Text>
             <Text type="lg-thin" style={[pal.text, s.pt2]}>
-              Choose the algorithms that power your experience with custom
-              feeds.
+              <Trans>
+                Choose the algorithms that power your experience with custom
+                feeds.
+              </Trans>
             </Text>
           </View>
         </View>
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index cdc9768f7..8f8c2eea3 100644
--- a/src/view/com/composer/Composer.tsx
+++ b/src/view/com/composer/Composer.tsx
@@ -49,6 +49,8 @@ import {LabelsBtn} from './labels/LabelsBtn'
 import {SelectLangBtn} from './select-language/SelectLangBtn'
 import {EmojiPickerButton} from './text-input/web/EmojiPicker.web'
 import {insertMentionAt} from 'lib/strings/mention-manip'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModals, useModalControls} from '#/state/modals'
 import {useRequireAltTextEnabled} from '#/state/preferences'
 import {
@@ -70,6 +72,7 @@ export const ComposePost = observer(function ComposePost({
   const pal = usePalette('default')
   const {isDesktop, isMobile} = useWebMediaQueries()
   const store = useStores()
+  const {_} = useLingui()
   const requireAltTextEnabled = useRequireAltTextEnabled()
   const langPrefs = useLanguagePrefs()
   const setLangPrefs = useLanguagePrefsApi()
@@ -273,9 +276,11 @@ export const ComposePost = observer(function ComposePost({
             onPress={onPressCancel}
             onAccessibilityEscape={onPressCancel}
             accessibilityRole="button"
-            accessibilityLabel="Cancel"
+            accessibilityLabel={_(msg`Cancel`)}
             accessibilityHint="Closes post composer and discards post draft">
-            <Text style={[pal.link, s.f18]}>Cancel</Text>
+            <Text style={[pal.link, s.f18]}>
+              <Trans>Cancel</Trans>
+            </Text>
           </TouchableOpacity>
           <View style={s.flex1} />
           {isProcessing ? (
@@ -316,7 +321,9 @@ export const ComposePost = observer(function ComposePost({
                 </TouchableOpacity>
               ) : (
                 <View style={[styles.postBtn, pal.btn]}>
-                  <Text style={[pal.textLight, s.f16, s.bold]}>Post</Text>
+                  <Text style={[pal.textLight, s.f16, s.bold]}>
+                    <Trans>Post</Trans>
+                  </Text>
                 </View>
               )}
             </>
@@ -332,7 +339,7 @@ export const ComposePost = observer(function ComposePost({
               />
             </View>
             <Text style={[pal.text, s.flex1]}>
-              One or more images is missing alt text.
+              <Trans>One or more images is missing alt text.</Trans>
             </Text>
           </View>
         )}
@@ -388,7 +395,7 @@ export const ComposePost = observer(function ComposePost({
               onSuggestedLinksChanged={setSuggestedLinks}
               onError={setError}
               accessible={true}
-              accessibilityLabel="Write post"
+              accessibilityLabel={_(msg`Write post`)}
               accessibilityHint={`Compose posts up to ${MAX_GRAPHEME_LENGTH} characters in length`}
             />
           </View>
@@ -417,11 +424,11 @@ export const ComposePost = observer(function ComposePost({
                   style={[pal.borderDark, styles.addExtLinkBtn]}
                   onPress={() => onPressAddLinkCard(url)}
                   accessibilityRole="button"
-                  accessibilityLabel="Add link card"
+                  accessibilityLabel={_(msg`Add link card`)}
                   accessibilityHint={`Creates a card with a thumbnail. The card links to ${url}`}>
                   <Text style={pal.text}>
-                    Add link card:{' '}
-                    <Text style={pal.link}>{toShortUrl(url)}</Text>
+                    <Trans>Add link card:</Trans>
+                    <Text style={[pal.link, s.ml5]}>{toShortUrl(url)}</Text>
                   </Text>
                 </TouchableOpacity>
               ))}
diff --git a/src/view/com/composer/ExternalEmbed.tsx b/src/view/com/composer/ExternalEmbed.tsx
index c9200ec63..502e4b4d2 100644
--- a/src/view/com/composer/ExternalEmbed.tsx
+++ b/src/view/com/composer/ExternalEmbed.tsx
@@ -11,6 +11,8 @@ import {Text} from '../util/text/Text'
 import {s} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {ExternalEmbedDraft} from 'lib/api/index'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export const ExternalEmbed = ({
   link,
@@ -21,6 +23,7 @@ export const ExternalEmbed = ({
 }) => {
   const pal = usePalette('default')
   const palError = usePalette('error')
+  const {_} = useLingui()
   if (!link) {
     return <View />
   }
@@ -64,7 +67,7 @@ export const ExternalEmbed = ({
         style={styles.removeBtn}
         onPress={onRemove}
         accessibilityRole="button"
-        accessibilityLabel="Remove image preview"
+        accessibilityLabel={_(msg`Remove image preview`)}
         accessibilityHint={`Removes default thumbnail from ${link.uri}`}
         onAccessibilityEscape={onRemove}>
         <FontAwesomeIcon size={18} icon="xmark" style={s.white} />
diff --git a/src/view/com/composer/Prompt.tsx b/src/view/com/composer/Prompt.tsx
index e54404f52..5e8a01d96 100644
--- a/src/view/com/composer/Prompt.tsx
+++ b/src/view/com/composer/Prompt.tsx
@@ -5,10 +5,13 @@ import {Text} from '../util/text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useStores} from 'state/index'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isDesktop} = useWebMediaQueries()
   return (
     <TouchableOpacity
@@ -16,7 +19,7 @@ export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
       style={[pal.view, pal.border, styles.prompt]}
       onPress={() => onPressCompose()}
       accessibilityRole="button"
-      accessibilityLabel="Compose reply"
+      accessibilityLabel={_(msg`Compose reply`)}
       accessibilityHint="Opens composer">
       <UserAvatar avatar={store.me.avatar} size={38} />
       <Text
@@ -25,7 +28,7 @@ export function ComposePrompt({onPressCompose}: {onPressCompose: () => void}) {
           pal.text,
           isDesktop ? styles.labelDesktopWeb : styles.labelMobile,
         ]}>
-        Write your reply
+        <Trans>Write your reply</Trans>
       </Text>
     </TouchableOpacity>
   )
diff --git a/src/view/com/composer/labels/LabelsBtn.tsx b/src/view/com/composer/labels/LabelsBtn.tsx
index 4b6ad81c7..7d90774f2 100644
--- a/src/view/com/composer/labels/LabelsBtn.tsx
+++ b/src/view/com/composer/labels/LabelsBtn.tsx
@@ -7,6 +7,8 @@ import {ShieldExclamation} from 'lib/icons'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
 import {isNative} from 'platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 export const LabelsBtn = observer(function LabelsBtn({
@@ -19,6 +21,7 @@ export const LabelsBtn = observer(function LabelsBtn({
   onChange: (v: string[]) => void
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {openModal} = useModalControls()
 
   return (
@@ -26,7 +29,7 @@ export const LabelsBtn = observer(function LabelsBtn({
       type="default-light"
       testID="labelsBtn"
       style={[styles.button, !hasMedia && styles.dimmed]}
-      accessibilityLabel="Content warnings"
+      accessibilityLabel={_(msg`Content warnings`)}
       accessibilityHint=""
       onPress={() => {
         if (isNative) {
diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx
index 069a05475..69c8debb0 100644
--- a/src/view/com/composer/photos/Gallery.tsx
+++ b/src/view/com/composer/photos/Gallery.tsx
@@ -10,6 +10,8 @@ import {Text} from 'view/com/util/text/Text'
 import {Dimensions} from 'lib/media/types'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 import {isNative} from 'platform/detection'
 
@@ -48,6 +50,7 @@ const GalleryInner = observer(function GalleryImpl({
   containerInfo,
 }: GalleryInnerProps) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
   const {openModal} = useModalControls()
 
@@ -113,7 +116,7 @@ const GalleryInner = observer(function GalleryImpl({
             <TouchableOpacity
               testID="altTextButton"
               accessibilityRole="button"
-              accessibilityLabel="Add alt text"
+              accessibilityLabel={_(msg`Add alt text`)}
               accessibilityHint=""
               onPress={() => {
                 Keyboard.dismiss()
@@ -124,7 +127,7 @@ const GalleryInner = observer(function GalleryImpl({
               }}
               style={[styles.altTextControl, altTextControlStyle]}>
               <Text style={styles.altTextControlLabel} accessible={false}>
-                ALT
+                <Trans>ALT</Trans>
               </Text>
               {image.altText.length > 0 ? (
                 <FontAwesomeIcon
@@ -138,7 +141,7 @@ const GalleryInner = observer(function GalleryImpl({
               <TouchableOpacity
                 testID="editPhotoButton"
                 accessibilityRole="button"
-                accessibilityLabel="Edit image"
+                accessibilityLabel={_(msg`Edit image`)}
                 accessibilityHint=""
                 onPress={() => {
                   if (isNative) {
@@ -161,7 +164,7 @@ const GalleryInner = observer(function GalleryImpl({
               <TouchableOpacity
                 testID="removePhotoButton"
                 accessibilityRole="button"
-                accessibilityLabel="Remove image"
+                accessibilityLabel={_(msg`Remove image`)}
                 accessibilityHint=""
                 onPress={() => gallery.remove(image)}
                 style={styles.imageControl}>
@@ -174,7 +177,7 @@ const GalleryInner = observer(function GalleryImpl({
             </View>
             <TouchableOpacity
               accessibilityRole="button"
-              accessibilityLabel="Add alt text"
+              accessibilityLabel={_(msg`Add alt text`)}
               accessibilityHint=""
               onPress={() => {
                 Keyboard.dismiss()
@@ -203,8 +206,10 @@ const GalleryInner = observer(function GalleryImpl({
           <FontAwesomeIcon icon="info" size={12} color={pal.colors.text} />
         </View>
         <Text type="sm" style={[pal.textLight, s.flex1]}>
-          Alt text describes images for blind and low-vision users, and helps
-          give context to everyone.
+          <Trans>
+            Alt text describes images for blind and low-vision users, and helps
+            give context to everyone.
+          </Trans>
         </Text>
       </View>
     </>
diff --git a/src/view/com/composer/photos/OpenCameraBtn.tsx b/src/view/com/composer/photos/OpenCameraBtn.tsx
index 99e820d51..4eac7179e 100644
--- a/src/view/com/composer/photos/OpenCameraBtn.tsx
+++ b/src/view/com/composer/photos/OpenCameraBtn.tsx
@@ -13,6 +13,8 @@ import {HITSLOP_10, POST_IMG_MAX} from 'lib/constants'
 import {GalleryModel} from 'state/models/media/gallery'
 import {isMobileWeb, isNative} from 'platform/detection'
 import {logger} from '#/logger'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = {
   gallery: GalleryModel
@@ -22,6 +24,7 @@ export function OpenCameraBtn({gallery}: Props) {
   const pal = usePalette('default')
   const {track} = useAnalytics()
   const store = useStores()
+  const {_} = useLingui()
   const {requestCameraAccessIfNeeded} = useCameraPermission()
 
   const onPressTakePicture = useCallback(async () => {
@@ -56,7 +59,7 @@ export function OpenCameraBtn({gallery}: Props) {
       style={styles.button}
       hitSlop={HITSLOP_10}
       accessibilityRole="button"
-      accessibilityLabel="Camera"
+      accessibilityLabel={_(msg`Camera`)}
       accessibilityHint="Opens camera on device">
       <FontAwesomeIcon
         icon="camera"
diff --git a/src/view/com/composer/photos/SelectPhotoBtn.tsx b/src/view/com/composer/photos/SelectPhotoBtn.tsx
index a6826eb98..af0a22b01 100644
--- a/src/view/com/composer/photos/SelectPhotoBtn.tsx
+++ b/src/view/com/composer/photos/SelectPhotoBtn.tsx
@@ -10,6 +10,8 @@ import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
 import {GalleryModel} from 'state/models/media/gallery'
 import {HITSLOP_10} from 'lib/constants'
 import {isNative} from 'platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 type Props = {
   gallery: GalleryModel
@@ -18,6 +20,7 @@ type Props = {
 export function SelectPhotoBtn({gallery}: Props) {
   const pal = usePalette('default')
   const {track} = useAnalytics()
+  const {_} = useLingui()
   const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
 
   const onPressSelectPhotos = useCallback(async () => {
@@ -37,7 +40,7 @@ export function SelectPhotoBtn({gallery}: Props) {
       style={styles.button}
       hitSlop={HITSLOP_10}
       accessibilityRole="button"
-      accessibilityLabel="Gallery"
+      accessibilityLabel={_(msg`Gallery`)}
       accessibilityHint="Opens device photo gallery">
       <FontAwesomeIcon
         icon={['far', 'image']}
diff --git a/src/view/com/composer/select-language/SelectLangBtn.tsx b/src/view/com/composer/select-language/SelectLangBtn.tsx
index 896df041e..7ea63ed62 100644
--- a/src/view/com/composer/select-language/SelectLangBtn.tsx
+++ b/src/view/com/composer/select-language/SelectLangBtn.tsx
@@ -21,9 +21,12 @@ import {
   toPostLanguages,
   hasPostLanguage,
 } from '#/state/preferences/languages'
+import {t, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const SelectLangBtn = observer(function SelectLangBtn() {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {openModal} = useModalControls()
   const langPrefs = useLanguagePrefs()
   const setLangPrefs = useLanguagePrefsApi()
@@ -82,11 +85,11 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
     }
 
     return [
-      {heading: true, label: 'Post language'},
+      {heading: true, label: t`Post language`},
       ...arr.slice(0, 6),
       {sep: true},
       {
-        label: 'Other...',
+        label: t`Other...`,
         onPress: onPressMore,
       },
     ]
@@ -99,7 +102,7 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
       items={items}
       openUpwards
       style={styles.button}
-      accessibilityLabel="Language selection"
+      accessibilityLabel={_(msg`Language selection`)}
       accessibilityHint="">
       {postLanguagesPref.length > 0 ? (
         <Text type="lg-bold" style={[pal.link, styles.label]} numberOfLines={1}>
diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx
index 1037007b7..044f69efe 100644
--- a/src/view/com/feeds/FeedPage.tsx
+++ b/src/view/com/feeds/FeedPage.tsx
@@ -21,6 +21,8 @@ import {FAB} from '../util/fab/FAB'
 import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn'
 import useAppState from 'react-native-appstate-hook'
 import {logger} from '#/logger'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const FeedPage = observer(function FeedPageImpl({
   testID,
@@ -37,6 +39,7 @@ export const FeedPage = observer(function FeedPageImpl({
 }) {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isDesktop} = useWebMediaQueries()
   const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
   const {screen, track} = useAnalytics()
@@ -157,7 +160,7 @@ export const FeedPage = observer(function FeedPageImpl({
             type="title-lg"
             href="/settings/home-feed"
             style={{fontWeight: 'bold'}}
-            accessibilityLabel="Feed Preferences"
+            accessibilityLabel={_(msg`Feed Preferences`)}
             accessibilityHint=""
             text={
               <FontAwesomeIcon
@@ -170,7 +173,7 @@ export const FeedPage = observer(function FeedPageImpl({
       )
     }
     return <></>
-  }, [isDesktop, pal, store, hasNew])
+  }, [isDesktop, pal.view, pal.text, pal.textLight, store, hasNew, _])
 
   return (
     <View testID={testID} style={s.h100pct}>
@@ -188,7 +191,7 @@ export const FeedPage = observer(function FeedPageImpl({
       {(isScrolledDown || hasNew) && (
         <LoadLatestBtn
           onPress={onPressLoadLatest}
-          label="Load new posts"
+          label={_(msg`Load new posts`)}
           showIndicator={hasNew}
         />
       )}
@@ -197,7 +200,7 @@ export const FeedPage = observer(function FeedPageImpl({
         onPress={onPressCompose}
         icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
         accessibilityRole="button"
-        accessibilityLabel="New post"
+        accessibilityLabel={_(msg`New post`)}
         accessibilityHint=""
       />
     </View>
diff --git a/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx b/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx
index bb006d506..c806bc6a6 100644
--- a/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx
+++ b/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx
@@ -5,10 +5,10 @@
  * LICENSE file in the root directory of this source tree.
  *
  */
-
-import {createHitslop} from 'lib/constants'
 import React from 'react'
+import {createHitslop} from 'lib/constants'
 import {SafeAreaView, Text, TouchableOpacity, StyleSheet} from 'react-native'
+import {t} from '@lingui/macro'
 
 type Props = {
   onRequestClose: () => void
@@ -23,7 +23,7 @@ const ImageDefaultHeader = ({onRequestClose}: Props) => (
       onPress={onRequestClose}
       hitSlop={HIT_SLOP}
       accessibilityRole="button"
-      accessibilityLabel="Close image"
+      accessibilityLabel={t`Close image`}
       accessibilityHint="Closes viewer for header image"
       onAccessibilityEscape={onRequestClose}>
       <Text style={styles.closeText}>✕</Text>
diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx
index ddf965f42..331a2b823 100644
--- a/src/view/com/lightbox/Lightbox.web.tsx
+++ b/src/view/com/lightbox/Lightbox.web.tsx
@@ -14,6 +14,8 @@ import * as models from 'state/models/ui/shell'
 import {colors, s} from 'lib/styles'
 import ImageDefaultHeader from './ImageViewing/components/ImageDefaultHeader'
 import {Text} from '../util/text/Text'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 interface Img {
   uri: string
@@ -62,6 +64,7 @@ function LightboxInner({
   initialIndex: number
   onClose: () => void
 }) {
+  const {_} = useLingui()
   const [index, setIndex] = useState<number>(initialIndex)
   const [isAltExpanded, setAltExpanded] = useState(false)
 
@@ -101,7 +104,7 @@ function LightboxInner({
       <TouchableWithoutFeedback
         onPress={onClose}
         accessibilityRole="button"
-        accessibilityLabel="Close image viewer"
+        accessibilityLabel={_(msg`Close image viewer`)}
         accessibilityHint="Exits image view"
         onAccessibilityEscape={onClose}>
         <View style={styles.imageCenterer}>
@@ -117,7 +120,7 @@ function LightboxInner({
               onPress={onPressLeft}
               style={[styles.btn, styles.leftBtn]}
               accessibilityRole="button"
-              accessibilityLabel="Previous image"
+              accessibilityLabel={_(msg`Previous image`)}
               accessibilityHint="">
               <FontAwesomeIcon
                 icon="angle-left"
@@ -131,7 +134,7 @@ function LightboxInner({
               onPress={onPressRight}
               style={[styles.btn, styles.rightBtn]}
               accessibilityRole="button"
-              accessibilityLabel="Next image"
+              accessibilityLabel={_(msg`Next image`)}
               accessibilityHint="">
               <FontAwesomeIcon
                 icon="angle-right"
@@ -145,7 +148,7 @@ function LightboxInner({
       {imgs[index].alt ? (
         <View style={styles.footer}>
           <Pressable
-            accessibilityLabel="Expand alt text"
+            accessibilityLabel={_(msg`Expand alt text`)}
             accessibilityHint="If alt text is long, toggles alt text expanded state"
             onPress={() => {
               setAltExpanded(!isAltExpanded)
diff --git a/src/view/com/lists/ListsList.tsx b/src/view/com/lists/ListsList.tsx
index 8c6510886..2883a31d5 100644
--- a/src/view/com/lists/ListsList.tsx
+++ b/src/view/com/lists/ListsList.tsx
@@ -20,6 +20,7 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {FlatList} from '../util/Views'
 import {s} from 'lib/styles'
 import {logger} from '#/logger'
+import {Trans} from '@lingui/macro'
 
 const LOADING = {_reactKey: '__loading__'}
 const EMPTY = {_reactKey: '__empty__'}
@@ -107,7 +108,9 @@ export const ListsList = observer(function ListsListImpl({
           <View
             testID="listsEmpty"
             style={[{padding: 18, borderTopWidth: 1}, pal.border]}>
-            <Text style={pal.textLight}>You have no lists.</Text>
+            <Text style={pal.textLight}>
+              <Trans>You have no lists.</Trans>
+            </Text>
           </View>
         )
       } else if (item === ERROR_ITEM) {
diff --git a/src/view/com/modals/AddAppPasswords.tsx b/src/view/com/modals/AddAppPasswords.tsx
index 621c61b90..095ad48bd 100644
--- a/src/view/com/modals/AddAppPasswords.tsx
+++ b/src/view/com/modals/AddAppPasswords.tsx
@@ -13,6 +13,8 @@ import {
 import Clipboard from '@react-native-clipboard/clipboard'
 import * as Toast from '../util/Toast'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['70%']
@@ -55,6 +57,7 @@ const shadesOfBlue: string[] = [
 export function Component({}: {}) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const [name, setName] = useState(
     shadesOfBlue[Math.floor(Math.random() * shadesOfBlue.length)],
@@ -121,15 +124,19 @@ export function Component({}: {}) {
       <View>
         {!appPassword ? (
           <Text type="lg" style={[pal.text]}>
-            Please enter a unique name for this App Password or use our randomly
-            generated one.
+            <Trans>
+              Please enter a unique name for this App Password or use our
+              randomly generated one.
+            </Trans>
           </Text>
         ) : (
           <Text type="lg" style={[pal.text]}>
-            <Text type="lg-bold" style={[pal.text]}>
-              Here is your app password.
-            </Text>{' '}
-            Use this to sign into the other app along with your handle.
+            <Text type="lg-bold" style={[pal.text, s.mr5]}>
+              <Trans>Here is your app password.</Trans>
+            </Text>
+            <Trans>
+              Use this to sign into the other app along with your handle.
+            </Trans>
           </Text>
         )}
         {!appPassword ? (
@@ -154,7 +161,7 @@ export function Component({}: {}) {
               returnKeyType="done"
               onEndEditing={createAppPassword}
               accessible={true}
-              accessibilityLabel="Name"
+              accessibilityLabel={_(msg`Name`)}
               accessibilityHint="Input name for app password"
             />
           </View>
@@ -163,13 +170,15 @@ export function Component({}: {}) {
             style={[pal.border, styles.passwordContainer, pal.btn]}
             onPress={onCopy}
             accessibilityRole="button"
-            accessibilityLabel="Copy"
+            accessibilityLabel={_(msg`Copy`)}
             accessibilityHint="Copies app password">
             <Text type="2xl-bold" style={[pal.text]}>
               {appPassword}
             </Text>
             {wasCopied ? (
-              <Text style={[pal.textLight]}>Copied</Text>
+              <Text style={[pal.textLight]}>
+                <Trans>Copied</Trans>
+              </Text>
             ) : (
               <FontAwesomeIcon
                 icon={['far', 'clone']}
@@ -182,14 +191,18 @@ export function Component({}: {}) {
       </View>
       {appPassword ? (
         <Text type="lg" style={[pal.textLight, s.mb10]}>
-          For security reasons, you won't be able to view this again. If you
-          lose this password, you'll need to generate a new one.
+          <Trans>
+            For security reasons, you won't be able to view this again. If you
+            lose this password, you'll need to generate a new one.
+          </Trans>
         </Text>
       ) : (
         <Text type="xs" style={[pal.textLight, s.mb10, s.mt2]}>
-          Can only contain letters, numbers, spaces, dashes, and underscores.
-          Must be at least 4 characters long, but no more than 32 characters
-          long.
+          <Trans>
+            Can only contain letters, numbers, spaces, dashes, and underscores.
+            Must be at least 4 characters long, but no more than 32 characters
+            long.
+          </Trans>
         </Text>
       )}
       <View style={styles.btnContainer}>
diff --git a/src/view/com/modals/AltImage.tsx b/src/view/com/modals/AltImage.tsx
index 9c377a121..80130f43a 100644
--- a/src/view/com/modals/AltImage.tsx
+++ b/src/view/com/modals/AltImage.tsx
@@ -19,6 +19,8 @@ import {Text} from '../util/text/Text'
 import LinearGradient from 'react-native-linear-gradient'
 import {isAndroid, isWeb} from 'platform/detection'
 import {ImageModel} from 'state/models/media/image'
+import {useLingui} from '@lingui/react'
+import {Trans, msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['fullscreen']
@@ -30,6 +32,7 @@ interface Props {
 export function Component({image}: Props) {
   const pal = usePalette('default')
   const theme = useTheme()
+  const {_} = useLingui()
   const [altText, setAltText] = useState(image.altText)
   const windim = useWindowDimensions()
   const {closeModal} = useModalControls()
@@ -90,7 +93,7 @@ export function Component({image}: Props) {
             placeholderTextColor={pal.colors.textLight}
             value={altText}
             onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))}
-            accessibilityLabel="Image alt text"
+            accessibilityLabel={_(msg`Image alt text`)}
             accessibilityHint=""
             accessibilityLabelledBy="imageAltText"
             autoFocus
@@ -99,7 +102,7 @@ export function Component({image}: Props) {
             <TouchableOpacity
               testID="altTextImageSaveBtn"
               onPress={onPressSave}
-              accessibilityLabel="Save alt text"
+              accessibilityLabel={_(msg`Save alt text`)}
               accessibilityHint={`Saves alt text, which reads: ${altText}`}
               accessibilityRole="button">
               <LinearGradient
@@ -108,7 +111,7 @@ export function Component({image}: Props) {
                 end={{x: 1, y: 1}}
                 style={[styles.button]}>
                 <Text type="button-lg" style={[s.white, s.bold]}>
-                  Save
+                  <Trans>Save</Trans>
                 </Text>
               </LinearGradient>
             </TouchableOpacity>
@@ -116,12 +119,12 @@ export function Component({image}: Props) {
               testID="altTextImageCancelBtn"
               onPress={onPressCancel}
               accessibilityRole="button"
-              accessibilityLabel="Cancel add image alt text"
+              accessibilityLabel={_(msg`Cancel add image alt text`)}
               accessibilityHint=""
               onAccessibilityEscape={onPressCancel}>
               <View style={[styles.button]}>
                 <Text type="button-lg" style={[pal.textLight]}>
-                  Cancel
+                  <Trans>Cancel</Trans>
                 </Text>
               </View>
             </TouchableOpacity>
diff --git a/src/view/com/modals/BirthDateSettings.tsx b/src/view/com/modals/BirthDateSettings.tsx
index 7b0778f83..6655b7a6b 100644
--- a/src/view/com/modals/BirthDateSettings.tsx
+++ b/src/view/com/modals/BirthDateSettings.tsx
@@ -15,6 +15,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {cleanError} from 'lib/strings/errors'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['50%']
@@ -22,6 +24,7 @@ export const snapPoints = ['50%']
 export const Component = observer(function Component({}: {}) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const [date, setDate] = useState<Date>(
     store.preferences.birthDate || new Date(),
@@ -49,12 +52,12 @@ export const Component = observer(function Component({}: {}) {
       style={[pal.view, styles.container, isMobile && {paddingHorizontal: 18}]}>
       <View style={styles.titleSection}>
         <Text type="title-lg" style={[pal.text, styles.title]}>
-          My Birthday
+          <Trans>My Birthday</Trans>
         </Text>
       </View>
 
       <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
-        This information is not shared with other users.
+        <Trans>This information is not shared with other users.</Trans>
       </Text>
 
       <View>
@@ -65,7 +68,7 @@ export const Component = observer(function Component({}: {}) {
           buttonType="default-light"
           buttonStyle={[pal.border, styles.dateInputButton]}
           buttonLabelType="lg"
-          accessibilityLabel="Birthday"
+          accessibilityLabel={_(msg`Birthday`)}
           accessibilityHint="Enter your birth date"
           accessibilityLabelledBy="birthDate"
         />
@@ -86,9 +89,11 @@ export const Component = observer(function Component({}: {}) {
             onPress={onSave}
             style={styles.btn}
             accessibilityRole="button"
-            accessibilityLabel="Save"
+            accessibilityLabel={_(msg`Save`)}
             accessibilityHint="">
-            <Text style={[s.white, s.bold, s.f18]}>Save</Text>
+            <Text style={[s.white, s.bold, s.f18]}>
+              <Trans>Save</Trans>
+            </Text>
           </TouchableOpacity>
         )}
       </View>
diff --git a/src/view/com/modals/ChangeEmail.tsx b/src/view/com/modals/ChangeEmail.tsx
index ec37aeede..710c0588e 100644
--- a/src/view/com/modals/ChangeEmail.tsx
+++ b/src/view/com/modals/ChangeEmail.tsx
@@ -12,6 +12,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {cleanError} from 'lib/strings/errors'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 enum Stages {
@@ -25,6 +27,7 @@ export const snapPoints = ['90%']
 export const Component = observer(function Component({}: {}) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const [stage, setStage] = useState<Stages>(Stages.InputEmail)
   const [email, setEmail] = useState<string>(
     store.session.currentSession?.email || '',
@@ -62,7 +65,9 @@ export const Component = observer(function Component({}: {}) {
       // you can remove this any time after Oct2023
       // -prf
       if (err === 'email must be confirmed (temporary)') {
-        err = `Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.`
+        err = _(
+          msg`Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.`,
+        )
       }
       setError(err)
     } finally {
@@ -103,26 +108,26 @@ export const Component = observer(function Component({}: {}) {
         style={[s.flex1, isMobile && {paddingHorizontal: 18}]}>
         <View style={styles.titleSection}>
           <Text type="title-lg" style={[pal.text, styles.title]}>
-            {stage === Stages.InputEmail ? 'Change Your Email' : ''}
-            {stage === Stages.ConfirmCode ? 'Security Step Required' : ''}
-            {stage === Stages.Done ? 'Email Updated' : ''}
+            {stage === Stages.InputEmail ? _(msg`Change Your Email`) : ''}
+            {stage === Stages.ConfirmCode ? _(msg`Security Step Required`) : ''}
+            {stage === Stages.Done ? _(msg`Email Updated`) : ''}
           </Text>
         </View>
 
         <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
           {stage === Stages.InputEmail ? (
-            <>Enter your new email address below.</>
+            <Trans>Enter your new email address below.</Trans>
           ) : stage === Stages.ConfirmCode ? (
-            <>
+            <Trans>
               An email has been sent to your previous address,{' '}
               {store.session.currentSession?.email || ''}. It includes a
               confirmation code which you can enter below.
-            </>
+            </Trans>
           ) : (
-            <>
+            <Trans>
               Your email has been updated but not verified. As a next step,
               please verify your new email.
-            </>
+            </Trans>
           )}
         </Text>
 
@@ -135,7 +140,7 @@ export const Component = observer(function Component({}: {}) {
             value={email}
             onChangeText={setEmail}
             accessible={true}
-            accessibilityLabel="Email"
+            accessibilityLabel={_(msg`Email`)}
             accessibilityHint=""
             autoCapitalize="none"
             autoComplete="email"
@@ -151,7 +156,7 @@ export const Component = observer(function Component({}: {}) {
             value={confirmationCode}
             onChangeText={setConfirmationCode}
             accessible={true}
-            accessibilityLabel="Confirmation code"
+            accessibilityLabel={_(msg`Confirmation code`)}
             accessibilityHint=""
             autoCapitalize="none"
             autoComplete="off"
@@ -175,9 +180,9 @@ export const Component = observer(function Component({}: {}) {
                   testID="requestChangeBtn"
                   type="primary"
                   onPress={onRequestChange}
-                  accessibilityLabel="Request Change"
+                  accessibilityLabel={_(msg`Request Change`)}
                   accessibilityHint=""
-                  label="Request Change"
+                  label={_(msg`Request Change`)}
                   labelContainerStyle={{justifyContent: 'center', padding: 4}}
                   labelStyle={[s.f18]}
                 />
@@ -187,9 +192,9 @@ export const Component = observer(function Component({}: {}) {
                   testID="confirmBtn"
                   type="primary"
                   onPress={onConfirm}
-                  accessibilityLabel="Confirm Change"
+                  accessibilityLabel={_(msg`Confirm Change`)}
                   accessibilityHint=""
-                  label="Confirm Change"
+                  label={_(msg`Confirm Change`)}
                   labelContainerStyle={{justifyContent: 'center', padding: 4}}
                   labelStyle={[s.f18]}
                 />
@@ -199,9 +204,9 @@ export const Component = observer(function Component({}: {}) {
                   testID="verifyBtn"
                   type="primary"
                   onPress={onVerify}
-                  accessibilityLabel="Verify New Email"
+                  accessibilityLabel={_(msg`Verify New Email`)}
                   accessibilityHint=""
-                  label="Verify New Email"
+                  label={_(msg`Verify New Email`)}
                   labelContainerStyle={{justifyContent: 'center', padding: 4}}
                   labelStyle={[s.f18]}
                 />
@@ -210,9 +215,9 @@ export const Component = observer(function Component({}: {}) {
                 testID="cancelBtn"
                 type="default"
                 onPress={() => closeModal()}
-                accessibilityLabel="Cancel"
+                accessibilityLabel={_(msg`Cancel`)}
                 accessibilityHint=""
-                label="Cancel"
+                label={_(msg`Cancel`)}
                 labelContainerStyle={{justifyContent: 'center', padding: 4}}
                 labelStyle={[s.f18]}
               />
diff --git a/src/view/com/modals/ChangeHandle.tsx b/src/view/com/modals/ChangeHandle.tsx
index 6184cb3b7..c03ebafda 100644
--- a/src/view/com/modals/ChangeHandle.tsx
+++ b/src/view/com/modals/ChangeHandle.tsx
@@ -22,6 +22,8 @@ import {useTheme} from 'lib/ThemeContext'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {cleanError} from 'lib/strings/errors'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['100%']
@@ -31,6 +33,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
   const [error, setError] = useState<string>('')
   const pal = usePalette('default')
   const {track} = useAnalytics()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
 
   const [isProcessing, setProcessing] = useState<boolean>(false)
@@ -141,7 +144,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
           <TouchableOpacity
             onPress={onPressCancel}
             accessibilityRole="button"
-            accessibilityLabel="Cancel change handle"
+            accessibilityLabel={_(msg`Cancel change handle`)}
             accessibilityHint="Exits handle change process"
             onAccessibilityEscape={onPressCancel}>
             <Text type="lg" style={pal.textLight}>
@@ -153,7 +156,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
           type="2xl-bold"
           style={[styles.titleMiddle, pal.text]}
           numberOfLines={1}>
-          Change Handle
+          <Trans>Change Handle</Trans>
         </Text>
         <View style={styles.titleRight}>
           {isProcessing ? (
@@ -163,7 +166,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
               testID="retryConnectButton"
               onPress={onPressRetryConnect}
               accessibilityRole="button"
-              accessibilityLabel="Retry change handle"
+              accessibilityLabel={_(msg`Retry change handle`)}
               accessibilityHint={`Retries handle change to ${handle}`}>
               <Text type="xl-bold" style={[pal.link, s.pr5]}>
                 Retry
@@ -173,10 +176,10 @@ export function Component({onChanged}: {onChanged: () => void}) {
             <TouchableOpacity
               onPress={onPressSave}
               accessibilityRole="button"
-              accessibilityLabel="Save handle change"
+              accessibilityLabel={_(msg`Save handle change`)}
               accessibilityHint={`Saves handle change to ${handle}`}>
               <Text type="2xl-medium" style={pal.link}>
-                Save
+                <Trans>Save</Trans>
               </Text>
             </TouchableOpacity>
           ) : undefined}
@@ -234,6 +237,7 @@ function ProvidedHandleForm({
 }) {
   const pal = usePalette('default')
   const theme = useTheme()
+  const {_} = useLingui()
 
   // events
   // =
@@ -266,12 +270,12 @@ function ProvidedHandleForm({
           onChangeText={onChangeHandle}
           editable={!isProcessing}
           accessible={true}
-          accessibilityLabel="Handle"
+          accessibilityLabel={_(msg`Handle`)}
           accessibilityHint="Sets Bluesky username"
         />
       </View>
       <Text type="md" style={[pal.textLight, s.pl10, s.pt10]}>
-        Your full handle will be{' '}
+        <Trans>Your full handle will be </Trans>
         <Text type="md-bold" style={pal.textLight}>
           @{createFullHandle(handle, userDomain)}
         </Text>
@@ -280,9 +284,9 @@ function ProvidedHandleForm({
         onPress={onToggleCustom}
         accessibilityRole="button"
         accessibilityHint="Hosting provider"
-        accessibilityLabel="Opens modal for using custom domain">
+        accessibilityLabel={_(msg`Opens modal for using custom domain`)}>
         <Text type="md-medium" style={[pal.link, s.pl10, s.pt5]}>
-          I have my own domain
+          <Trans>I have my own domain</Trans>
         </Text>
       </TouchableOpacity>
     </>
@@ -314,6 +318,7 @@ function CustomHandleForm({
   const palSecondary = usePalette('secondary')
   const palError = usePalette('error')
   const theme = useTheme()
+  const {_} = useLingui()
   const [isVerifying, setIsVerifying] = React.useState(false)
   const [error, setError] = React.useState<string>('')
   const [isDNSForm, setDNSForm] = React.useState<boolean>(true)
@@ -367,7 +372,7 @@ function CustomHandleForm({
   return (
     <>
       <Text type="md" style={[pal.text, s.pb5, s.pl5]} nativeID="customDomain">
-        Enter the domain you want to use
+        <Trans>Enter the domain you want to use</Trans>
       </Text>
       <View style={[pal.btn, styles.textInputWrapper]}>
         <FontAwesomeIcon
@@ -385,7 +390,7 @@ function CustomHandleForm({
           onChangeText={onChangeHandle}
           editable={!isProcessing}
           accessibilityLabelledBy="customDomain"
-          accessibilityLabel="Custom domain"
+          accessibilityLabel={_(msg`Custom domain`)}
           accessibilityHint="Input your preferred hosting provider"
         />
       </View>
@@ -413,7 +418,7 @@ function CustomHandleForm({
       {isDNSForm ? (
         <>
           <Text type="md" style={[pal.text, s.pb5, s.pl5]}>
-            Add the following DNS record to your domain:
+            <Trans>Add the following DNS record to your domain:</Trans>
           </Text>
           <View style={[styles.dnsTable, pal.btn]}>
             <Text type="md-medium" style={[styles.dnsLabel, pal.text]}>
@@ -451,7 +456,7 @@ function CustomHandleForm({
       ) : (
         <>
           <Text type="md" style={[pal.text, s.pb5, s.pl5]}>
-            Upload a text file to:
+            <Trans>Upload a text file to:</Trans>
           </Text>
           <View style={[styles.valueContainer, pal.btn]}>
             <View style={[styles.dnsValue]}>
@@ -483,7 +488,7 @@ function CustomHandleForm({
       {canSave === true && (
         <View style={[styles.message, palSecondary.view]}>
           <Text type="md-medium" style={palSecondary.text}>
-            Domain verified!
+            <Trans>Domain verified!</Trans>
           </Text>
         </View>
       )}
@@ -511,7 +516,7 @@ function CustomHandleForm({
       <View style={styles.spacer} />
       <TouchableOpacity
         onPress={onToggleCustom}
-        accessibilityLabel="Use default provider"
+        accessibilityLabel={_(msg`Use default provider`)}
         accessibilityHint="Use bsky.social as hosting provider">
         <Text type="md-medium" style={[pal.link, s.pl10, s.pt5]}>
           Nevermind, create a handle for me
diff --git a/src/view/com/modals/Confirm.tsx b/src/view/com/modals/Confirm.tsx
index 6b942057b..5e869f396 100644
--- a/src/view/com/modals/Confirm.tsx
+++ b/src/view/com/modals/Confirm.tsx
@@ -11,6 +11,8 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
 import {cleanError} from 'lib/strings/errors'
 import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import type {ConfirmModal} from '#/state/modals'
 import {useModalControls} from '#/state/modals'
 
@@ -26,6 +28,7 @@ export function Component({
   cancelBtnText,
 }: ConfirmModal) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const [isProcessing, setIsProcessing] = useState<boolean>(false)
   const [error, setError] = useState<string>('')
@@ -69,7 +72,7 @@ export function Component({
           onPress={onPress}
           style={[styles.btn, confirmBtnStyle]}
           accessibilityRole="button"
-          accessibilityLabel="Confirm"
+          accessibilityLabel={_(msg`Confirm`)}
           accessibilityHint="">
           <Text style={[s.white, s.bold, s.f18]}>
             {confirmBtnText ?? 'Confirm'}
@@ -82,7 +85,7 @@ export function Component({
           onPress={onPressCancel}
           style={[styles.btnCancel, s.mt10]}
           accessibilityRole="button"
-          accessibilityLabel="Cancel"
+          accessibilityLabel={_(msg`Cancel`)}
           accessibilityHint="">
           <Text type="button-lg" style={pal.textLight}>
             {cancelBtnText ?? 'Cancel'}
diff --git a/src/view/com/modals/ContentFilteringSettings.tsx b/src/view/com/modals/ContentFilteringSettings.tsx
index 0891a6473..ad4a0fa52 100644
--- a/src/view/com/modals/ContentFilteringSettings.tsx
+++ b/src/view/com/modals/ContentFilteringSettings.tsx
@@ -16,6 +16,8 @@ import {isIOS} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import * as Toast from '../util/Toast'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['90%']
@@ -25,6 +27,7 @@ export const Component = observer(
     const store = useStores()
     const {isMobile} = useWebMediaQueries()
     const pal = usePalette('default')
+    const {_} = useLingui()
     const {closeModal} = useModalControls()
 
     React.useEffect(() => {
@@ -37,7 +40,9 @@ export const Component = observer(
 
     return (
       <View testID="contentFilteringModal" style={[pal.view, styles.container]}>
-        <Text style={[pal.text, styles.title]}>Content Filtering</Text>
+        <Text style={[pal.text, styles.title]}>
+          <Trans>Content Filtering</Trans>
+        </Text>
         <ScrollView style={styles.scrollContainer}>
           <AdultContentEnabledPref />
           <ContentLabelPref
@@ -71,14 +76,16 @@ export const Component = observer(
             testID="sendReportBtn"
             onPress={onPressDone}
             accessibilityRole="button"
-            accessibilityLabel="Done"
+            accessibilityLabel={_(msg`Done`)}
             accessibilityHint="">
             <LinearGradient
               colors={[gradients.blueLight.start, gradients.blueLight.end]}
               start={{x: 0, y: 0}}
               end={{x: 1, y: 1}}
               style={[styles.btn]}>
-              <Text style={[s.white, s.bold, s.f18]}>Done</Text>
+              <Text style={[s.white, s.bold, s.f18]}>
+                <Trans>Done</Trans>
+              </Text>
             </LinearGradient>
           </Pressable>
         </View>
diff --git a/src/view/com/modals/CreateOrEditList.tsx b/src/view/com/modals/CreateOrEditList.tsx
index cdad37770..cfd0f7569 100644
--- a/src/view/com/modals/CreateOrEditList.tsx
+++ b/src/view/com/modals/CreateOrEditList.tsx
@@ -24,6 +24,8 @@ import {useTheme} from 'lib/ThemeContext'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {cleanError, isNetworkError} from 'lib/strings/errors'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 const MAX_NAME = 64 // todo
@@ -47,6 +49,7 @@ export function Component({
   const pal = usePalette('default')
   const theme = useTheme()
   const {track} = useAnalytics()
+  const {_} = useLingui()
 
   const activePurpose = useMemo(() => {
     if (list?.data?.purpose) {
@@ -164,14 +167,18 @@ export function Component({
         ]}
         testID="createOrEditListModal">
         <Text style={[styles.title, pal.text]}>
-          {list ? 'Edit' : 'New'} {purposeLabel} List
+          <Trans>
+            {list ? 'Edit' : 'New'} {purposeLabel} List
+          </Trans>
         </Text>
         {error !== '' && (
           <View style={styles.errorContainer}>
             <ErrorMessage message={error} />
           </View>
         )}
-        <Text style={[styles.label, pal.text]}>List Avatar</Text>
+        <Text style={[styles.label, pal.text]}>
+          <Trans>List Avatar</Trans>
+        </Text>
         <View style={[styles.avi, {borderColor: pal.colors.background}]}>
           <EditableUserAvatar
             type="list"
@@ -183,7 +190,7 @@ export function Component({
         <View style={styles.form}>
           <View>
             <Text style={[styles.label, pal.text]} nativeID="list-name">
-              List Name
+              <Trans>List Name</Trans>
             </Text>
             <TextInput
               testID="editNameInput"
@@ -195,14 +202,14 @@ export function Component({
               value={name}
               onChangeText={v => setName(enforceLen(v, MAX_NAME))}
               accessible={true}
-              accessibilityLabel="Name"
+              accessibilityLabel={_(msg`Name`)}
               accessibilityHint=""
               accessibilityLabelledBy="list-name"
             />
           </View>
           <View style={s.pb10}>
             <Text style={[styles.label, pal.text]} nativeID="list-description">
-              Description
+              <Trans>Description</Trans>
             </Text>
             <TextInput
               testID="editDescriptionInput"
@@ -218,7 +225,7 @@ export function Component({
               value={description}
               onChangeText={v => setDescription(enforceLen(v, MAX_DESCRIPTION))}
               accessible={true}
-              accessibilityLabel="Description"
+              accessibilityLabel={_(msg`Description`)}
               accessibilityHint=""
               accessibilityLabelledBy="list-description"
             />
@@ -233,14 +240,16 @@ export function Component({
               style={s.mt10}
               onPress={onPressSave}
               accessibilityRole="button"
-              accessibilityLabel="Save"
+              accessibilityLabel={_(msg`Save`)}
               accessibilityHint="">
               <LinearGradient
                 colors={[gradients.blueLight.start, gradients.blueLight.end]}
                 start={{x: 0, y: 0}}
                 end={{x: 1, y: 1}}
                 style={[styles.btn]}>
-                <Text style={[s.white, s.bold]}>Save</Text>
+                <Text style={[s.white, s.bold]}>
+                  <Trans>Save</Trans>
+                </Text>
               </LinearGradient>
             </TouchableOpacity>
           )}
@@ -249,11 +258,13 @@ export function Component({
             style={s.mt5}
             onPress={onPressCancel}
             accessibilityRole="button"
-            accessibilityLabel="Cancel"
+            accessibilityLabel={_(msg`Cancel`)}
             accessibilityHint=""
             onAccessibilityEscape={onPressCancel}>
             <View style={[styles.btn]}>
-              <Text style={[s.black, s.bold, pal.text]}>Cancel</Text>
+              <Text style={[s.black, s.bold, pal.text]}>
+                <Trans>Cancel</Trans>
+              </Text>
             </View>
           </TouchableOpacity>
         </View>
diff --git a/src/view/com/modals/DeleteAccount.tsx b/src/view/com/modals/DeleteAccount.tsx
index 9a8a8b4b0..624dbda2d 100644
--- a/src/view/com/modals/DeleteAccount.tsx
+++ b/src/view/com/modals/DeleteAccount.tsx
@@ -17,6 +17,8 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {ErrorMessage} from '../util/error/ErrorMessage'
 import {cleanError} from 'lib/strings/errors'
 import {resetToTab} from '../../../Navigation'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['60%']
@@ -25,6 +27,7 @@ export function Component({}: {}) {
   const pal = usePalette('default')
   const theme = useTheme()
   const store = useStores()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const {isMobile} = useWebMediaQueries()
   const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
@@ -71,7 +74,7 @@ export function Component({}: {}) {
       <View style={[styles.innerContainer, pal.view]}>
         <View style={[styles.titleContainer, pal.view]}>
           <Text type="title-xl" style={[s.textCenter, pal.text]}>
-            Delete Account
+            <Trans>Delete Account</Trans>
           </Text>
           <View style={[pal.view, s.flexRow]}>
             <Text type="title-xl" style={[pal.text, s.bold]}>
@@ -95,8 +98,10 @@ export function Component({}: {}) {
         {!isEmailSent ? (
           <>
             <Text type="lg" style={[styles.description, pal.text]}>
-              For security reasons, we'll need to send a confirmation code to
-              your email address.
+              <Trans>
+                For security reasons, we'll need to send a confirmation code to
+                your email address.
+              </Trans>
             </Text>
             {error ? (
               <View style={s.mt10}>
@@ -113,7 +118,7 @@ export function Component({}: {}) {
                   style={styles.mt20}
                   onPress={onPressSendEmail}
                   accessibilityRole="button"
-                  accessibilityLabel="Send email"
+                  accessibilityLabel={_(msg`Send email`)}
                   accessibilityHint="Sends email with confirmation code for account deletion">
                   <LinearGradient
                     colors={[
@@ -124,7 +129,7 @@ export function Component({}: {}) {
                     end={{x: 1, y: 1}}
                     style={[styles.btn]}>
                     <Text type="button-lg" style={[s.white, s.bold]}>
-                      Send Email
+                      <Trans>Send Email</Trans>
                     </Text>
                   </LinearGradient>
                 </TouchableOpacity>
@@ -132,11 +137,11 @@ export function Component({}: {}) {
                   style={[styles.btn, s.mt10]}
                   onPress={onCancel}
                   accessibilityRole="button"
-                  accessibilityLabel="Cancel account deletion"
+                  accessibilityLabel={_(msg`Cancel account deletion`)}
                   accessibilityHint=""
                   onAccessibilityEscape={onCancel}>
                   <Text type="button-lg" style={pal.textLight}>
-                    Cancel
+                    <Trans>Cancel</Trans>
                   </Text>
                 </TouchableOpacity>
               </>
@@ -149,8 +154,10 @@ export function Component({}: {}) {
               type="lg"
               style={styles.description}
               nativeID="confirmationCode">
-              Check your inbox for an email with the confirmation code to enter
-              below:
+              <Trans>
+                Check your inbox for an email with the confirmation code to
+                enter below:
+              </Trans>
             </Text>
             <TextInput
               style={[styles.textInput, pal.borderDark, pal.text, styles.mb20]}
@@ -160,11 +167,11 @@ export function Component({}: {}) {
               value={confirmCode}
               onChangeText={setConfirmCode}
               accessibilityLabelledBy="confirmationCode"
-              accessibilityLabel="Confirmation code"
+              accessibilityLabel={_(msg`Confirmation code`)}
               accessibilityHint="Input confirmation code for account deletion"
             />
             <Text type="lg" style={styles.description} nativeID="password">
-              Please enter your password as well:
+              <Trans>Please enter your password as well:</Trans>
             </Text>
             <TextInput
               style={[styles.textInput, pal.borderDark, pal.text]}
@@ -175,7 +182,7 @@ export function Component({}: {}) {
               value={password}
               onChangeText={setPassword}
               accessibilityLabelledBy="password"
-              accessibilityLabel="Password"
+              accessibilityLabel={_(msg`Password`)}
               accessibilityHint="Input password for account deletion"
             />
             {error ? (
@@ -193,21 +200,21 @@ export function Component({}: {}) {
                   style={[styles.btn, styles.evilBtn, styles.mt20]}
                   onPress={onPressConfirmDelete}
                   accessibilityRole="button"
-                  accessibilityLabel="Confirm delete account"
+                  accessibilityLabel={_(msg`Confirm delete account`)}
                   accessibilityHint="">
                   <Text type="button-lg" style={[s.white, s.bold]}>
-                    Delete my account
+                    <Trans>Delete my account</Trans>
                   </Text>
                 </TouchableOpacity>
                 <TouchableOpacity
                   style={[styles.btn, s.mt10]}
                   onPress={onCancel}
                   accessibilityRole="button"
-                  accessibilityLabel="Cancel account deletion"
+                  accessibilityLabel={_(msg`Cancel account deletion`)}
                   accessibilityHint="Exits account deletion process"
                   onAccessibilityEscape={onCancel}>
                   <Text type="button-lg" style={pal.textLight}>
-                    Cancel
+                    <Trans>Cancel</Trans>
                   </Text>
                 </TouchableOpacity>
               </>
diff --git a/src/view/com/modals/EditImage.tsx b/src/view/com/modals/EditImage.tsx
index a2a458f4c..753907472 100644
--- a/src/view/com/modals/EditImage.tsx
+++ b/src/view/com/modals/EditImage.tsx
@@ -18,6 +18,8 @@ import {Slider} from '@miblanchard/react-native-slider'
 import {MaterialIcons} from '@expo/vector-icons'
 import {observer} from 'mobx-react-lite'
 import {getKeys} from 'lib/type-assertions'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['80%']
@@ -52,6 +54,7 @@ export const Component = observer(function EditImageImpl({
 }: Props) {
   const pal = usePalette('default')
   const theme = useTheme()
+  const {_} = useLingui()
   const windowDimensions = useWindowDimensions()
   const {isMobile} = useWebMediaQueries()
   const {closeModal} = useModalControls()
@@ -200,7 +203,9 @@ export const Component = observer(function EditImageImpl({
           paddingHorizontal: isMobile ? 16 : undefined,
         },
       ]}>
-      <Text style={[styles.title, pal.text]}>Edit image</Text>
+      <Text style={[styles.title, pal.text]}>
+        <Trans>Edit image</Trans>
+      </Text>
       <View style={[styles.gap18, s.flexRow]}>
         <View>
           <View
@@ -228,7 +233,7 @@ export const Component = observer(function EditImageImpl({
         <View>
           {!isMobile ? (
             <Text type="sm-bold" style={pal.text}>
-              Ratios
+              <Trans>Ratios</Trans>
             </Text>
           ) : null}
           <View style={imgControlStyles}>
@@ -263,7 +268,7 @@ export const Component = observer(function EditImageImpl({
           </View>
           {!isMobile ? (
             <Text type="sm-bold" style={[pal.text, styles.subsection]}>
-              Transformations
+              <Trans>Transformations</Trans>
             </Text>
           ) : null}
           <View style={imgControlStyles}>
@@ -291,7 +296,7 @@ export const Component = observer(function EditImageImpl({
       </View>
       <View style={[styles.gap18, styles.bottomSection, pal.border]}>
         <Text type="sm-bold" style={pal.text} nativeID="alt-text">
-          Accessibility
+          <Trans>Accessibility</Trans>
         </Text>
         <TextInput
           testID="altTextImageInput"
@@ -307,7 +312,7 @@ export const Component = observer(function EditImageImpl({
           multiline
           value={altText}
           onChangeText={text => setAltText(enforceLen(text, MAX_ALT_TEXT))}
-          accessibilityLabel="Alt text"
+          accessibilityLabel={_(msg`Alt text`)}
           accessibilityHint=""
           accessibilityLabelledBy="alt-text"
         />
@@ -315,7 +320,7 @@ export const Component = observer(function EditImageImpl({
       <View style={styles.btns}>
         <Pressable onPress={onPressCancel} accessibilityRole="button">
           <Text type="xl" style={pal.link}>
-            Cancel
+            <Trans>Cancel</Trans>
           </Text>
         </Pressable>
         <Pressable onPress={onPressSave} accessibilityRole="button">
@@ -325,7 +330,7 @@ export const Component = observer(function EditImageImpl({
             end={{x: 1, y: 1}}
             style={[styles.btn]}>
             <Text type="xl-medium" style={s.white}>
-              Done
+              <Trans>Done</Trans>
             </Text>
           </LinearGradient>
         </Pressable>
diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx
index f08bb2326..eef408e98 100644
--- a/src/view/com/modals/EditProfile.tsx
+++ b/src/view/com/modals/EditProfile.tsx
@@ -26,6 +26,8 @@ import {useAnalytics} from 'lib/analytics/analytics'
 import {cleanError, isNetworkError} from 'lib/strings/errors'
 import Animated, {FadeOut} from 'react-native-reanimated'
 import {isWeb} from 'platform/detection'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 const AnimatedTouchableOpacity =
@@ -44,6 +46,7 @@ export function Component({
   const pal = usePalette('default')
   const theme = useTheme()
   const {track} = useAnalytics()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
 
   const [isProcessing, setProcessing] = useState<boolean>(false)
@@ -151,7 +154,9 @@ export function Component({
   return (
     <KeyboardAvoidingView style={s.flex1} behavior="height">
       <ScrollView style={[pal.view]} testID="editProfileModal">
-        <Text style={[styles.title, pal.text]}>Edit my profile</Text>
+        <Text style={[styles.title, pal.text]}>
+          <Trans>Edit my profile</Trans>
+        </Text>
         <View style={styles.photos}>
           <UserBanner
             banner={userBanner}
@@ -172,7 +177,9 @@ export function Component({
         )}
         <View style={styles.form}>
           <View>
-            <Text style={[styles.label, pal.text]}>Display Name</Text>
+            <Text style={[styles.label, pal.text]}>
+              <Trans>Display Name</Trans>
+            </Text>
             <TextInput
               testID="editProfileDisplayNameInput"
               style={[styles.textInput, pal.border, pal.text]}
@@ -183,12 +190,14 @@ export function Component({
                 setDisplayName(enforceLen(v, MAX_DISPLAY_NAME))
               }
               accessible={true}
-              accessibilityLabel="Display name"
+              accessibilityLabel={_(msg`Display name`)}
               accessibilityHint="Edit your display name"
             />
           </View>
           <View style={s.pb10}>
-            <Text style={[styles.label, pal.text]}>Description</Text>
+            <Text style={[styles.label, pal.text]}>
+              <Trans>Description</Trans>
+            </Text>
             <TextInput
               testID="editProfileDescriptionInput"
               style={[styles.textArea, pal.border, pal.text]}
@@ -199,7 +208,7 @@ export function Component({
               value={description}
               onChangeText={v => setDescription(enforceLen(v, MAX_DESCRIPTION))}
               accessible={true}
-              accessibilityLabel="Description"
+              accessibilityLabel={_(msg`Description`)}
               accessibilityHint="Edit your profile description"
             />
           </View>
@@ -213,14 +222,16 @@ export function Component({
               style={s.mt10}
               onPress={onPressSave}
               accessibilityRole="button"
-              accessibilityLabel="Save"
+              accessibilityLabel={_(msg`Save`)}
               accessibilityHint="Saves any changes to your profile">
               <LinearGradient
                 colors={[gradients.blueLight.start, gradients.blueLight.end]}
                 start={{x: 0, y: 0}}
                 end={{x: 1, y: 1}}
                 style={[styles.btn]}>
-                <Text style={[s.white, s.bold]}>Save Changes</Text>
+                <Text style={[s.white, s.bold]}>
+                  <Trans>Save Changes</Trans>
+                </Text>
               </LinearGradient>
             </TouchableOpacity>
           )}
@@ -231,11 +242,13 @@ export function Component({
               style={s.mt5}
               onPress={onPressCancel}
               accessibilityRole="button"
-              accessibilityLabel="Cancel profile editing"
+              accessibilityLabel={_(msg`Cancel profile editing`)}
               accessibilityHint=""
               onAccessibilityEscape={onPressCancel}>
               <View style={[styles.btn]}>
-                <Text style={[s.black, s.bold, pal.text]}>Cancel</Text>
+                <Text style={[s.black, s.bold, pal.text]}>
+                  <Trans>Cancel</Trans>
+                </Text>
               </View>
             </AnimatedTouchableOpacity>
           )}
diff --git a/src/view/com/modals/InviteCodes.tsx b/src/view/com/modals/InviteCodes.tsx
index 227b25275..a90a9eab6 100644
--- a/src/view/com/modals/InviteCodes.tsx
+++ b/src/view/com/modals/InviteCodes.tsx
@@ -15,6 +15,7 @@ import {ScrollView} from './util'
 import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 import {useInvitesState, useInvitesAPI} from '#/state/invites'
 import {UserInfoText} from '../util/UserInfoText'
@@ -38,8 +39,10 @@ export function Component({}: {}) {
       <View style={[styles.container, pal.view]} testID="inviteCodesModal">
         <View style={[styles.empty, pal.viewLight]}>
           <Text type="lg" style={[pal.text, styles.emptyText]}>
-            You don't have any invite codes yet! We'll send you some when you've
-            been on Bluesky for a little longer.
+            <Trans>
+              You don't have any invite codes yet! We'll send you some when
+              you've been on Bluesky for a little longer.
+            </Trans>
           </Text>
         </View>
         <View style={styles.flex1} />
@@ -63,10 +66,12 @@ export function Component({}: {}) {
   return (
     <View style={[styles.container, pal.view]} testID="inviteCodesModal">
       <Text type="title-xl" style={[styles.title, pal.text]}>
-        Invite a Friend
+        <Trans>Invite a Friend</Trans>
       </Text>
       <Text type="lg" style={[styles.description, pal.text]}>
-        Each code works once. You'll receive more invite codes periodically.
+        <Trans>
+          Each code works once. You'll receive more invite codes periodically.
+        </Trans>
       </Text>
       <ScrollView style={[styles.scrollContainer, pal.border]}>
         {store.me.invites.map((invite, i) => (
@@ -138,7 +143,9 @@ const InviteCode = observer(function InviteCodeImpl({
         </Text>
         <View style={styles.flex1} />
         {!used && invitesState.copiedInvites.includes(invite.code) && (
-          <Text style={[pal.textLight, styles.codeCopied]}>Copied</Text>
+          <Text style={[pal.textLight, styles.codeCopied]}>
+            <Trans>Copied</Trans>
+          </Text>
         )}
         {!used && (
           <FontAwesomeIcon
@@ -154,7 +161,9 @@ const InviteCode = observer(function InviteCodeImpl({
             gap: 8,
             paddingTop: 6,
           }}>
-          <Text style={pal.text}>Used by:</Text>
+          <Text style={pal.text}>
+            <Trans>Used by:</Trans>
+          </Text>
           {invite.uses.map(use => (
             <Link
               key={use.usedBy}
diff --git a/src/view/com/modals/LinkWarning.tsx b/src/view/com/modals/LinkWarning.tsx
index 751c69b3f..cb86387a0 100644
--- a/src/view/com/modals/LinkWarning.tsx
+++ b/src/view/com/modals/LinkWarning.tsx
@@ -10,6 +10,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {isPossiblyAUrl, splitApexDomain} from 'lib/strings/url-helpers'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['50%']
@@ -24,6 +26,7 @@ export const Component = observer(function Component({
   const pal = usePalette('default')
   const {closeModal} = useModalControls()
   const {isMobile} = useWebMediaQueries()
+  const {_} = useLingui()
   const potentiallyMisleading = isPossiblyAUrl(text)
 
   const onPressVisit = () => {
@@ -45,26 +48,26 @@ export const Component = observer(function Component({
                 size={18}
               />
               <Text type="title-lg" style={[pal.text, styles.title]}>
-                Potentially Misleading Link
+                <Trans>Potentially Misleading Link</Trans>
               </Text>
             </>
           ) : (
             <Text type="title-lg" style={[pal.text, styles.title]}>
-              Leaving Bluesky
+              <Trans>Leaving Bluesky</Trans>
             </Text>
           )}
         </View>
 
         <View style={{gap: 10}}>
           <Text type="lg" style={pal.text}>
-            This link is taking you to the following website:
+            <Trans>This link is taking you to the following website:</Trans>
           </Text>
 
           <LinkBox href={href} />
 
           {potentiallyMisleading && (
             <Text type="lg" style={pal.text}>
-              Make sure this is where you intend to go!
+              <Trans>Make sure this is where you intend to go!</Trans>
             </Text>
           )}
         </View>
@@ -74,7 +77,7 @@ export const Component = observer(function Component({
             testID="confirmBtn"
             type="primary"
             onPress={onPressVisit}
-            accessibilityLabel="Visit Site"
+            accessibilityLabel={_(msg`Visit Site`)}
             accessibilityHint=""
             label="Visit Site"
             labelContainerStyle={{justifyContent: 'center', padding: 4}}
@@ -84,7 +87,7 @@ export const Component = observer(function Component({
             testID="cancelBtn"
             type="default"
             onPress={() => closeModal()}
-            accessibilityLabel="Cancel"
+            accessibilityLabel={_(msg`Cancel`)}
             accessibilityHint=""
             label="Cancel"
             labelContainerStyle={{justifyContent: 'center', padding: 4}}
diff --git a/src/view/com/modals/ListAddUser.tsx b/src/view/com/modals/ListAddUser.tsx
index 8864ebc78..e59ab90df 100644
--- a/src/view/com/modals/ListAddUser.tsx
+++ b/src/view/com/modals/ListAddUser.tsx
@@ -26,6 +26,8 @@ import {cleanError} from 'lib/strings/errors'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
 import {HITSLOP_20} from '#/lib/constants'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['90%']
@@ -39,6 +41,7 @@ export const Component = observer(function Component({
 }) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const {isMobile} = useWebMediaQueries()
   const [query, setQuery] = useState('')
@@ -85,7 +88,7 @@ export const Component = observer(function Component({
             value={query}
             onChangeText={onChangeQuery}
             accessible={true}
-            accessibilityLabel="Search"
+            accessibilityLabel={_(msg`Search`)}
             accessibilityHint=""
             autoFocus
             autoCapitalize="none"
@@ -97,7 +100,7 @@ export const Component = observer(function Component({
             <Pressable
               onPress={onPressCancelSearch}
               accessibilityRole="button"
-              accessibilityLabel="Cancel search"
+              accessibilityLabel={_(msg`Cancel search`)}
               accessibilityHint="Exits inputting search query"
               onAccessibilityEscape={onPressCancelSearch}
               hitSlop={HITSLOP_20}>
@@ -136,7 +139,7 @@ export const Component = observer(function Component({
                 pal.textLight,
                 {paddingHorizontal: 12, paddingVertical: 16},
               ]}>
-              No results found for {autocompleteView.prefix}
+              <Trans>No results found for {autocompleteView.prefix}</Trans>
             </Text>
           )}
         </ScrollView>
@@ -149,7 +152,7 @@ export const Component = observer(function Component({
             testID="doneBtn"
             type="default"
             onPress={() => closeModal()}
-            accessibilityLabel="Done"
+            accessibilityLabel={_(msg`Done`)}
             accessibilityHint=""
             label="Done"
             labelContainerStyle={{justifyContent: 'center', padding: 4}}
diff --git a/src/view/com/modals/Repost.tsx b/src/view/com/modals/Repost.tsx
index 13728b62b..a72da29b4 100644
--- a/src/view/com/modals/Repost.tsx
+++ b/src/view/com/modals/Repost.tsx
@@ -6,6 +6,8 @@ import {Text} from '../util/text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {RepostIcon} from 'lib/icons'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = [250]
@@ -21,6 +23,7 @@ export function Component({
   // TODO: Add author into component
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const onPress = async () => {
     closeModal()
@@ -38,7 +41,7 @@ export function Component({
           accessibilityHint={isReposted ? 'Remove repost' : 'Repost '}>
           <RepostIcon strokeWidth={2} size={24} style={s.blue3} />
           <Text type="title-lg" style={[styles.actionBtnLabel, pal.text]}>
-            {!isReposted ? 'Repost' : 'Undo repost'}
+            <Trans>{!isReposted ? 'Repost' : 'Undo repost'}</Trans>
           </Text>
         </TouchableOpacity>
         <TouchableOpacity
@@ -46,11 +49,11 @@ export function Component({
           style={[styles.actionBtn]}
           onPress={onQuote}
           accessibilityRole="button"
-          accessibilityLabel="Quote post"
+          accessibilityLabel={_(msg`Quote post`)}
           accessibilityHint="">
           <FontAwesomeIcon icon="quote-left" size={24} style={s.blue3} />
           <Text type="title-lg" style={[styles.actionBtnLabel, pal.text]}>
-            Quote Post
+            <Trans>Quote Post</Trans>
           </Text>
         </TouchableOpacity>
       </View>
@@ -58,7 +61,7 @@ export function Component({
         testID="cancelBtn"
         onPress={onPress}
         accessibilityRole="button"
-        accessibilityLabel="Cancel quote post"
+        accessibilityLabel={_(msg`Cancel quote post`)}
         accessibilityHint=""
         onAccessibilityEscape={onPress}>
         <LinearGradient
@@ -66,7 +69,9 @@ export function Component({
           start={{x: 0, y: 0}}
           end={{x: 1, y: 1}}
           style={[styles.btn]}>
-          <Text style={[s.white, s.bold, s.f18]}>Cancel</Text>
+          <Text style={[s.white, s.bold, s.f18]}>
+            <Trans>Cancel</Trans>
+          </Text>
         </LinearGradient>
       </TouchableOpacity>
     </View>
diff --git a/src/view/com/modals/SelfLabel.tsx b/src/view/com/modals/SelfLabel.tsx
index 242b6a38a..f8b64085d 100644
--- a/src/view/com/modals/SelfLabel.tsx
+++ b/src/view/com/modals/SelfLabel.tsx
@@ -9,6 +9,8 @@ import {isWeb} from 'platform/detection'
 import {Button} from '../util/forms/Button'
 import {SelectableBtn} from '../util/forms/SelectableBtn'
 import {ScrollView} from 'view/com/modals/util'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn']
@@ -28,6 +30,7 @@ export const Component = observer(function Component({
   const {closeModal} = useModalControls()
   const {isMobile} = useWebMediaQueries()
   const [selected, setSelected] = useState(labels)
+  const {_} = useLingui()
 
   const toggleAdultLabel = (label: string) => {
     const hadLabel = selected.includes(label)
@@ -51,7 +54,7 @@ export const Component = observer(function Component({
     <View testID="selfLabelModal" style={[pal.view, styles.container]}>
       <View style={styles.titleSection}>
         <Text type="title-lg" style={[pal.text, styles.title]}>
-          Add a content warning
+          <Trans>Add a content warning</Trans>
         </Text>
       </View>
 
@@ -70,7 +73,7 @@ export const Component = observer(function Component({
               paddingBottom: 8,
             }}>
             <Text type="title" style={pal.text}>
-              Adult Content
+              <Trans>Adult Content</Trans>
             </Text>
             {hasAdultSelection ? (
               <Button
@@ -78,7 +81,7 @@ export const Component = observer(function Component({
                 onPress={removeAdultLabel}
                 style={{paddingTop: 0, paddingBottom: 0, paddingRight: 0}}>
                 <Text type="md" style={pal.link}>
-                  Remove
+                  <Trans>Remove</Trans>
                 </Text>
               </Button>
             ) : null}
@@ -116,23 +119,25 @@ export const Component = observer(function Component({
 
               <Text style={[pal.text, styles.adultExplainer]}>
                 {selected.includes('sexual') ? (
-                  <>Pictures meant for adults.</>
+                  <Trans>Pictures meant for adults.</Trans>
                 ) : selected.includes('nudity') ? (
-                  <>Artistic or non-erotic nudity.</>
+                  <Trans>Artistic or non-erotic nudity.</Trans>
                 ) : selected.includes('porn') ? (
-                  <>Sexual activity or erotic nudity.</>
+                  <Trans>Sexual activity or erotic nudity.</Trans>
                 ) : (
-                  <>If none are selected, suitable for all ages.</>
+                  <Trans>If none are selected, suitable for all ages.</Trans>
                 )}
               </Text>
             </>
           ) : (
             <View>
               <Text style={[pal.textLight]}>
-                <Text type="md-bold" style={[pal.textLight]}>
-                  Not Applicable
+                <Text type="md-bold" style={[pal.textLight, s.mr5]}>
+                  <Trans>Not Applicable.</Trans>
                 </Text>
-                . This warning is only available for posts with media attached.
+                <Trans>
+                  This warning is only available for posts with media attached.
+                </Trans>
               </Text>
             </View>
           )}
@@ -147,9 +152,11 @@ export const Component = observer(function Component({
           }}
           style={styles.btn}
           accessibilityRole="button"
-          accessibilityLabel="Confirm"
+          accessibilityLabel={_(msg`Confirm`)}
           accessibilityHint="">
-          <Text style={[s.white, s.bold, s.f18]}>Done</Text>
+          <Text style={[s.white, s.bold, s.f18]}>
+            <Trans>Done</Trans>
+          </Text>
         </TouchableOpacity>
       </View>
     </View>
diff --git a/src/view/com/modals/ServerInput.tsx b/src/view/com/modals/ServerInput.tsx
index 0f8db30b6..09a460315 100644
--- a/src/view/com/modals/ServerInput.tsx
+++ b/src/view/com/modals/ServerInput.tsx
@@ -11,6 +11,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {useTheme} from 'lib/ThemeContext'
 import {LOCAL_DEV_SERVICE, STAGING_SERVICE, PROD_SERVICE} from 'state/index'
 import {LOGIN_INCLUDE_DEV_SERVERS} from 'lib/build-flags'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['80%']
@@ -19,6 +21,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
   const theme = useTheme()
   const pal = usePalette('default')
   const [customUrl, setCustomUrl] = useState<string>('')
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
 
   const doSelect = (url: string) => {
@@ -32,7 +35,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
   return (
     <View style={[pal.view, s.flex1]} testID="serverInputModal">
       <Text type="2xl-bold" style={[pal.text, s.textCenter]}>
-        Choose Service
+        <Trans>Choose Service</Trans>
       </Text>
       <ScrollView style={styles.inner}>
         <View style={styles.group}>
@@ -43,7 +46,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
                 style={styles.btn}
                 onPress={() => doSelect(LOCAL_DEV_SERVICE)}
                 accessibilityRole="button">
-                <Text style={styles.btnText}>Local dev server</Text>
+                <Text style={styles.btnText}>
+                  <Trans>Local dev server</Trans>
+                </Text>
                 <FontAwesomeIcon
                   icon="arrow-right"
                   style={s.white as FontAwesomeIconStyle}
@@ -53,7 +58,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
                 style={styles.btn}
                 onPress={() => doSelect(STAGING_SERVICE)}
                 accessibilityRole="button">
-                <Text style={styles.btnText}>Staging</Text>
+                <Text style={styles.btnText}>
+                  <Trans>Staging</Trans>
+                </Text>
                 <FontAwesomeIcon
                   icon="arrow-right"
                   style={s.white as FontAwesomeIconStyle}
@@ -65,9 +72,11 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
             style={styles.btn}
             onPress={() => doSelect(PROD_SERVICE)}
             accessibilityRole="button"
-            accessibilityLabel="Select Bluesky Social"
+            accessibilityLabel={_(msg`Select Bluesky Social`)}
             accessibilityHint="Sets Bluesky Social as your service provider">
-            <Text style={styles.btnText}>Bluesky.Social</Text>
+            <Text style={styles.btnText}>
+              <Trans>Bluesky.Social</Trans>
+            </Text>
             <FontAwesomeIcon
               icon="arrow-right"
               style={s.white as FontAwesomeIconStyle}
@@ -75,7 +84,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
           </TouchableOpacity>
         </View>
         <View style={styles.group}>
-          <Text style={[pal.text, styles.label]}>Other service</Text>
+          <Text style={[pal.text, styles.label]}>
+            <Trans>Other service</Trans>
+          </Text>
           <View style={s.flexRow}>
             <TextInput
               testID="customServerTextInput"
@@ -88,7 +99,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
               keyboardAppearance={theme.colorScheme}
               value={customUrl}
               onChangeText={setCustomUrl}
-              accessibilityLabel="Custom domain"
+              accessibilityLabel={_(msg`Custom domain`)}
               // TODO: Simplify this wording further to be understandable by everyone
               accessibilityHint="Use your domain as your Bluesky client service provider"
             />
diff --git a/src/view/com/modals/SwitchAccount.tsx b/src/view/com/modals/SwitchAccount.tsx
index d5fa32692..1d9457995 100644
--- a/src/view/com/modals/SwitchAccount.tsx
+++ b/src/view/com/modals/SwitchAccount.tsx
@@ -17,12 +17,15 @@ import {Link} from '../util/Link'
 import {makeProfileLink} from 'lib/routes/links'
 import {BottomSheetScrollView} from '@gorhom/bottom-sheet'
 import {Haptics} from 'lib/haptics'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const snapPoints = ['40%', '90%']
 
 export function Component({}: {}) {
   const pal = usePalette('default')
   const {track} = useAnalytics()
+  const {_: _lingui} = useLingui()
 
   const store = useStores()
   const [isSwitching, _, onPressSwitchAccount] = useAccountSwitcher()
@@ -41,7 +44,7 @@ export function Component({}: {}) {
       style={[styles.container, pal.view]}
       contentContainerStyle={[styles.innerContainer, pal.view]}>
       <Text type="title-xl" style={[styles.title, pal.text]}>
-        Switch Account
+        <Trans>Switch Account</Trans>
       </Text>
       {isSwitching ? (
         <View style={[pal.view, styles.linkCard]}>
@@ -65,10 +68,10 @@ export function Component({}: {}) {
               testID="signOutBtn"
               onPress={isSwitching ? undefined : onPressSignout}
               accessibilityRole="button"
-              accessibilityLabel="Sign out"
+              accessibilityLabel={_lingui(msg`Sign out`)}
               accessibilityHint={`Signs ${store.me.displayName} out of Bluesky`}>
               <Text type="lg" style={pal.link}>
-                Sign out
+                <Trans>Sign out</Trans>
               </Text>
             </TouchableOpacity>
           </View>
diff --git a/src/view/com/modals/UserAddRemoveLists.tsx b/src/view/com/modals/UserAddRemoveLists.tsx
index f86e88439..efcfc43be 100644
--- a/src/view/com/modals/UserAddRemoveLists.tsx
+++ b/src/view/com/modals/UserAddRemoveLists.tsx
@@ -21,6 +21,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb, isAndroid} from 'platform/detection'
 import isEqual from 'lodash.isequal'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['fullscreen']
@@ -39,6 +41,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
   const store = useStores()
   const {closeModal} = useModalControls()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const palPrimary = usePalette('primary')
   const palInverted = usePalette('inverted')
   const [originalSelections, setOriginalSelections] = React.useState<string[]>(
@@ -181,7 +184,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
   return (
     <View testID="userAddRemoveListsModal" style={s.hContentRegion}>
       <Text style={[styles.title, pal.text]}>
-        Update {displayName} in Lists
+        <Trans>Update {displayName} in Lists</Trans>
       </Text>
       <ListsList
         listsList={listsList}
@@ -195,7 +198,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
           type="default"
           onPress={onPressCancel}
           style={styles.footerBtn}
-          accessibilityLabel="Cancel"
+          accessibilityLabel={_(msg`Cancel`)}
           accessibilityHint=""
           onAccessibilityEscape={onPressCancel}
           label="Cancel"
@@ -206,7 +209,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
             type="primary"
             onPress={onPressSave}
             style={styles.footerBtn}
-            accessibilityLabel="Save changes"
+            accessibilityLabel={_(msg`Save changes`)}
             accessibilityHint=""
             onAccessibilityEscape={onPressSave}
             label="Save Changes"
diff --git a/src/view/com/modals/VerifyEmail.tsx b/src/view/com/modals/VerifyEmail.tsx
index 3adaffb14..e48e0e4a2 100644
--- a/src/view/com/modals/VerifyEmail.tsx
+++ b/src/view/com/modals/VerifyEmail.tsx
@@ -20,6 +20,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb} from 'platform/detection'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {cleanError} from 'lib/strings/errors'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['90%']
@@ -37,6 +39,7 @@ export const Component = observer(function Component({
 }) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const [stage, setStage] = useState<Stages>(
     showReminder ? Stages.Reminder : Stages.Email,
   )
@@ -98,21 +101,21 @@ export const Component = observer(function Component({
 
         <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
           {stage === Stages.Reminder ? (
-            <>
+            <Trans>
               Your email has not yet been verified. This is an important
               security step which we recommend.
-            </>
+            </Trans>
           ) : stage === Stages.Email ? (
-            <>
+            <Trans>
               This is important in case you ever need to change your email or
               reset your password.
-            </>
+            </Trans>
           ) : stage === Stages.ConfirmCode ? (
-            <>
+            <Trans>
               An email has been sent to{' '}
               {store.session.currentSession?.email || ''}. It includes a
               confirmation code which you can enter below.
-            </>
+            </Trans>
           ) : (
             ''
           )}
@@ -132,7 +135,7 @@ export const Component = observer(function Component({
             </View>
             <Pressable
               accessibilityRole="link"
-              accessibilityLabel="Change my email"
+              accessibilityLabel={_(msg`Change my email`)}
               accessibilityHint=""
               onPress={onEmailIncorrect}
               style={styles.changeEmailLink}>
@@ -150,7 +153,7 @@ export const Component = observer(function Component({
             value={confirmationCode}
             onChangeText={setConfirmationCode}
             accessible={true}
-            accessibilityLabel="Confirmation code"
+            accessibilityLabel={_(msg`Confirmation code`)}
             accessibilityHint=""
             autoCapitalize="none"
             autoComplete="off"
@@ -174,7 +177,7 @@ export const Component = observer(function Component({
                   testID="getStartedBtn"
                   type="primary"
                   onPress={() => setStage(Stages.Email)}
-                  accessibilityLabel="Get Started"
+                  accessibilityLabel={_(msg`Get Started`)}
                   accessibilityHint=""
                   label="Get Started"
                   labelContainerStyle={{justifyContent: 'center', padding: 4}}
@@ -187,7 +190,7 @@ export const Component = observer(function Component({
                     testID="sendEmailBtn"
                     type="primary"
                     onPress={onSendEmail}
-                    accessibilityLabel="Send Confirmation Email"
+                    accessibilityLabel={_(msg`Send Confirmation Email`)}
                     accessibilityHint=""
                     label="Send Confirmation Email"
                     labelContainerStyle={{
@@ -199,7 +202,7 @@ export const Component = observer(function Component({
                   <Button
                     testID="haveCodeBtn"
                     type="default"
-                    accessibilityLabel="I have a code"
+                    accessibilityLabel={_(msg`I have a code`)}
                     accessibilityHint=""
                     label="I have a confirmation code"
                     labelContainerStyle={{
@@ -216,7 +219,7 @@ export const Component = observer(function Component({
                   testID="confirmBtn"
                   type="primary"
                   onPress={onConfirm}
-                  accessibilityLabel="Confirm"
+                  accessibilityLabel={_(msg`Confirm`)}
                   accessibilityHint=""
                   label="Confirm"
                   labelContainerStyle={{justifyContent: 'center', padding: 4}}
diff --git a/src/view/com/modals/Waitlist.tsx b/src/view/com/modals/Waitlist.tsx
index 219bdc583..a31545c0a 100644
--- a/src/view/com/modals/Waitlist.tsx
+++ b/src/view/com/modals/Waitlist.tsx
@@ -17,6 +17,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {useTheme} from 'lib/ThemeContext'
 import {ErrorMessage} from '../util/error/ErrorMessage'
 import {cleanError} from 'lib/strings/errors'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export const snapPoints = ['80%']
@@ -24,6 +26,7 @@ export const snapPoints = ['80%']
 export function Component({}: {}) {
   const pal = usePalette('default')
   const theme = useTheme()
+  const {_} = useLingui()
   const {closeModal} = useModalControls()
   const [email, setEmail] = React.useState<string>('')
   const [isEmailSent, setIsEmailSent] = React.useState<boolean>(false)
@@ -61,12 +64,14 @@ export function Component({}: {}) {
     <View style={[styles.container, pal.view]}>
       <View style={[styles.innerContainer, pal.view]}>
         <Text type="title-xl" style={[styles.title, pal.text]}>
-          Join the waitlist
+          <Trans>Join the waitlist</Trans>
         </Text>
         <Text type="lg" style={[styles.description, pal.text]}>
-          Bluesky uses invites to build a healthier community. If you don't know
-          anybody with an invite, you can sign up for the waitlist and we'll
-          send one soon.
+          <Trans>
+            Bluesky uses invites to build a healthier community. If you don't
+            know anybody with an invite, you can sign up for the waitlist and
+            we'll send one soon.
+          </Trans>
         </Text>
         <TextInput
           style={[styles.textInput, pal.borderDark, pal.text, s.mb10, s.mt10]}
@@ -80,7 +85,7 @@ export function Component({}: {}) {
           onSubmitEditing={onPressSignup}
           enterKeyHint="done"
           accessible={true}
-          accessibilityLabel="Email"
+          accessibilityLabel={_(msg`Email`)}
           accessibilityHint="Input your email to get on the Bluesky waitlist"
         />
         {error ? (
@@ -99,7 +104,9 @@ export function Component({}: {}) {
               style={pal.text as FontAwesomeIconStyle}
             />
             <Text style={[s.ml10, pal.text]}>
-              Your email has been saved! We&apos;ll be in touch soon.
+              <Trans>
+                Your email has been saved! We&apos;ll be in touch soon.
+              </Trans>
             </Text>
           </View>
         ) : (
@@ -114,7 +121,7 @@ export function Component({}: {}) {
                 end={{x: 1, y: 1}}
                 style={[styles.btn]}>
                 <Text type="button-lg" style={[s.white, s.bold]}>
-                  Join Waitlist
+                  <Trans>Join Waitlist</Trans>
                 </Text>
               </LinearGradient>
             </TouchableOpacity>
@@ -122,11 +129,11 @@ export function Component({}: {}) {
               style={[styles.btn, s.mt10]}
               onPress={onCancel}
               accessibilityRole="button"
-              accessibilityLabel="Cancel waitlist signup"
+              accessibilityLabel={_(msg`Cancel waitlist signup`)}
               accessibilityHint={`Exits signing up for waitlist with ${email}`}
               onAccessibilityEscape={onCancel}>
               <Text type="button-lg" style={pal.textLight}>
-                Cancel
+                <Trans>Cancel</Trans>
               </Text>
             </TouchableOpacity>
           </>
diff --git a/src/view/com/modals/crop-image/CropImage.web.tsx b/src/view/com/modals/crop-image/CropImage.web.tsx
index c88d002a9..6f094a1fd 100644
--- a/src/view/com/modals/crop-image/CropImage.web.tsx
+++ b/src/view/com/modals/crop-image/CropImage.web.tsx
@@ -10,6 +10,8 @@ import {s, gradients} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {SquareIcon, RectWideIcon, RectTallIcon} from 'lib/icons'
 import {Image as RNImage} from 'react-native-image-crop-picker'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 enum AspectRatio {
@@ -35,6 +37,7 @@ export function Component({
 }) {
   const {closeModal} = useModalControls()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const [as, setAs] = React.useState<AspectRatio>(AspectRatio.Square)
   const [scale, setScale] = React.useState<number>(1)
   const editorRef = React.useRef<ImageEditor>(null)
@@ -96,7 +99,7 @@ export function Component({
         <TouchableOpacity
           onPress={doSetAs(AspectRatio.Wide)}
           accessibilityRole="button"
-          accessibilityLabel="Wide"
+          accessibilityLabel={_(msg`Wide`)}
           accessibilityHint="Sets image aspect ratio to wide">
           <RectWideIcon
             size={24}
@@ -106,7 +109,7 @@ export function Component({
         <TouchableOpacity
           onPress={doSetAs(AspectRatio.Tall)}
           accessibilityRole="button"
-          accessibilityLabel="Tall"
+          accessibilityLabel={_(msg`Tall`)}
           accessibilityHint="Sets image aspect ratio to tall">
           <RectTallIcon
             size={24}
@@ -116,7 +119,7 @@ export function Component({
         <TouchableOpacity
           onPress={doSetAs(AspectRatio.Square)}
           accessibilityRole="button"
-          accessibilityLabel="Square"
+          accessibilityLabel={_(msg`Square`)}
           accessibilityHint="Sets image aspect ratio to square">
           <SquareIcon
             size={24}
@@ -128,7 +131,7 @@ export function Component({
         <TouchableOpacity
           onPress={onPressCancel}
           accessibilityRole="button"
-          accessibilityLabel="Cancel image crop"
+          accessibilityLabel={_(msg`Cancel image crop`)}
           accessibilityHint="Exits image cropping process">
           <Text type="xl" style={pal.link}>
             Cancel
@@ -138,7 +141,7 @@ export function Component({
         <TouchableOpacity
           onPress={onPressDone}
           accessibilityRole="button"
-          accessibilityLabel="Save image crop"
+          accessibilityLabel={_(msg`Save image crop`)}
           accessibilityHint="Saves image crop settings">
           <LinearGradient
             colors={[gradients.blueLight.start, gradients.blueLight.end]}
@@ -146,7 +149,7 @@ export function Component({
             end={{x: 1, y: 1}}
             style={[styles.btn]}>
             <Text type="xl-medium" style={s.white}>
-              Done
+              <Trans>Done</Trans>
             </Text>
           </LinearGradient>
         </TouchableOpacity>
diff --git a/src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx b/src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx
index c2d0c222a..91e11a19c 100644
--- a/src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx
+++ b/src/view/com/modals/lang-settings/ConfirmLanguagesButton.tsx
@@ -4,6 +4,8 @@ import LinearGradient from 'react-native-linear-gradient'
 import {s, colors, gradients} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const ConfirmLanguagesButton = ({
   onPress,
@@ -13,6 +15,7 @@ export const ConfirmLanguagesButton = ({
   extraText?: string
 }) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
   return (
     <View
@@ -28,14 +31,16 @@ export const ConfirmLanguagesButton = ({
         testID="confirmContentLanguagesBtn"
         onPress={onPress}
         accessibilityRole="button"
-        accessibilityLabel="Confirm content language settings"
+        accessibilityLabel={_(msg`Confirm content language settings`)}
         accessibilityHint="">
         <LinearGradient
           colors={[gradients.blueLight.start, gradients.blueLight.end]}
           start={{x: 0, y: 0}}
           end={{x: 1, y: 1}}
           style={[styles.btn]}>
-          <Text style={[s.white, s.bold, s.f18]}>Done{extraText}</Text>
+          <Text style={[s.white, s.bold, s.f18]}>
+            <Trans>Done{extraText}</Trans>
+          </Text>
         </LinearGradient>
       </Pressable>
     </View>
diff --git a/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx b/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx
index 0b19abc68..b8c125b65 100644
--- a/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx
+++ b/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx
@@ -8,6 +8,7 @@ import {deviceLocales} from 'platform/detection'
 import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
 import {LanguageToggle} from './LanguageToggle'
 import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
+import {Trans} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 import {
   useLanguagePrefs,
@@ -69,12 +70,16 @@ export function Component({}: {}) {
               maxHeight: '90vh',
             },
       ]}>
-      <Text style={[pal.text, styles.title]}>Content Languages</Text>
+      <Text style={[pal.text, styles.title]}>
+        <Trans>Content Languages</Trans>
+      </Text>
       <Text style={[pal.text, styles.description]}>
-        Which languages would you like to see in your algorithmic feeds?
+        <Trans>
+          Which languages would you like to see in your algorithmic feeds?
+        </Trans>
       </Text>
       <Text style={[pal.textLight, styles.description]}>
-        Leave them all unchecked to see any language.
+        <Trans>Leave them all unchecked to see any language.</Trans>
       </Text>
       <ScrollView style={styles.scrollContainer}>
         {languages.map(lang => (
diff --git a/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx b/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx
index 7ec26ca52..7fcb24d58 100644
--- a/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx
+++ b/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx
@@ -9,6 +9,7 @@ import {deviceLocales} from 'platform/detection'
 import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
 import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
 import {ToggleButton} from 'view/com/util/forms/ToggleButton'
+import {Trans} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 import {
   useLanguagePrefs,
@@ -71,9 +72,11 @@ export const Component = observer(function PostLanguagesSettingsImpl() {
               maxHeight: '90vh',
             },
       ]}>
-      <Text style={[pal.text, styles.title]}>Post Languages</Text>
+      <Text style={[pal.text, styles.title]}>
+        <Trans>Post Languages</Trans>
+      </Text>
       <Text style={[pal.text, styles.description]}>
-        Which languages are used in this post?
+        <Trans>Which languages are used in this post?</Trans>
       </Text>
       <ScrollView style={styles.scrollContainer}>
         {languages.map(lang => {
diff --git a/src/view/com/modals/report/InputIssueDetails.tsx b/src/view/com/modals/report/InputIssueDetails.tsx
index 70a8f7b24..2f701b799 100644
--- a/src/view/com/modals/report/InputIssueDetails.tsx
+++ b/src/view/com/modals/report/InputIssueDetails.tsx
@@ -8,6 +8,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {s} from 'lib/styles'
 import {SendReportButton} from './SendReportButton'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export function InputIssueDetails({
   details,
@@ -23,6 +25,7 @@ export function InputIssueDetails({
   isProcessing: boolean
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
 
   return (
@@ -35,14 +38,16 @@ export function InputIssueDetails({
         style={[s.mb10, styles.backBtn]}
         onPress={goBack}
         accessibilityRole="button"
-        accessibilityLabel="Add details"
+        accessibilityLabel={_(msg`Add details`)}
         accessibilityHint="Add more details to your report">
         <FontAwesomeIcon size={18} icon="angle-left" style={[pal.link]} />
-        <Text style={[pal.text, s.f18, pal.link]}> Back</Text>
+        <Text style={[pal.text, s.f18, pal.link]}>
+          <Trans> Back</Trans>
+        </Text>
       </TouchableOpacity>
       <View style={[pal.btn, styles.detailsInputContainer]}>
         <TextInput
-          accessibilityLabel="Text input field"
+          accessibilityLabel={_(msg`Text input field`)}
           accessibilityHint="Enter a reason for reporting this post."
           placeholder="Enter a reason or any other details here."
           placeholderTextColor={pal.textLight.color}
diff --git a/src/view/com/modals/report/Modal.tsx b/src/view/com/modals/report/Modal.tsx
index 8dc3f53f7..5183bdc10 100644
--- a/src/view/com/modals/report/Modal.tsx
+++ b/src/view/com/modals/report/Modal.tsx
@@ -14,6 +14,8 @@ import {SendReportButton} from './SendReportButton'
 import {InputIssueDetails} from './InputIssueDetails'
 import {ReportReasonOptions} from './ReasonOptions'
 import {CollectionId} from './types'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 const DMCA_LINK = 'https://blueskyweb.xyz/support/copyright'
@@ -148,6 +150,7 @@ const SelectIssue = ({
   atUri: AtUri | null
 }) => {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const collectionName = getCollectionNameForReport(atUri)
   const onSelectIssue = (v: string) => setIssue(v)
   const goToDetails = () => {
@@ -160,9 +163,11 @@ const SelectIssue = ({
 
   return (
     <>
-      <Text style={[pal.text, styles.title]}>Report {collectionName}</Text>
+      <Text style={[pal.text, styles.title]}>
+        <Trans>Report {collectionName}</Trans>
+      </Text>
       <Text style={[pal.textLight, styles.description]}>
-        What is the issue with this {collectionName}?
+        <Trans>What is the issue with this {collectionName}?</Trans>
       </Text>
       <View style={{marginBottom: 10}}>
         <ReportReasonOptions
@@ -184,9 +189,11 @@ const SelectIssue = ({
             style={styles.addDetailsBtn}
             onPress={goToDetails}
             accessibilityRole="button"
-            accessibilityLabel="Add details"
+            accessibilityLabel={_(msg`Add details`)}
             accessibilityHint="Add more details to your report">
-            <Text style={[s.f18, pal.link]}>Add details to report</Text>
+            <Text style={[s.f18, pal.link]}>
+              <Trans>Add details to report</Trans>
+            </Text>
           </TouchableOpacity>
         </>
       ) : undefined}
diff --git a/src/view/com/modals/report/SendReportButton.tsx b/src/view/com/modals/report/SendReportButton.tsx
index 82fb65f20..40c239bff 100644
--- a/src/view/com/modals/report/SendReportButton.tsx
+++ b/src/view/com/modals/report/SendReportButton.tsx
@@ -8,6 +8,8 @@ import {
 } from 'react-native'
 import {Text} from '../../util/text/Text'
 import {s, gradients, colors} from 'lib/styles'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export function SendReportButton({
   onPress,
@@ -16,6 +18,7 @@ export function SendReportButton({
   onPress: () => void
   isProcessing: boolean
 }) {
+  const {_} = useLingui()
   // loading state
   // =
   if (isProcessing) {
@@ -31,14 +34,16 @@ export function SendReportButton({
       style={s.mt10}
       onPress={onPress}
       accessibilityRole="button"
-      accessibilityLabel="Report post"
+      accessibilityLabel={_(msg`Report post`)}
       accessibilityHint={`Reports post with reason and details`}>
       <LinearGradient
         colors={[gradients.blueLight.start, gradients.blueLight.end]}
         start={{x: 0, y: 0}}
         end={{x: 1, y: 1}}
         style={[styles.btn]}>
-        <Text style={[s.white, s.bold, s.f18]}>Send Report</Text>
+        <Text style={[s.white, s.bold, s.f18]}>
+          <Trans>Send Report</Trans>
+        </Text>
       </LinearGradient>
     </TouchableOpacity>
   )
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx
index c38ab3fd5..0387ed38d 100644
--- a/src/view/com/notifications/FeedItem.tsx
+++ b/src/view/com/notifications/FeedItem.tsx
@@ -40,6 +40,8 @@ import {formatCount} from '../util/numeric/format'
 import {makeProfileLink} from 'lib/routes/links'
 import {TimeElapsed} from '../util/TimeElapsed'
 import {isWeb} from 'platform/detection'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 const MAX_AUTHORS = 5
 
@@ -232,7 +234,9 @@ export const FeedItem = observer(function FeedItemImpl({
             />
             {authors.length > 1 ? (
               <>
-                <Text style={[pal.text]}> and </Text>
+                <Text style={[pal.text, s.mr5, s.ml5]}>
+                  <Trans>and</Trans>
+                </Text>
                 <Text style={[pal.text, s.bold]}>
                   {formatCount(authors.length - 1)}{' '}
                   {pluralize(authors.length - 1, 'other')}
@@ -292,6 +296,8 @@ function CondensedAuthorsList({
   onToggleAuthorsExpanded: () => void
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
+
   if (!visible) {
     return (
       <View style={styles.avis}>
@@ -299,7 +305,7 @@ function CondensedAuthorsList({
           style={styles.expandedAuthorsCloseBtn}
           onPress={onToggleAuthorsExpanded}
           accessibilityRole="button"
-          accessibilityLabel="Hide user list"
+          accessibilityLabel={_(msg`Hide user list`)}
           accessibilityHint="Collapses list of users for a given notification">
           <FontAwesomeIcon
             icon="angle-up"
@@ -307,7 +313,7 @@ function CondensedAuthorsList({
             style={[styles.expandedAuthorsCloseBtnIcon, pal.text]}
           />
           <Text type="sm-medium" style={pal.text}>
-            Hide
+            <Trans>Hide</Trans>
           </Text>
         </TouchableOpacity>
       </View>
@@ -328,7 +334,7 @@ function CondensedAuthorsList({
   }
   return (
     <TouchableOpacity
-      accessibilityLabel="Show users"
+      accessibilityLabel={_(msg`Show users`)}
       accessibilityHint="Opens an expanded list of users in this notification"
       onPress={onToggleAuthorsExpanded}>
       <View style={styles.avis}>
diff --git a/src/view/com/pager/FeedsTabBarMobile.tsx b/src/view/com/pager/FeedsTabBarMobile.tsx
index b33829ee5..791fe71be 100644
--- a/src/view/com/pager/FeedsTabBarMobile.tsx
+++ b/src/view/com/pager/FeedsTabBarMobile.tsx
@@ -14,6 +14,8 @@ import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
 import {s} from 'lib/styles'
 import {HITSLOP_10} from 'lib/constants'
 import Animated from 'react-native-reanimated'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
 import {useSetDrawerOpen} from '#/state/shell/drawer-open'
 
@@ -22,6 +24,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
 ) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const setDrawerOpen = useSetDrawerOpen()
   const items = useHomeTabs(store.preferences.pinnedFeeds)
   const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
@@ -45,7 +48,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
             testID="viewHeaderDrawerBtn"
             onPress={onPressAvi}
             accessibilityRole="button"
-            accessibilityLabel="Open navigation"
+            accessibilityLabel={_(msg`Open navigation`)}
             accessibilityHint="Access profile and other navigation links"
             hitSlop={HITSLOP_10}>
             <FontAwesomeIcon
@@ -64,7 +67,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
             href="/settings/home-feed"
             hitSlop={HITSLOP_10}
             accessibilityRole="button"
-            accessibilityLabel="Home Feed Preferences"
+            accessibilityLabel={_(msg`Home Feed Preferences`)}
             accessibilityHint="">
             <FontAwesomeIcon
               icon="sliders"
diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx
index 4eb47b0a3..f868c3dca 100644
--- a/src/view/com/post-thread/PostThread.tsx
+++ b/src/view/com/post-thread/PostThread.tsx
@@ -31,6 +31,8 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {NavigationProp} from 'lib/routes/types'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 const MAINTAIN_VISIBLE_CONTENT_POSITION = {minIndexForVisible: 2}
 
@@ -79,6 +81,7 @@ export const PostThread = observer(function PostThread({
   treeView: boolean
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isTablet, isDesktop} = useWebMediaQueries()
   const ref = useRef<FlatList>(null)
   const hasScrolledIntoView = useRef<boolean>(false)
@@ -197,7 +200,7 @@ export const PostThread = observer(function PostThread({
         return (
           <View style={[pal.border, pal.viewLight, styles.itemContainer]}>
             <Text type="lg-bold" style={pal.textLight}>
-              Deleted post.
+              <Trans>Deleted post.</Trans>
             </Text>
           </View>
         )
@@ -205,7 +208,7 @@ export const PostThread = observer(function PostThread({
         return (
           <View style={[pal.border, pal.viewLight, styles.itemContainer]}>
             <Text type="lg-bold" style={pal.textLight}>
-              Blocked post.
+              <Trans>Blocked post.</Trans>
             </Text>
           </View>
         )
@@ -214,7 +217,7 @@ export const PostThread = observer(function PostThread({
           <Pressable
             onPress={() => setMaxVisible(n => n + 50)}
             style={[pal.border, pal.view, styles.itemContainer]}
-            accessibilityLabel="Load more posts"
+            accessibilityLabel={_(msg`Load more posts`)}
             accessibilityHint="">
             <View
               style={[
@@ -222,7 +225,7 @@ export const PostThread = observer(function PostThread({
                 {paddingHorizontal: 18, paddingVertical: 14, borderRadius: 6},
               ]}>
               <Text type="lg-medium" style={pal.text}>
-                Load more posts
+                <Trans>Load more posts</Trans>
               </Text>
             </View>
           </Pressable>
@@ -275,6 +278,7 @@ export const PostThread = observer(function PostThread({
       posts,
       onRefresh,
       treeView,
+      _,
     ],
   )
 
@@ -302,15 +306,15 @@ export const PostThread = observer(function PostThread({
         <CenteredView>
           <View style={[pal.view, pal.border, styles.notFoundContainer]}>
             <Text type="title-lg" style={[pal.text, s.mb5]}>
-              Post not found
+              <Trans>Post not found</Trans>
             </Text>
             <Text type="md" style={[pal.text, s.mb10]}>
-              The post may have been deleted.
+              <Trans>The post may have been deleted.</Trans>
             </Text>
             <TouchableOpacity
               onPress={onPressBack}
               accessibilityRole="button"
-              accessibilityLabel="Back"
+              accessibilityLabel={_(msg`Back`)}
               accessibilityHint="">
               <Text type="2xl" style={pal.link}>
                 <FontAwesomeIcon
@@ -318,7 +322,7 @@ export const PostThread = observer(function PostThread({
                   style={[pal.link as FontAwesomeIconStyle, s.mr5]}
                   size={14}
                 />
-                Back
+                <Trans>Back</Trans>
               </Text>
             </TouchableOpacity>
           </View>
@@ -336,15 +340,18 @@ export const PostThread = observer(function PostThread({
       <CenteredView>
         <View style={[pal.view, pal.border, styles.notFoundContainer]}>
           <Text type="title-lg" style={[pal.text, s.mb5]}>
-            Post hidden
+            <Trans>Post hidden</Trans>
           </Text>
           <Text type="md" style={[pal.text, s.mb10]}>
-            You have blocked the author or you have been blocked by the author.
+            <Trans>
+              You have blocked the author or you have been blocked by the
+              author.
+            </Trans>
           </Text>
           <TouchableOpacity
             onPress={onPressBack}
             accessibilityRole="button"
-            accessibilityLabel="Back"
+            accessibilityLabel={_(msg`Back`)}
             accessibilityHint="">
             <Text type="2xl" style={pal.link}>
               <FontAwesomeIcon
@@ -352,7 +359,7 @@ export const PostThread = observer(function PostThread({
                 style={[pal.link as FontAwesomeIconStyle, s.mr5]}
                 size={14}
               />
-              Back
+              <Trans>Back</Trans>
             </Text>
           </TouchableOpacity>
         </View>
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index b72121a37..49b769e13 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -37,6 +37,7 @@ import {makeProfileLink} from 'lib/routes/links'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {MAX_POST_LINES} from 'lib/constants'
 import {logger} from '#/logger'
+import {Trans} from '@lingui/macro'
 import {useMutedThreads, useToggleThreadMute} from '#/state/muted-threads'
 import {useLanguagePrefs} from '#/state/preferences'
 
@@ -176,7 +177,9 @@ export const PostThreadItem = observer(function PostThreadItem({
           icon={['far', 'trash-can']}
           style={pal.icon as FontAwesomeIconStyle}
         />
-        <Text style={[pal.textLight, s.ml10]}>This post has been deleted.</Text>
+        <Text style={[pal.textLight, s.ml10]}>
+          <Trans>This post has been deleted.</Trans>
+        </Text>
       </View>
     )
   }
@@ -650,9 +653,11 @@ function ExpandedPostDetails({
       <Text style={pal.textLight}>{niceDate(post.indexedAt)}</Text>
       {needsTranslation && (
         <>
-          <Text style={pal.textLight}> • </Text>
+          <Text style={[pal.textLight, s.ml5, s.mr5]}>•</Text>
           <Link href={translatorUrl} title="Translate">
-            <Text style={pal.link}>Translate</Text>
+            <Text style={pal.link}>
+              <Trans>Translate</Trans>
+            </Text>
           </Link>
         </>
       )}
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 1ee209785..d7b7b8ed7 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -40,6 +40,8 @@ import {makeProfileLink} from 'lib/routes/links'
 import {Link} from '../util/Link'
 import {ProfileHeaderSuggestedFollows} from './ProfileHeaderSuggestedFollows'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 interface Props {
@@ -114,6 +116,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
   const pal = usePalette('default')
   const palInverted = usePalette('inverted')
   const store = useStores()
+  const {_} = useLingui()
   const {openModal} = useModalControls()
   const navigation = useNavigation<NavigationProp>()
   const {track} = useAnalytics()
@@ -369,10 +372,10 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
               onPress={onPressEditProfile}
               style={[styles.btn, styles.mainBtn, pal.btn]}
               accessibilityRole="button"
-              accessibilityLabel="Edit profile"
+              accessibilityLabel={_(msg`Edit profile`)}
               accessibilityHint="Opens editor for profile display name, avatar, background image, and description">
               <Text type="button" style={pal.text}>
-                Edit Profile
+                <Trans>Edit Profile</Trans>
               </Text>
             </TouchableOpacity>
           ) : view.viewer.blocking ? (
@@ -382,10 +385,10 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
                 onPress={onPressUnblockAccount}
                 style={[styles.btn, styles.mainBtn, pal.btn]}
                 accessibilityRole="button"
-                accessibilityLabel="Unblock"
+                accessibilityLabel={_(msg`Unblock`)}
                 accessibilityHint="">
                 <Text type="button" style={[pal.text, s.bold]}>
-                  Unblock
+                  <Trans>Unblock</Trans>
                 </Text>
               </TouchableOpacity>
             )
@@ -439,7 +442,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
                     size={14}
                   />
                   <Text type="button" style={pal.text}>
-                    Following
+                    <Trans>Following</Trans>
                   </Text>
                 </TouchableOpacity>
               ) : (
@@ -455,7 +458,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
                     style={[palInverted.text, s.mr5]}
                   />
                   <Text type="button" style={[palInverted.text, s.bold]}>
-                    Follow
+                    <Trans>Follow</Trans>
                   </Text>
                 </TouchableOpacity>
               )}
@@ -465,7 +468,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
             <NativeDropdown
               testID="profileHeaderDropdownBtn"
               items={dropdownItems}
-              accessibilityLabel="More options"
+              accessibilityLabel={_(msg`More options`)}
               accessibilityHint="">
               <View style={[styles.btn, styles.secondaryBtn, pal.btn]}>
                 <FontAwesomeIcon icon="ellipsis" size={20} style={[pal.text]} />
@@ -488,7 +491,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
           {view.viewer.followedBy && !blockHide ? (
             <View style={[styles.pill, pal.btn, s.mr5]}>
               <Text type="xs" style={[pal.text]}>
-                Follows you
+                <Trans>Follows you</Trans>
               </Text>
             </View>
           ) : undefined}
@@ -533,7 +536,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
                   {following}{' '}
                 </Text>
                 <Text type="md" style={[pal.textLight]}>
-                  following
+                  <Trans>following</Trans>
                 </Text>
               </Link>
               <Text type="md" style={[s.bold, pal.text]}>
@@ -572,7 +575,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
           onPress={onPressBack}
           hitSlop={BACK_HITSLOP}
           accessibilityRole="button"
-          accessibilityLabel="Back"
+          accessibilityLabel={_(msg`Back`)}
           accessibilityHint="">
           <View style={styles.backBtnWrapper}>
             <BlurView style={styles.backBtn} blurType="dark">
diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx
index 0b8015aa9..251d3141b 100644
--- a/src/view/com/profile/ProfileSubpageHeader.tsx
+++ b/src/view/com/profile/ProfileSubpageHeader.tsx
@@ -17,6 +17,8 @@ import {NavigationProp} from 'lib/routes/types'
 import {BACK_HITSLOP} from 'lib/constants'
 import {isNative} from 'platform/detection'
 import {ImagesLightbox} from 'state/models/ui/shell'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useSetDrawerOpen} from '#/state/shell'
 
 export const ProfileSubpageHeader = observer(function HeaderImpl({
@@ -45,6 +47,7 @@ export const ProfileSubpageHeader = observer(function HeaderImpl({
   const store = useStores()
   const setDrawerOpen = useSetDrawerOpen()
   const navigation = useNavigation<NavigationProp>()
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
   const pal = usePalette('default')
   const canGoBack = navigation.canGoBack()
@@ -123,7 +126,7 @@ export const ProfileSubpageHeader = observer(function HeaderImpl({
           testID="headerAviButton"
           onPress={onPressAvi}
           accessibilityRole="image"
-          accessibilityLabel="View the avatar"
+          accessibilityLabel={_(msg`View the avatar`)}
           accessibilityHint=""
           style={{width: 58}}>
           <UserAvatar type={avatarType} size={58} avatar={avatar} />
diff --git a/src/view/com/search/HeaderWithInput.tsx b/src/view/com/search/HeaderWithInput.tsx
index 1a6b427c6..04cbeab6e 100644
--- a/src/view/com/search/HeaderWithInput.tsx
+++ b/src/view/com/search/HeaderWithInput.tsx
@@ -11,6 +11,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {HITSLOP_10} from 'lib/constants'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetDrawerOpen} from '#/state/shell'
 
 interface Props {
@@ -36,6 +38,7 @@ export function HeaderWithInput({
   const setDrawerOpen = useSetDrawerOpen()
   const theme = useTheme()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {track} = useAnalytics()
   const textInput = React.useRef<TextInput>(null)
   const {isMobile} = useWebMediaQueries()
@@ -65,7 +68,7 @@ export function HeaderWithInput({
           hitSlop={HITSLOP_10}
           style={styles.headerMenuBtn}
           accessibilityRole="button"
-          accessibilityLabel="Menu"
+          accessibilityLabel={_(msg`Menu`)}
           accessibilityHint="Access navigation links and settings">
           <FontAwesomeIcon icon="bars" size={18} color={pal.colors.textLight} />
         </TouchableOpacity>
@@ -95,7 +98,7 @@ export function HeaderWithInput({
           onSubmitEditing={onSubmitQuery}
           autoFocus={false}
           accessibilityRole="search"
-          accessibilityLabel="Search"
+          accessibilityLabel={_(msg`Search`)}
           accessibilityHint=""
           autoCorrect={false}
           autoCapitalize="none"
@@ -105,7 +108,7 @@ export function HeaderWithInput({
             testID="searchTextInputClearBtn"
             onPress={onPressClearQuery}
             accessibilityRole="button"
-            accessibilityLabel="Clear search query"
+            accessibilityLabel={_(msg`Clear search query`)}
             accessibilityHint="">
             <FontAwesomeIcon
               icon="xmark"
@@ -120,7 +123,9 @@ export function HeaderWithInput({
           <TouchableOpacity
             onPress={onPressCancelSearchInner}
             accessibilityRole="button">
-            <Text style={pal.text}>Cancel</Text>
+            <Text style={pal.text}>
+              <Trans>Cancel</Trans>
+            </Text>
           </TouchableOpacity>
         </View>
       ) : undefined}
diff --git a/src/view/com/util/AccountDropdownBtn.tsx b/src/view/com/util/AccountDropdownBtn.tsx
index 29571696b..2042531e9 100644
--- a/src/view/com/util/AccountDropdownBtn.tsx
+++ b/src/view/com/util/AccountDropdownBtn.tsx
@@ -9,10 +9,14 @@ import {useStores} from 'state/index'
 import {usePalette} from 'lib/hooks/usePalette'
 import {DropdownItem, NativeDropdown} from './forms/NativeDropdown'
 import * as Toast from '../../com/util/Toast'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export function AccountDropdownBtn({handle}: {handle: string}) {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
+
   const items: DropdownItem[] = [
     {
       label: 'Remove account',
@@ -34,7 +38,7 @@ export function AccountDropdownBtn({handle}: {handle: string}) {
       <NativeDropdown
         testID="accountSettingsDropdownBtn"
         items={items}
-        accessibilityLabel="Account options"
+        accessibilityLabel={_(msg`Account options`)}
         accessibilityHint="">
         <FontAwesomeIcon
           icon="ellipsis-h"
diff --git a/src/view/com/util/BottomSheetCustomBackdrop.tsx b/src/view/com/util/BottomSheetCustomBackdrop.tsx
index 91379f1c9..ed5a2f165 100644
--- a/src/view/com/util/BottomSheetCustomBackdrop.tsx
+++ b/src/view/com/util/BottomSheetCustomBackdrop.tsx
@@ -6,6 +6,7 @@ import Animated, {
   interpolate,
   useAnimatedStyle,
 } from 'react-native-reanimated'
+import {t} from '@lingui/macro'
 
 export function createCustomBackdrop(
   onClose?: (() => void) | undefined,
@@ -29,7 +30,7 @@ export function createCustomBackdrop(
     return (
       <TouchableWithoutFeedback
         onPress={onClose}
-        accessibilityLabel="Close bottom drawer"
+        accessibilityLabel={t`Close bottom drawer`}
         accessibilityHint=""
         onAccessibilityEscape={() => {
           if (onClose !== undefined) {
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index 9db457325..9bbea1c14 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -16,6 +16,8 @@ import {isWeb, isAndroid} from 'platform/detection'
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import {UserPreviewLink} from './UserPreviewLink'
 import {DropdownItem, NativeDropdown} from './forms/NativeDropdown'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export type UserAvatarType = 'user' | 'algo' | 'list'
 
@@ -184,6 +186,7 @@ export function EditableUserAvatar({
 }: EditableUserAvatarProps) {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {requestCameraAccessIfNeeded} = useCameraPermission()
   const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
 
@@ -294,7 +297,7 @@ export function EditableUserAvatar({
     <NativeDropdown
       testID="changeAvatarBtn"
       items={dropdownItems}
-      accessibilityLabel="Image options"
+      accessibilityLabel={_(msg`Image options`)}
       accessibilityHint="">
       {avatar ? (
         <HighPriorityImage
diff --git a/src/view/com/util/UserBanner.tsx b/src/view/com/util/UserBanner.tsx
index 4bdfad06c..caae3790b 100644
--- a/src/view/com/util/UserBanner.tsx
+++ b/src/view/com/util/UserBanner.tsx
@@ -14,6 +14,8 @@ import {usePalette} from 'lib/hooks/usePalette'
 import {isWeb, isAndroid} from 'platform/detection'
 import {Image as RNImage} from 'react-native-image-crop-picker'
 import {NativeDropdown, DropdownItem} from './forms/NativeDropdown'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export function UserBanner({
   banner,
@@ -26,6 +28,7 @@ export function UserBanner({
 }) {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {requestCameraAccessIfNeeded} = useCameraPermission()
   const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
 
@@ -112,7 +115,7 @@ export function UserBanner({
     <NativeDropdown
       testID="changeBannerBtn"
       items={dropdownItems}
-      accessibilityLabel="Image options"
+      accessibilityLabel={_(msg`Image options`)}
       accessibilityHint="">
       {banner ? (
         <Image
diff --git a/src/view/com/util/error/ErrorMessage.tsx b/src/view/com/util/error/ErrorMessage.tsx
index 370f10ae3..b4adbb557 100644
--- a/src/view/com/util/error/ErrorMessage.tsx
+++ b/src/view/com/util/error/ErrorMessage.tsx
@@ -13,6 +13,8 @@ import {
 import {Text} from '../text/Text'
 import {useTheme} from 'lib/ThemeContext'
 import {usePalette} from 'lib/hooks/usePalette'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 export function ErrorMessage({
   message,
@@ -27,6 +29,7 @@ export function ErrorMessage({
 }) {
   const theme = useTheme()
   const pal = usePalette('error')
+  const {_} = useLingui()
   return (
     <View testID="errorMessageView" style={[styles.outer, pal.view, style]}>
       <View
@@ -49,7 +52,7 @@ export function ErrorMessage({
           style={styles.btn}
           onPress={onPressTryAgain}
           accessibilityRole="button"
-          accessibilityLabel="Retry"
+          accessibilityLabel={_(msg`Retry`)}
           accessibilityHint="Retries the last action, which errored out">
           <FontAwesomeIcon
             icon="arrows-rotate"
diff --git a/src/view/com/util/error/ErrorScreen.tsx b/src/view/com/util/error/ErrorScreen.tsx
index a5deeb18f..4cd6dd4b4 100644
--- a/src/view/com/util/error/ErrorScreen.tsx
+++ b/src/view/com/util/error/ErrorScreen.tsx
@@ -9,6 +9,8 @@ import {useTheme} from 'lib/ThemeContext'
 import {usePalette} from 'lib/hooks/usePalette'
 import {Button} from '../forms/Button'
 import {CenteredView} from '../Views'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export function ErrorScreen({
   title,
@@ -25,6 +27,8 @@ export function ErrorScreen({
 }) {
   const theme = useTheme()
   const pal = usePalette('default')
+  const {_} = useLingui()
+
   return (
     <CenteredView testID={testID} style={[styles.outer, pal.view]}>
       <View style={styles.errorIconContainer}>
@@ -58,7 +62,7 @@ export function ErrorScreen({
             type="default"
             style={[styles.btn]}
             onPress={onPressTryAgain}
-            accessibilityLabel="Retry"
+            accessibilityLabel={_(msg`Retry`)}
             accessibilityHint="Retries the last action, which errored out">
             <FontAwesomeIcon
               icon="arrows-rotate"
@@ -66,7 +70,7 @@ export function ErrorScreen({
               size={16}
             />
             <Text type="button" style={[styles.btnText, pal.link]}>
-              Try again
+              <Trans>Try again</Trans>
             </Text>
           </Button>
         </View>
diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx
index 1bed60b5d..ad8f50f5e 100644
--- a/src/view/com/util/forms/DropdownButton.tsx
+++ b/src/view/com/util/forms/DropdownButton.tsx
@@ -17,6 +17,8 @@ import {colors} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useTheme} from 'lib/ThemeContext'
 import {HITSLOP_10} from 'lib/constants'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 const ESTIMATED_BTN_HEIGHT = 50
 const ESTIMATED_SEP_HEIGHT = 16
@@ -207,6 +209,7 @@ const DropdownItems = ({
 }: DropDownItemProps) => {
   const pal = usePalette('default')
   const theme = useTheme()
+  const {_} = useLingui()
   const dropDownBackgroundColor =
     theme.colorScheme === 'dark' ? pal.btn : pal.view
   const separatorColor =
@@ -224,7 +227,7 @@ const DropdownItems = ({
       {/* This TouchableWithoutFeedback renders the background so if the user clicks outside, the dropdown closes */}
       <TouchableWithoutFeedback
         onPress={onOuterPress}
-        accessibilityLabel="Toggle dropdown"
+        accessibilityLabel={_(msg`Toggle dropdown`)}
         accessibilityHint="">
         <View style={[styles.bg]} />
       </TouchableWithoutFeedback>
diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx
index 45abed647..a10841450 100644
--- a/src/view/com/util/forms/PostDropdownBtn.tsx
+++ b/src/view/com/util/forms/PostDropdownBtn.tsx
@@ -9,6 +9,8 @@ import {
   DropdownItem as NativeDropdownItem,
 } from './NativeDropdown'
 import {EventStopper} from '../EventStopper'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 export function PostDropdownBtn({
@@ -38,6 +40,7 @@ export function PostDropdownBtn({
   style?: StyleProp<ViewStyle>
 }) {
   const theme = useTheme()
+  const {_} = useLingui()
   const defaultCtrlColor = theme.palette.default.postCtrl
   const {openModal} = useModalControls()
 
@@ -152,7 +155,7 @@ export function PostDropdownBtn({
       <NativeDropdown
         testID={testID}
         items={dropdownItems}
-        accessibilityLabel="More post options"
+        accessibilityLabel={_(msg`More post options`)}
         accessibilityHint="">
         <View style={style}>
           <FontAwesomeIcon icon="ellipsis" size={20} color={defaultCtrlColor} />
diff --git a/src/view/com/util/forms/SearchInput.tsx b/src/view/com/util/forms/SearchInput.tsx
index c1eb82bd4..02b462b55 100644
--- a/src/view/com/util/forms/SearchInput.tsx
+++ b/src/view/com/util/forms/SearchInput.tsx
@@ -14,6 +14,8 @@ import {
 import {MagnifyingGlassIcon} from 'lib/icons'
 import {useTheme} from 'lib/ThemeContext'
 import {usePalette} from 'lib/hooks/usePalette'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 interface Props {
   query: string
@@ -33,6 +35,7 @@ export function SearchInput({
 }: Props) {
   const theme = useTheme()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const textInput = React.useRef<TextInput>(null)
 
   const onPressCancelSearchInner = React.useCallback(() => {
@@ -58,7 +61,7 @@ export function SearchInput({
         onChangeText={onChangeQuery}
         onSubmitEditing={onSubmitQuery}
         accessibilityRole="search"
-        accessibilityLabel="Search"
+        accessibilityLabel={_(msg`Search`)}
         accessibilityHint=""
         autoCorrect={false}
         autoCapitalize="none"
@@ -67,7 +70,7 @@ export function SearchInput({
         <TouchableOpacity
           onPress={onPressCancelSearchInner}
           accessibilityRole="button"
-          accessibilityLabel="Clear search query"
+          accessibilityLabel={_(msg`Clear search query`)}
           accessibilityHint="">
           <FontAwesomeIcon
             icon="xmark"
diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx
index b6fe0dd8c..a13aae2b5 100644
--- a/src/view/com/util/moderation/ContentHider.tsx
+++ b/src/view/com/util/moderation/ContentHider.tsx
@@ -6,6 +6,8 @@ import {ModerationUI} from '@atproto/api'
 import {Text} from '../text/Text'
 import {ShieldExclamation} from 'lib/icons'
 import {describeModerationCause} from 'lib/moderation'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 export function ContentHider({
@@ -23,6 +25,7 @@ export function ContentHider({
   childContainerStyle?: StyleProp<ViewStyle>
 }>) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
   const [override, setOverride] = React.useState(false)
   const {openModal} = useModalControls()
@@ -69,7 +72,7 @@ export function ContentHider({
             })
           }}
           accessibilityRole="button"
-          accessibilityLabel="Learn more about this warning"
+          accessibilityLabel={_(msg`Learn more about this warning`)}
           accessibilityHint="">
           <ShieldExclamation size={18} style={pal.text} />
         </Pressable>
diff --git a/src/view/com/util/moderation/PostAlerts.tsx b/src/view/com/util/moderation/PostAlerts.tsx
index 2c9a71859..bc5bf9b32 100644
--- a/src/view/com/util/moderation/PostAlerts.tsx
+++ b/src/view/com/util/moderation/PostAlerts.tsx
@@ -5,6 +5,8 @@ import {Text} from '../text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {ShieldExclamation} from 'lib/icons'
 import {describeModerationCause} from 'lib/moderation'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export function PostAlerts({
@@ -16,6 +18,7 @@ export function PostAlerts({
   style?: StyleProp<ViewStyle>
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {openModal} = useModalControls()
 
   const shouldAlert = !!moderation.cause && moderation.alert
@@ -34,14 +37,14 @@ export function PostAlerts({
         })
       }}
       accessibilityRole="button"
-      accessibilityLabel="Learn more about this warning"
+      accessibilityLabel={_(msg`Learn more about this warning`)}
       accessibilityHint=""
       style={[styles.container, pal.viewLight, style]}>
       <ShieldExclamation style={pal.text} size={16} />
       <Text type="lg" style={[pal.text]}>
         {desc.name}{' '}
         <Text type="lg" style={[pal.link, styles.learnMoreBtn]}>
-          Learn More
+          <Trans>Learn More</Trans>
         </Text>
       </Text>
     </Pressable>
diff --git a/src/view/com/util/moderation/PostHider.tsx b/src/view/com/util/moderation/PostHider.tsx
index a9ccf2ebd..c2b857f54 100644
--- a/src/view/com/util/moderation/PostHider.tsx
+++ b/src/view/com/util/moderation/PostHider.tsx
@@ -8,6 +8,8 @@ import {Text} from '../text/Text'
 import {addStyle} from 'lib/styles'
 import {describeModerationCause} from 'lib/moderation'
 import {ShieldExclamation} from 'lib/icons'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 interface Props extends ComponentProps<typeof Link> {
@@ -26,6 +28,7 @@ export function PostHider({
   ...props
 }: Props) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {isMobile} = useWebMediaQueries()
   const [override, setOverride] = React.useState(false)
   const {openModal} = useModalControls()
@@ -70,7 +73,7 @@ export function PostHider({
             })
           }}
           accessibilityRole="button"
-          accessibilityLabel="Learn more about this warning"
+          accessibilityLabel={_(msg`Learn more about this warning`)}
           accessibilityHint="">
           <ShieldExclamation size={18} style={pal.text} />
         </Pressable>
diff --git a/src/view/com/util/moderation/ProfileHeaderAlerts.tsx b/src/view/com/util/moderation/ProfileHeaderAlerts.tsx
index d2406e7ae..d2675ca54 100644
--- a/src/view/com/util/moderation/ProfileHeaderAlerts.tsx
+++ b/src/view/com/util/moderation/ProfileHeaderAlerts.tsx
@@ -8,6 +8,8 @@ import {
   describeModerationCause,
   getProfileModerationCauses,
 } from 'lib/moderation'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 export function ProfileHeaderAlerts({
@@ -18,6 +20,7 @@ export function ProfileHeaderAlerts({
   style?: StyleProp<ViewStyle>
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const {openModal} = useModalControls()
 
   const causes = getProfileModerationCauses(moderation)
@@ -41,7 +44,7 @@ export function ProfileHeaderAlerts({
               })
             }}
             accessibilityRole="button"
-            accessibilityLabel="Learn more about this warning"
+            accessibilityLabel={_(msg`Learn more about this warning`)}
             accessibilityHint=""
             style={[styles.container, pal.viewLight, style]}>
             <ShieldExclamation style={pal.text} size={24} />
@@ -49,7 +52,7 @@ export function ProfileHeaderAlerts({
               {desc.name}
             </Text>
             <Text type="lg" style={[pal.link, styles.learnMoreBtn]}>
-              Learn More
+              <Trans>Learn More</Trans>
             </Text>
           </Pressable>
         )
diff --git a/src/view/com/util/moderation/ScreenHider.tsx b/src/view/com/util/moderation/ScreenHider.tsx
index c3d23b84d..946f937e9 100644
--- a/src/view/com/util/moderation/ScreenHider.tsx
+++ b/src/view/com/util/moderation/ScreenHider.tsx
@@ -18,7 +18,10 @@ import {NavigationProp} from 'lib/routes/types'
 import {Text} from '../text/Text'
 import {Button} from '../forms/Button'
 import {describeModerationCause} from 'lib/moderation'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
+import {s} from '#/lib/styles'
 
 export function ScreenHider({
   testID,
@@ -36,6 +39,7 @@ export function ScreenHider({
 }>) {
   const pal = usePalette('default')
   const palInverted = usePalette('inverted')
+  const {_} = useLingui()
   const [override, setOverride] = React.useState(false)
   const navigation = useNavigation<NavigationProp>()
   const {isMobile} = useWebMediaQueries()
@@ -62,14 +66,13 @@ export function ScreenHider({
         </View>
       </View>
       <Text type="title-2xl" style={[styles.title, pal.text]}>
-        Content Warning
+        <Trans>Content Warning</Trans>
       </Text>
       <Text type="2xl" style={[styles.description, pal.textLight]}>
-        This {screenDescription} has been flagged:{' '}
-        <Text type="2xl-medium" style={pal.text}>
-          {desc.name}
+        <Trans>This {screenDescription} has been flagged:</Trans>
+        <Text type="2xl-medium" style={[pal.text, s.ml5]}>
+          {desc.name}.
         </Text>
-        .{' '}
         <TouchableWithoutFeedback
           onPress={() => {
             openModal({
@@ -79,10 +82,10 @@ export function ScreenHider({
             })
           }}
           accessibilityRole="button"
-          accessibilityLabel="Learn more about this warning"
+          accessibilityLabel={_(msg`Learn more about this warning`)}
           accessibilityHint="">
           <Text type="2xl" style={pal.link}>
-            Learn More
+            <Trans>Learn More</Trans>
           </Text>
         </TouchableWithoutFeedback>
       </Text>
@@ -99,7 +102,7 @@ export function ScreenHider({
           }}
           style={styles.btn}>
           <Text type="button-lg" style={pal.textInverted}>
-            Go back
+            <Trans>Go back</Trans>
           </Text>
         </Button>
         {!moderation.noOverride && (
@@ -108,7 +111,7 @@ export function ScreenHider({
             onPress={() => setOverride(v => !v)}
             style={styles.btn}>
             <Text type="button-lg" style={pal.text}>
-              Show anyway
+              <Trans>Show anyway</Trans>
             </Text>
           </Button>
         )}
diff --git a/src/view/com/util/post-ctrls/RepostButton.web.tsx b/src/view/com/util/post-ctrls/RepostButton.web.tsx
index 57f544d41..70f7229d4 100644
--- a/src/view/com/util/post-ctrls/RepostButton.web.tsx
+++ b/src/view/com/util/post-ctrls/RepostButton.web.tsx
@@ -10,6 +10,8 @@ import {
   DropdownItem as NativeDropdownItem,
 } from '../forms/NativeDropdown'
 import {EventStopper} from '../EventStopper'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 
 interface Props {
   isReposted: boolean
@@ -28,6 +30,7 @@ export const RepostButton = ({
   onQuote,
 }: Props) => {
   const theme = useTheme()
+  const {_} = useLingui()
 
   const defaultControlColor = React.useMemo(
     () => ({
@@ -63,7 +66,7 @@ export const RepostButton = ({
     <EventStopper>
       <NativeDropdown
         items={dropdownItems}
-        accessibilityLabel="Repost or quote post"
+        accessibilityLabel={_(msg`Repost or quote post`)}
         accessibilityHint="">
         <View
           style={[
diff --git a/src/view/screens/AppPasswords.tsx b/src/view/screens/AppPasswords.tsx
index 338adfbaf..092f4bc2c 100644
--- a/src/view/screens/AppPasswords.tsx
+++ b/src/view/screens/AppPasswords.tsx
@@ -16,6 +16,8 @@ import {useAnalytics} from 'lib/analytics/analytics'
 import {useFocusEffect} from '@react-navigation/native'
 import {ViewHeader} from '../com/util/ViewHeader'
 import {CenteredView} from 'view/com/util/Views'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
 import {useLanguagePrefs} from '#/state/preferences'
@@ -55,8 +57,10 @@ export const AppPasswords = withAuthRequired(
           <AppPasswordsHeader />
           <View style={[styles.empty, pal.viewLight]}>
             <Text type="lg" style={[pal.text, styles.emptyText]}>
-              You have not created any app passwords yet. You can create one by
-              pressing the button below.
+              <Trans>
+                You have not created any app passwords yet. You can create one
+                by pressing the button below.
+              </Trans>
             </Text>
           </View>
           {!isTabletOrDesktop && <View style={styles.flex1} />}
@@ -146,8 +150,10 @@ function AppPasswordsHeader() {
           pal.text,
           isTabletOrDesktop && styles.descriptionDesktop,
         ]}>
-        Use app passwords to login to other Bluesky clients without giving full
-        access to your account or password.
+        <Trans>
+          Use app passwords to login to other Bluesky clients without giving
+          full access to your account or password.
+        </Trans>
       </Text>
     </>
   )
@@ -164,6 +170,7 @@ function AppPassword({
 }) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {openModal} = useModalControls()
   const {contentLanguages} = useLanguagePrefs()
 
@@ -188,7 +195,7 @@ function AppPassword({
       style={[styles.item, pal.border]}
       onPress={onDelete}
       accessibilityRole="button"
-      accessibilityLabel="Delete app password"
+      accessibilityLabel={_(msg`Delete app password`)}
       accessibilityHint="">
       <View>
         <Text type="md-bold" style={pal.text}>
diff --git a/src/view/screens/Feeds.tsx b/src/view/screens/Feeds.tsx
index 169660a8f..c2ec9208f 100644
--- a/src/view/screens/Feeds.tsx
+++ b/src/view/screens/Feeds.tsx
@@ -27,6 +27,8 @@ import {FeedSourceModel} from 'state/models/content/feed-source'
 import {FlatList} from 'view/com/util/Views'
 import {useFocusEffect} from '@react-navigation/native'
 import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetMinimalShellMode} from '#/state/shell'
 
 type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
@@ -34,6 +36,7 @@ export const FeedsScreen = withAuthRequired(
   observer<Props>(function FeedsScreenImpl({}: Props) {
     const pal = usePalette('default')
     const store = useStores()
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
     const myFeeds = store.me.myFeeds
@@ -88,12 +91,12 @@ export const FeedsScreen = withAuthRequired(
           href="/settings/saved-feeds"
           hitSlop={10}
           accessibilityRole="button"
-          accessibilityLabel="Edit Saved Feeds"
+          accessibilityLabel={_(msg`Edit Saved Feeds`)}
           accessibilityHint="Opens screen to edit Saved Feeds">
           <CogIcon size={22} strokeWidth={2} style={pal.textLight} />
         </Link>
       )
-    }, [pal])
+    }, [pal, _])
 
     const onRefresh = React.useCallback(() => {
       myFeeds.refresh()
@@ -124,11 +127,11 @@ export const FeedsScreen = withAuthRequired(
                   },
                 ]}>
                 <Text type="title-lg" style={[pal.text, s.bold]}>
-                  My Feeds
+                  <Trans>My Feeds</Trans>
                 </Text>
                 <Link
                   href="/settings/saved-feeds"
-                  accessibilityLabel="Edit My Feeds"
+                  accessibilityLabel={_(msg`Edit My Feeds`)}
                   accessibilityHint="">
                   <CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
                 </Link>
@@ -139,7 +142,7 @@ export const FeedsScreen = withAuthRequired(
         } else if (item.type === 'saved-feeds-loading') {
           return (
             <>
-              {Array.from(Array(item.numItems)).map((_, i) => (
+              {Array.from(Array(item.numItems)).map((_i, i) => (
                 <SavedFeedLoadingPlaceholder key={`placeholder-${i}`} />
               ))}
             </>
@@ -161,7 +164,7 @@ export const FeedsScreen = withAuthRequired(
                   },
                 ]}>
                 <Text type="title-lg" style={[pal.text, s.bold]}>
-                  Discover new feeds
+                  <Trans>Discover new feeds</Trans>
                 </Text>
                 {!isMobile && (
                   <SearchInput
@@ -203,14 +206,22 @@ export const FeedsScreen = withAuthRequired(
                 paddingBottom: '150%',
               }}>
               <Text type="lg" style={pal.textLight}>
-                No results found for "{query}"
+                <Trans>No results found for "{query}"</Trans>
               </Text>
             </View>
           )
         }
         return null
       },
-      [isMobile, pal, query, onChangeQuery, onPressCancelSearch, onSubmitQuery],
+      [
+        isMobile,
+        pal,
+        query,
+        onChangeQuery,
+        onPressCancelSearch,
+        onSubmitQuery,
+        _,
+      ],
     )
 
     return (
@@ -249,7 +260,7 @@ export const FeedsScreen = withAuthRequired(
           onPress={onPressCompose}
           icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
           accessibilityRole="button"
-          accessibilityLabel="New post"
+          accessibilityLabel={_(msg`New post`)}
           accessibilityHint=""
         />
       </View>
@@ -289,7 +300,7 @@ function SavedFeed({feed}: {feed: FeedSourceModel}) {
         {feed.error ? (
           <View style={[styles.offlineSlug, pal.borderDark]}>
             <Text type="xs" style={pal.textLight}>
-              Feed offline
+              <Trans>Feed offline</Trans>
             </Text>
           </View>
         ) : null}
diff --git a/src/view/screens/Log.tsx b/src/view/screens/Log.tsx
index f524279a5..69c07edae 100644
--- a/src/view/screens/Log.tsx
+++ b/src/view/screens/Log.tsx
@@ -11,6 +11,8 @@ import {Text} from '../com/util/text/Text'
 import {usePalette} from 'lib/hooks/usePalette'
 import {getEntries} from '#/logger/logDump'
 import {ago} from 'lib/strings/time'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useSetMinimalShellMode} from '#/state/shell'
 
 export const LogScreen = observer(function Log({}: NativeStackScreenProps<
@@ -18,6 +20,7 @@ export const LogScreen = observer(function Log({}: NativeStackScreenProps<
   'Log'
 >) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const setMinimalShellMode = useSetMinimalShellMode()
   const [expanded, setExpanded] = React.useState<string[]>([])
 
@@ -47,7 +50,7 @@ export const LogScreen = observer(function Log({}: NativeStackScreenProps<
                 <TouchableOpacity
                   style={[styles.entry, pal.border, pal.view]}
                   onPress={toggler(entry.id)}
-                  accessibilityLabel="View debug entry"
+                  accessibilityLabel={_(msg`View debug entry`)}
                   accessibilityHint="Opens additional details for a debug entry">
                   {entry.level === 'debug' ? (
                     <FontAwesomeIcon icon="info" />
diff --git a/src/view/screens/PreferencesHomeFeed.tsx b/src/view/screens/PreferencesHomeFeed.tsx
index 21c15931f..da99dc16f 100644
--- a/src/view/screens/PreferencesHomeFeed.tsx
+++ b/src/view/screens/PreferencesHomeFeed.tsx
@@ -14,6 +14,8 @@ import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
 import {ViewHeader} from 'view/com/util/ViewHeader'
 import {CenteredView} from 'view/com/util/Views'
 import debounce from 'lodash.debounce'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 function RepliesThresholdInput({enabled}: {enabled: boolean}) {
   const store = useStores()
@@ -66,6 +68,7 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
 }: Props) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {isTabletOrDesktop} = useWebMediaQueries()
 
   return (
@@ -84,7 +87,7 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
           isTabletOrDesktop && {paddingTop: 20, paddingBottom: 20},
         ]}>
         <Text type="xl" style={[pal.textLight, styles.description]}>
-          Fine-tune the content you see on your home screen.
+          <Trans>Fine-tune the content you see on your home screen.</Trans>
         </Text>
       </View>
 
@@ -92,10 +95,12 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
         <View style={styles.cardsContainer}>
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Show Replies
+              <Trans>Show Replies</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Set this setting to "No" to hide all replies from your feed.
+              <Trans>
+                Set this setting to "No" to hide all replies from your feed.
+              </Trans>
             </Text>
             <ToggleButton
               testID="toggleRepliesBtn"
@@ -112,10 +117,13 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
               store.preferences.homeFeed.hideReplies && styles.dimmed,
             ]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Reply Filters
+              <Trans>Reply Filters</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Enable this setting to only see replies between people you follow.
+              <Trans>
+                Enable this setting to only see replies between people you
+                follow.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -129,8 +137,10 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
               style={[s.mb10]}
             />
             <Text style={[pal.text]}>
-              Adjust the number of likes a reply must have to be shown in your
-              feed.
+              <Trans>
+                Adjust the number of likes a reply must have to be shown in your
+                feed.
+              </Trans>
             </Text>
             <RepliesThresholdInput
               enabled={!store.preferences.homeFeed.hideReplies}
@@ -139,10 +149,12 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
 
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Show Reposts
+              <Trans>Show Reposts</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Set this setting to "No" to hide all reposts from your feed.
+              <Trans>
+                Set this setting to "No" to hide all reposts from your feed.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -154,11 +166,13 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
 
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Show Quote Posts
+              <Trans>Show Quote Posts</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Set this setting to "No" to hide all quote posts from your feed.
-              Reposts will still be visible.
+              <Trans>
+                Set this setting to "No" to hide all quote posts from your feed.
+                Reposts will still be visible.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -170,12 +184,14 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
 
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              <FontAwesomeIcon icon="flask" color={pal.colors.text} /> Show
-              Posts from My Feeds
+              <FontAwesomeIcon icon="flask" color={pal.colors.text} />
+              <Trans>Show Posts from My Feeds</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Set this setting to "Yes" to show samples of your saved feeds in
-              your following feed. This is an experimental feature.
+              <Trans>
+                Set this setting to "Yes" to show samples of your saved feeds in
+                your following feed. This is an experimental feature.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -204,9 +220,11 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
           }}
           style={[styles.btn, isTabletOrDesktop && styles.btnDesktop]}
           accessibilityRole="button"
-          accessibilityLabel="Confirm"
+          accessibilityLabel={_(msg`Confirm`)}
           accessibilityHint="">
-          <Text style={[s.white, s.bold, s.f18]}>Done</Text>
+          <Text style={[s.white, s.bold, s.f18]}>
+            <Trans>Done</Trans>
+          </Text>
         </TouchableOpacity>
       </View>
     </CenteredView>
diff --git a/src/view/screens/PreferencesThreads.tsx b/src/view/screens/PreferencesThreads.tsx
index af98a1833..8a2db13ce 100644
--- a/src/view/screens/PreferencesThreads.tsx
+++ b/src/view/screens/PreferencesThreads.tsx
@@ -12,6 +12,8 @@ import {RadioGroup} from 'view/com/util/forms/RadioGroup'
 import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
 import {ViewHeader} from 'view/com/util/ViewHeader'
 import {CenteredView} from 'view/com/util/Views'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'PreferencesThreads'>
 export const PreferencesThreads = observer(function PreferencesThreadsImpl({
@@ -19,6 +21,7 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
 }: Props) {
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const {isTabletOrDesktop} = useWebMediaQueries()
 
   return (
@@ -37,7 +40,7 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
           isTabletOrDesktop && {paddingTop: 20, paddingBottom: 20},
         ]}>
         <Text type="xl" style={[pal.textLight, styles.description]}>
-          Fine-tune the discussion threads.
+          <Trans>Fine-tune the discussion threads.</Trans>
         </Text>
       </View>
 
@@ -45,10 +48,10 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
         <View style={styles.cardsContainer}>
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Sort Replies
+              <Trans>Sort Replies</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Sort replies to the same post by:
+              <Trans>Sort replies to the same post by:</Trans>
             </Text>
             <View style={[pal.view, {borderRadius: 8, paddingVertical: 6}]}>
               <RadioGroup
@@ -67,10 +70,12 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
 
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              Prioritize Your Follows
+              <Trans>Prioritize Your Follows</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Show replies by people you follow before all other replies.
+              <Trans>
+                Show replies by people you follow before all other replies.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -84,12 +89,14 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
 
           <View style={[pal.viewLight, styles.card]}>
             <Text type="title-sm" style={[pal.text, s.pb5]}>
-              <FontAwesomeIcon icon="flask" color={pal.colors.text} /> Threaded
-              Mode
+              <FontAwesomeIcon icon="flask" color={pal.colors.text} />{' '}
+              <Trans>Threaded Mode</Trans>
             </Text>
             <Text style={[pal.text, s.pb10]}>
-              Set this setting to "Yes" to show replies in a threaded view. This
-              is an experimental feature.
+              <Trans>
+                Set this setting to "Yes" to show replies in a threaded view.
+                This is an experimental feature.
+              </Trans>
             </Text>
             <ToggleButton
               type="default-light"
@@ -118,9 +125,11 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
           }}
           style={[styles.btn, isTabletOrDesktop && styles.btnDesktop]}
           accessibilityRole="button"
-          accessibilityLabel="Confirm"
+          accessibilityLabel={_(msg`Confirm`)}
           accessibilityHint="">
-          <Text style={[s.white, s.bold, s.f18]}>Done</Text>
+          <Text style={[s.white, s.bold, s.f18]}>
+            <Trans>Done</Trans>
+          </Text>
         </TouchableOpacity>
       </View>
     </CenteredView>
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 9a25612ad..f2aa7f05d 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -30,6 +30,8 @@ import {FeedSourceModel} from 'state/models/content/feed-source'
 import {useSetTitle} from 'lib/hooks/useSetTitle'
 import {combinedDisplayName} from 'lib/strings/display-names'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetMinimalShellMode} from '#/state/shell'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
@@ -38,6 +40,7 @@ export const ProfileScreen = withAuthRequired(
     const store = useStores()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {screen, track} = useAnalytics()
+    const {_} = useLingui()
     const viewSelectorRef = React.useRef<ViewSelectorHandle>(null)
     const name = route.params.name === 'me' ? store.me.did : route.params.name
 
@@ -206,7 +209,11 @@ export const ProfileScreen = withAuthRequired(
           // if section is posts or posts & replies
         } else {
           if (item === ProfileUiModel.END_ITEM) {
-            return <Text style={styles.endItem}>- end of feed -</Text>
+            return (
+              <Text style={styles.endItem}>
+                <Trans>- end of feed -</Trans>
+              </Text>
+            )
           } else if (item === ProfileUiModel.LOADING_ITEM) {
             return <PostFeedLoadingPlaceholder />
           } else if (item._reactKey === '__error__') {
@@ -296,7 +303,7 @@ export const ProfileScreen = withAuthRequired(
           onPress={onPressCompose}
           icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
           accessibilityRole="button"
-          accessibilityLabel="New post"
+          accessibilityLabel={_(msg`New post`)}
           accessibilityHint=""
         />
       </ScreenHider>
diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx
index 3d1081642..8a8851c97 100644
--- a/src/view/screens/ProfileFeed.tsx
+++ b/src/view/screens/ProfileFeed.tsx
@@ -47,6 +47,8 @@ import {sanitizeHandle} from 'lib/strings/handles'
 import {makeProfileLink} from 'lib/routes/links'
 import {ComposeIcon2} from 'lib/icons'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useModalControls} from '#/state/modals'
 
 const SECTION_TITLES = ['Posts', 'About']
@@ -60,6 +62,7 @@ export const ProfileFeedScreen = withAuthRequired(
   observer(function ProfileFeedScreenImpl(props: Props) {
     const pal = usePalette('default')
     const store = useStores()
+    const {_} = useLingui()
     const navigation = useNavigation<NavigationProp>()
 
     const {name: handleOrDid} = props.route.params
@@ -98,7 +101,7 @@ export const ProfileFeedScreen = withAuthRequired(
         <CenteredView>
           <View style={[pal.view, pal.border, styles.notFoundContainer]}>
             <Text type="title-lg" style={[pal.text, s.mb10]}>
-              Could not load feed
+              <Trans>Could not load feed</Trans>
             </Text>
             <Text type="md" style={[pal.text, s.mb20]}>
               {error}
@@ -107,12 +110,12 @@ export const ProfileFeedScreen = withAuthRequired(
             <View style={{flexDirection: 'row'}}>
               <Button
                 type="default"
-                accessibilityLabel="Go Back"
+                accessibilityLabel={_(msg`Go Back`)}
                 accessibilityHint="Return to previous page"
                 onPress={onPressBack}
                 style={{flexShrink: 1}}>
                 <Text type="button" style={pal.text}>
-                  Go Back
+                  <Trans>Go Back</Trans>
                 </Text>
               </Button>
             </View>
@@ -142,6 +145,7 @@ export const ProfileFeedScreenInner = observer(
     const pal = usePalette('default')
     const store = useStores()
     const {track} = useAnalytics()
+    const {_} = useLingui()
     const feedSectionRef = React.useRef<SectionRef>(null)
     const {rkey, name: handleOrDid} = route.params
     const uri = useMemo(
@@ -313,7 +317,7 @@ export const ProfileFeedScreenInner = observer(
           <NativeDropdown
             testID="headerDropdownBtn"
             items={dropdownItems}
-            accessibilityLabel="More options"
+            accessibilityLabel={_(msg`More options`)}
             accessibilityHint="">
             <View style={[pal.viewLight, styles.btn]}>
               <FontAwesomeIcon
@@ -334,6 +338,7 @@ export const ProfileFeedScreenInner = observer(
       onTogglePinned,
       onToggleSaved,
       dropdownItems,
+      _,
     ])
 
     return (
@@ -374,7 +379,7 @@ export const ProfileFeedScreenInner = observer(
             />
           }
           accessibilityRole="button"
-          accessibilityLabel="New post"
+          accessibilityLabel={_(msg`New post`)}
           accessibilityHint=""
         />
       </View>
@@ -448,6 +453,7 @@ const AboutSection = observer(function AboutPageImpl({
   onScroll: (e: NativeScrollEvent) => void
 }) {
   const pal = usePalette('default')
+  const {_} = useLingui()
   const scrollHandler = useAnimatedScrollHandler({onScroll})
 
   if (!feedInfo) {
@@ -478,14 +484,14 @@ const AboutSection = observer(function AboutPageImpl({
           />
         ) : (
           <Text type="lg" style={[{fontStyle: 'italic'}, pal.textLight]}>
-            No description
+            <Trans>No description</Trans>
           </Text>
         )}
         <View style={{flexDirection: 'row', alignItems: 'center', gap: 10}}>
           <Button
             type="default"
             testID="toggleLikeBtn"
-            accessibilityLabel="Like this feed"
+            accessibilityLabel={_(msg`Like this feed`)}
             accessibilityHint=""
             onPress={onToggleLiked}
             style={{paddingHorizontal: 10}}>
diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx
index a165502b7..0bbb512c1 100644
--- a/src/view/screens/ProfileList.tsx
+++ b/src/view/screens/ProfileList.tsx
@@ -45,6 +45,8 @@ import {makeProfileLink, makeListLink} from 'lib/routes/links'
 import {ComposeIcon2} from 'lib/icons'
 import {ListItems} from 'view/com/lists/ListItems'
 import {logger} from '#/logger'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
 
@@ -107,6 +109,7 @@ export const ProfileListScreenInner = observer(
     listOwnerDid,
   }: Props & {listOwnerDid: string}) {
     const store = useStores()
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {rkey} = route.params
     const feedSectionRef = React.useRef<SectionRef>(null)
@@ -208,7 +211,7 @@ export const ProfileListScreenInner = observer(
               />
             }
             accessibilityRole="button"
-            accessibilityLabel="New post"
+            accessibilityLabel={_(msg`New post`)}
             accessibilityHint=""
           />
         </View>
@@ -246,7 +249,7 @@ export const ProfileListScreenInner = observer(
               />
             }
             accessibilityRole="button"
-            accessibilityLabel="New post"
+            accessibilityLabel={_(msg`New post`)}
             accessibilityHint=""
           />
         </View>
@@ -270,6 +273,7 @@ const Header = observer(function HeaderImpl({
 }) {
   const pal = usePalette('default')
   const palInverted = usePalette('inverted')
+  const {_} = useLingui()
   const navigation = useNavigation<NavigationProp>()
   const {openModal, closeModal} = useModalControls()
 
@@ -526,10 +530,12 @@ const Header = observer(function HeaderImpl({
           <NativeDropdown
             testID="subscribeBtn"
             items={subscribeDropdownItems}
-            accessibilityLabel="Subscribe to this list"
+            accessibilityLabel={_(msg`Subscribe to this list`)}
             accessibilityHint="">
             <View style={[palInverted.view, styles.btn]}>
-              <Text style={palInverted.text}>Subscribe</Text>
+              <Text style={palInverted.text}>
+                <Trans>Subscribe</Trans>
+              </Text>
             </View>
           </NativeDropdown>
         )
@@ -537,7 +543,7 @@ const Header = observer(function HeaderImpl({
       <NativeDropdown
         testID="headerDropdownBtn"
         items={dropdownItems}
-        accessibilityLabel="More options"
+        accessibilityLabel={_(msg`More options`)}
         accessibilityHint="">
         <View style={[pal.viewLight, styles.btn]}>
           <FontAwesomeIcon icon="ellipsis" size={20} color={pal.colors.text} />
@@ -624,6 +630,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
     ref,
   ) {
     const pal = usePalette('default')
+    const {_} = useLingui()
     const {isMobile} = useWebMediaQueries()
     const scrollElRef = React.useRef<FlatList>(null)
 
@@ -662,7 +669,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
                 testID="listDescriptionEmpty"
                 type="lg"
                 style={[{fontStyle: 'italic'}, pal.textLight]}>
-                No description
+                <Trans>No description</Trans>
               </Text>
             )}
             <Text type="md" style={[pal.textLight]} numberOfLines={1}>
@@ -688,12 +695,14 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
                 paddingBottom: isMobile ? 14 : 18,
               },
             ]}>
-            <Text type="lg-bold">Users</Text>
+            <Text type="lg-bold">
+              <Trans>Users</Trans>
+            </Text>
             {isOwner && (
               <Pressable
                 testID="addUserBtn"
                 accessibilityRole="button"
-                accessibilityLabel="Add a user to this list"
+                accessibilityLabel={_(msg`Add a user to this list`)}
                 accessibilityHint=""
                 onPress={onPressAddUser}
                 style={{flexDirection: 'row', alignItems: 'center', gap: 6}}>
@@ -702,7 +711,9 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
                   color={pal.colors.link}
                   size={16}
                 />
-                <Text style={pal.link}>Add</Text>
+                <Text style={pal.link}>
+                  <Trans>Add</Trans>
+                </Text>
               </Pressable>
             )}
           </View>
@@ -717,6 +728,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
       isCurateList,
       isOwner,
       onPressAddUser,
+      _,
     ])
 
     const renderEmptyState = useCallback(() => {
@@ -757,6 +769,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
 function ErrorScreen({error}: {error: string}) {
   const pal = usePalette('default')
   const navigation = useNavigation<NavigationProp>()
+  const {_} = useLingui()
   const onPressBack = useCallback(() => {
     if (navigation.canGoBack()) {
       navigation.goBack()
@@ -778,7 +791,7 @@ function ErrorScreen({error}: {error: string}) {
         },
       ]}>
       <Text type="title-lg" style={[pal.text, s.mb10]}>
-        Could not load list
+        <Trans>Could not load list</Trans>
       </Text>
       <Text type="md" style={[pal.text, s.mb20]}>
         {error}
@@ -787,12 +800,12 @@ function ErrorScreen({error}: {error: string}) {
       <View style={{flexDirection: 'row'}}>
         <Button
           type="default"
-          accessibilityLabel="Go Back"
+          accessibilityLabel={_(msg`Go Back`)}
           accessibilityHint="Return to previous page"
           onPress={onPressBack}
           style={{flexShrink: 1}}>
           <Text type="button" style={pal.text}>
-            Go Back
+            <Trans>Go Back</Trans>
           </Text>
         </Button>
       </View>
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index f912996ef..010de23db 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -63,6 +63,8 @@ import {
 // -prf
 import {useDebugHeaderSetting} from 'lib/api/debug-appview-proxy-header'
 import {STATUS_PAGE_URL} from 'lib/constants'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
 export const SettingsScreen = withAuthRequired(
@@ -71,6 +73,7 @@ export const SettingsScreen = withAuthRequired(
     const setColorMode = useSetColorMode()
     const pal = usePalette('default')
     const store = useStores()
+    const {_} = useLingui()
     const setMinimalShellMode = useSetMinimalShellMode()
     const requireAltTextEnabled = useRequireAltTextEnabled()
     const setRequireAltTextEnabled = useSetRequireAltTextEnabled()
@@ -213,7 +216,7 @@ export const SettingsScreen = withAuthRequired(
           {store.session.currentSession !== undefined ? (
             <>
               <Text type="xl-bold" style={[pal.text, styles.heading]}>
-                Account
+                <Trans>Account</Trans>
               </Text>
               <View style={[styles.infoLine]}>
                 <Text type="lg-medium" style={pal.text}>
@@ -233,17 +236,17 @@ export const SettingsScreen = withAuthRequired(
                 </Text>
                 <Link onPress={() => openModal({name: 'change-email'})}>
                   <Text type="lg" style={pal.link}>
-                    Change
+                    <Trans>Change</Trans>
                   </Text>
                 </Link>
               </View>
               <View style={[styles.infoLine]}>
                 <Text type="lg-medium" style={pal.text}>
-                  Birthday:{' '}
+                  <Trans>Birthday: </Trans>
                 </Text>
                 <Link onPress={() => openModal({name: 'birth-date-settings'})}>
                   <Text type="lg" style={pal.link}>
-                    Show
+                    <Trans>Show</Trans>
                   </Text>
                 </Link>
               </View>
@@ -253,7 +256,7 @@ export const SettingsScreen = withAuthRequired(
           ) : null}
           <View style={[s.flexRow, styles.heading]}>
             <Text type="xl-bold" style={pal.text}>
-              Signed in as
+              <Trans>Signed in as</Trans>
             </Text>
             <View style={s.flex1} />
           </View>
@@ -282,10 +285,10 @@ export const SettingsScreen = withAuthRequired(
                   testID="signOutBtn"
                   onPress={isSwitching ? undefined : onPressSignout}
                   accessibilityRole="button"
-                  accessibilityLabel="Sign out"
+                  accessibilityLabel={_(msg`Sign out`)}
                   accessibilityHint={`Signs ${store.me.displayName} out of Bluesky`}>
                   <Text type="lg" style={pal.link}>
-                    Sign out
+                    <Trans>Sign out</Trans>
                   </Text>
                 </TouchableOpacity>
               </View>
@@ -321,7 +324,7 @@ export const SettingsScreen = withAuthRequired(
             style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
             onPress={isSwitching ? undefined : onPressAddAccount}
             accessibilityRole="button"
-            accessibilityLabel="Add account"
+            accessibilityLabel={_(msg`Add account`)}
             accessibilityHint="Create a new Bluesky account">
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
@@ -330,21 +333,21 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text}>
-              Add account
+              <Trans>Add account</Trans>
             </Text>
           </TouchableOpacity>
 
           <View style={styles.spacer20} />
 
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Invite a Friend
+            <Trans>Invite a Friend</Trans>
           </Text>
           <TouchableOpacity
             testID="inviteFriendBtn"
             style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
             onPress={isSwitching ? undefined : onPressInviteCodes}
             accessibilityRole="button"
-            accessibilityLabel="Invite"
+            accessibilityLabel={_(msg`Invite`)}
             accessibilityHint="Opens invite code list">
             <View
               style={[
@@ -371,7 +374,7 @@ export const SettingsScreen = withAuthRequired(
           <View style={styles.spacer20} />
 
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Accessibility
+            <Trans>Accessibility</Trans>
           </Text>
           <View style={[pal.view, styles.toggleCard]}>
             <ToggleButton
@@ -386,7 +389,7 @@ export const SettingsScreen = withAuthRequired(
           <View style={styles.spacer20} />
 
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Appearance
+            <Trans>Appearance</Trans>
           </Text>
           <View>
             <View style={[styles.linkCard, pal.view, styles.selectableBtns]}>
@@ -415,7 +418,7 @@ export const SettingsScreen = withAuthRequired(
           <View style={styles.spacer20} />
 
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Basics
+            <Trans>Basics</Trans>
           </Text>
           <TouchableOpacity
             testID="preferencesHomeFeedButton"
@@ -423,7 +426,7 @@ export const SettingsScreen = withAuthRequired(
             onPress={openHomeFeedPreferences}
             accessibilityRole="button"
             accessibilityHint=""
-            accessibilityLabel="Opens the home feed preferences">
+            accessibilityLabel={_(msg`Opens the home feed preferences`)}>
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
                 icon="sliders"
@@ -431,7 +434,7 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text}>
-              Home Feed Preferences
+              <Trans>Home Feed Preferences</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
@@ -440,7 +443,7 @@ export const SettingsScreen = withAuthRequired(
             onPress={openThreadsPreferences}
             accessibilityRole="button"
             accessibilityHint=""
-            accessibilityLabel="Opens the threads preferences">
+            accessibilityLabel={_(msg`Opens the threads preferences`)}>
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
                 icon={['far', 'comments']}
@@ -449,20 +452,20 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text}>
-              Thread Preferences
+              <Trans>Thread Preferences</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
             testID="savedFeedsBtn"
             style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
             accessibilityHint="My Saved Feeds"
-            accessibilityLabel="Opens screen with all saved feeds"
+            accessibilityLabel={_(msg`Opens screen with all saved feeds`)}
             onPress={onPressSavedFeeds}>
             <View style={[styles.iconContainer, pal.btn]}>
               <HashtagIcon style={pal.text} size={18} strokeWidth={3} />
             </View>
             <Text type="lg" style={pal.text}>
-              My Saved Feeds
+              <Trans>My Saved Feeds</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
@@ -471,7 +474,7 @@ export const SettingsScreen = withAuthRequired(
             onPress={isSwitching ? undefined : onPressLanguageSettings}
             accessibilityRole="button"
             accessibilityHint="Language settings"
-            accessibilityLabel="Opens configurable language settings">
+            accessibilityLabel={_(msg`Opens configurable language settings`)}>
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
                 icon="language"
@@ -479,7 +482,7 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text}>
-              Languages
+              <Trans>Languages</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
@@ -490,18 +493,18 @@ export const SettingsScreen = withAuthRequired(
             }
             accessibilityRole="button"
             accessibilityHint=""
-            accessibilityLabel="Opens moderation settings">
+            accessibilityLabel={_(msg`Opens moderation settings`)}>
             <View style={[styles.iconContainer, pal.btn]}>
               <HandIcon style={pal.text} size={18} strokeWidth={6} />
             </View>
             <Text type="lg" style={pal.text}>
-              Moderation
+              <Trans>Moderation</Trans>
             </Text>
           </TouchableOpacity>
           <View style={styles.spacer20} />
 
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Advanced
+            <Trans>Advanced</Trans>
           </Text>
           <TouchableOpacity
             testID="appPasswordBtn"
@@ -509,7 +512,7 @@ export const SettingsScreen = withAuthRequired(
             onPress={onPressAppPasswords}
             accessibilityRole="button"
             accessibilityHint="Open app password settings"
-            accessibilityLabel="Opens the app password settings page">
+            accessibilityLabel={_(msg`Opens the app password settings page`)}>
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
                 icon="lock"
@@ -517,7 +520,7 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text}>
-              App passwords
+              <Trans>App passwords</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
@@ -525,7 +528,7 @@ export const SettingsScreen = withAuthRequired(
             style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
             onPress={isSwitching ? undefined : onPressChangeHandle}
             accessibilityRole="button"
-            accessibilityLabel="Change handle"
+            accessibilityLabel={_(msg`Change handle`)}
             accessibilityHint="Choose a new Bluesky username or create">
             <View style={[styles.iconContainer, pal.btn]}>
               <FontAwesomeIcon
@@ -534,19 +537,19 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={pal.text} numberOfLines={1}>
-              Change handle
+              <Trans>Change handle</Trans>
             </Text>
           </TouchableOpacity>
           <View style={styles.spacer20} />
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Danger Zone
+            <Trans>Danger Zone</Trans>
           </Text>
           <TouchableOpacity
             style={[pal.view, styles.linkCard]}
             onPress={onPressDeleteAccount}
             accessible={true}
             accessibilityRole="button"
-            accessibilityLabel="Delete account"
+            accessibilityLabel={_(msg`Delete account`)}
             accessibilityHint="Opens modal for account deletion confirmation. Requires email code.">
             <View style={[styles.iconContainer, dangerBg]}>
               <FontAwesomeIcon
@@ -556,21 +559,21 @@ export const SettingsScreen = withAuthRequired(
               />
             </View>
             <Text type="lg" style={dangerText}>
-              Delete my account…
+              <Trans>Delete my account…</Trans>
             </Text>
           </TouchableOpacity>
           <View style={styles.spacer20} />
           <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Developer Tools
+            <Trans>Developer Tools</Trans>
           </Text>
           <TouchableOpacity
             style={[pal.view, styles.linkCardNoIcon]}
             onPress={onPressSystemLog}
             accessibilityRole="button"
             accessibilityHint="Open system log"
-            accessibilityLabel="Opens the system log page">
+            accessibilityLabel={_(msg`Opens the system log page`)}>
             <Text type="lg" style={pal.text}>
-              System log
+              <Trans>System log</Trans>
             </Text>
           </TouchableOpacity>
           {__DEV__ ? (
@@ -588,9 +591,9 @@ export const SettingsScreen = withAuthRequired(
                 onPress={onPressStorybook}
                 accessibilityRole="button"
                 accessibilityHint="Open storybook page"
-                accessibilityLabel="Opens the storybook page">
+                accessibilityLabel={_(msg`Opens the storybook page`)}>
                 <Text type="lg" style={pal.text}>
-                  Storybook
+                  <Trans>Storybook</Trans>
                 </Text>
               </TouchableOpacity>
               <TouchableOpacity
@@ -598,9 +601,9 @@ export const SettingsScreen = withAuthRequired(
                 onPress={onPressResetPreferences}
                 accessibilityRole="button"
                 accessibilityHint="Reset preferences"
-                accessibilityLabel="Resets the preferences state">
+                accessibilityLabel={_(msg`Resets the preferences state`)}>
                 <Text type="lg" style={pal.text}>
-                  Reset preferences state
+                  <Trans>Reset preferences state</Trans>
                 </Text>
               </TouchableOpacity>
               <TouchableOpacity
@@ -608,9 +611,9 @@ export const SettingsScreen = withAuthRequired(
                 onPress={onPressResetOnboarding}
                 accessibilityRole="button"
                 accessibilityHint="Reset onboarding"
-                accessibilityLabel="Resets the onboarding state">
+                accessibilityLabel={_(msg`Resets the onboarding state`)}>
                 <Text type="lg" style={pal.text}>
-                  Reset onboarding state
+                  <Trans>Reset onboarding state</Trans>
                 </Text>
               </TouchableOpacity>
             </>
@@ -620,7 +623,9 @@ export const SettingsScreen = withAuthRequired(
               accessibilityRole="button"
               onPress={onPressBuildInfo}>
               <Text type="sm" style={[styles.buildInfo, pal.textLight]}>
-                Build version {AppInfo.appVersion} {AppInfo.updateChannel}
+                <Trans>
+                  Build version {AppInfo.appVersion} {AppInfo.updateChannel}
+                </Trans>
               </Text>
             </TouchableOpacity>
             <Text type="sm" style={[pal.textLight]}>
@@ -630,7 +635,7 @@ export const SettingsScreen = withAuthRequired(
               accessibilityRole="button"
               onPress={onPressStatusPage}>
               <Text type="sm" style={[styles.buildInfo, pal.textLight]}>
-                Status page
+                <Trans>Status page</Trans>
               </Text>
             </TouchableOpacity>
           </View>
@@ -646,6 +651,7 @@ const EmailConfirmationNotice = observer(
     const pal = usePalette('default')
     const palInverted = usePalette('inverted')
     const store = useStores()
+    const {_} = useLingui()
     const {isMobile} = useWebMediaQueries()
     const {openModal} = useModalControls()
 
@@ -656,7 +662,7 @@ const EmailConfirmationNotice = observer(
     return (
       <View style={{marginBottom: 20}}>
         <Text type="xl-bold" style={[pal.text, styles.heading]}>
-          Verify email
+          <Trans>Verify email</Trans>
         </Text>
         <View
           style={[
@@ -681,7 +687,7 @@ const EmailConfirmationNotice = observer(
                 isMobile && {flex: 1},
               ]}
               accessibilityRole="button"
-              accessibilityLabel="Verify my email"
+              accessibilityLabel={_(msg`Verify my email`)}
               accessibilityHint=""
               onPress={() => openModal({name: 'verify-email'})}>
               <FontAwesomeIcon
@@ -690,12 +696,12 @@ const EmailConfirmationNotice = observer(
                 size={16}
               />
               <Text type="button" style={palInverted.text}>
-                Verify My Email
+                <Trans>Verify My Email</Trans>
               </Text>
             </Pressable>
           </View>
           <Text style={pal.textLight}>
-            Protect your account by verifying your email.
+            <Trans>Protect your account by verifying your email.</Trans>
           </Text>
         </View>
       </View>
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index c8b3e0917..99e1d7d98 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -43,6 +43,8 @@ import {NavigationProp} from 'lib/routes/types'
 import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
 import {isWeb} from 'platform/detection'
 import {formatCount, formatCountShortOnly} from 'view/com/util/numeric/format'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useSetDrawerOpen} from '#/state/shell'
 import {useModalControls} from '#/state/modals'
 
@@ -50,6 +52,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
   const theme = useTheme()
   const pal = usePalette('default')
   const store = useStores()
+  const {_} = useLingui()
   const setDrawerOpen = useSetDrawerOpen()
   const navigation = useNavigation<NavigationProp>()
   const {track} = useAnalytics()
@@ -158,7 +161,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
           <View style={{}}>
             <TouchableOpacity
               testID="profileCardButton"
-              accessibilityLabel="Profile"
+              accessibilityLabel={_(msg`Profile`)}
               accessibilityHint="Navigates to your profile"
               onPress={onPressProfile}>
               <UserAvatar
@@ -215,7 +218,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               )
             }
             label="Search"
-            accessibilityLabel="Search"
+            accessibilityLabel={_(msg`Search`)}
             accessibilityHint=""
             bold={isAtSearch}
             onPress={onPressSearch}
@@ -237,7 +240,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               )
             }
             label="Home"
-            accessibilityLabel="Home"
+            accessibilityLabel={_(msg`Home`)}
             accessibilityHint=""
             bold={isAtHome}
             onPress={onPressHome}
@@ -259,7 +262,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               )
             }
             label="Notifications"
-            accessibilityLabel="Notifications"
+            accessibilityLabel={_(msg`Notifications`)}
             accessibilityHint={
               notifications.unreadCountLabel === ''
                 ? ''
@@ -286,7 +289,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               )
             }
             label="Feeds"
-            accessibilityLabel="Feeds"
+            accessibilityLabel={_(msg`Feeds`)}
             accessibilityHint=""
             bold={isAtFeeds}
             onPress={onPressMyFeeds}
@@ -294,14 +297,14 @@ export const DrawerContent = observer(function DrawerContentImpl() {
           <MenuItem
             icon={<ListIcon strokeWidth={2} style={pal.text} size={26} />}
             label="Lists"
-            accessibilityLabel="Lists"
+            accessibilityLabel={_(msg`Lists`)}
             accessibilityHint=""
             onPress={onPressLists}
           />
           <MenuItem
             icon={<HandIcon strokeWidth={5} style={pal.text} size={24} />}
             label="Moderation"
-            accessibilityLabel="Moderation"
+            accessibilityLabel={_(msg`Moderation`)}
             accessibilityHint=""
             onPress={onPressModeration}
           />
@@ -322,7 +325,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               )
             }
             label="Profile"
-            accessibilityLabel="Profile"
+            accessibilityLabel={_(msg`Profile`)}
             accessibilityHint=""
             onPress={onPressProfile}
           />
@@ -335,7 +338,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               />
             }
             label="Settings"
-            accessibilityLabel="Settings"
+            accessibilityLabel={_(msg`Settings`)}
             accessibilityHint=""
             onPress={onPressSettings}
           />
@@ -346,7 +349,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
         <View style={styles.footer}>
           <TouchableOpacity
             accessibilityRole="link"
-            accessibilityLabel="Send feedback"
+            accessibilityLabel={_(msg`Send feedback`)}
             accessibilityHint=""
             onPress={onPressFeedback}
             style={[
@@ -362,17 +365,17 @@ export const DrawerContent = observer(function DrawerContentImpl() {
               icon={['far', 'message']}
             />
             <Text type="lg-medium" style={[pal.link, s.pl10]}>
-              Feedback
+              <Trans>Feedback</Trans>
             </Text>
           </TouchableOpacity>
           <TouchableOpacity
             accessibilityRole="link"
-            accessibilityLabel="Send feedback"
+            accessibilityLabel={_(msg`Send feedback`)}
             accessibilityHint=""
             onPress={onPressHelp}
             style={[styles.footerBtn]}>
             <Text type="lg-medium" style={[pal.link, s.pl10]}>
-              Help
+              <Trans>Help</Trans>
             </Text>
           </TouchableOpacity>
         </View>
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx
index db4fa9d71..69a7c4c0e 100644
--- a/src/view/shell/bottom-bar/BottomBar.tsx
+++ b/src/view/shell/bottom-bar/BottomBar.tsx
@@ -24,6 +24,8 @@ import {styles} from './BottomBarStyles'
 import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
 import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
 import {UserAvatar} from 'view/com/util/UserAvatar'
+import {useLingui} from '@lingui/react'
+import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
 
 type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
@@ -34,6 +36,7 @@ export const BottomBar = observer(function BottomBarImpl({
   const {openModal} = useModalControls()
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const safeAreaInsets = useSafeAreaInsets()
   const {track} = useAnalytics()
   const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} =
@@ -105,7 +108,7 @@ export const BottomBar = observer(function BottomBarImpl({
         }
         onPress={onPressHome}
         accessibilityRole="tab"
-        accessibilityLabel="Home"
+        accessibilityLabel={_(msg`Home`)}
         accessibilityHint=""
       />
       <Btn
@@ -127,7 +130,7 @@ export const BottomBar = observer(function BottomBarImpl({
         }
         onPress={onPressSearch}
         accessibilityRole="search"
-        accessibilityLabel="Search"
+        accessibilityLabel={_(msg`Search`)}
         accessibilityHint=""
       />
       <Btn
@@ -149,7 +152,7 @@ export const BottomBar = observer(function BottomBarImpl({
         }
         onPress={onPressFeeds}
         accessibilityRole="tab"
-        accessibilityLabel="Feeds"
+        accessibilityLabel={_(msg`Feeds`)}
         accessibilityHint=""
       />
       <Btn
@@ -173,7 +176,7 @@ export const BottomBar = observer(function BottomBarImpl({
         notificationCount={notifications.unreadCountLabel}
         accessible={true}
         accessibilityRole="tab"
-        accessibilityLabel="Notifications"
+        accessibilityLabel={_(msg`Notifications`)}
         accessibilityHint={
           notifications.unreadCountLabel === ''
             ? ''
@@ -215,7 +218,7 @@ export const BottomBar = observer(function BottomBarImpl({
         onPress={onPressProfile}
         onLongPress={onLongPressProfile}
         accessibilityRole="tab"
-        accessibilityLabel="Profile"
+        accessibilityLabel={_(msg`Profile`)}
         accessibilityHint=""
       />
     </Animated.View>
diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx
index 39271605c..b85823b6f 100644
--- a/src/view/shell/desktop/LeftNav.tsx
+++ b/src/view/shell/desktop/LeftNav.tsx
@@ -39,6 +39,8 @@ import {getCurrentRoute, isTab, isStateAtTabRoot} from 'lib/routes/helpers'
 import {NavigationProp, CommonNavigatorParams} from 'lib/routes/types'
 import {router} from '../../../routes'
 import {makeProfileLink} from 'lib/routes/links'
+import {useLingui} from '@lingui/react'
+import {Trans, msg} from '@lingui/macro'
 
 const ProfileCard = observer(function ProfileCardImpl() {
   const store = useStores()
@@ -67,6 +69,7 @@ function BackBtn() {
   const {isTablet} = useWebMediaQueries()
   const pal = usePalette('default')
   const navigation = useNavigation<NavigationProp>()
+  const {_} = useLingui()
   const shouldShow = useNavigationState(state => !isStateAtTabRoot(state))
 
   const onPressBack = React.useCallback(() => {
@@ -86,7 +89,7 @@ function BackBtn() {
       onPress={onPressBack}
       style={styles.backBtn}
       accessibilityRole="button"
-      accessibilityLabel="Go back"
+      accessibilityLabel={_(msg`Go back`)}
       accessibilityHint="">
       <FontAwesomeIcon
         size={24}
@@ -184,6 +187,7 @@ const NavItem = observer(function NavItemImpl({
 function ComposeBtn() {
   const store = useStores()
   const {getState} = useNavigation()
+  const {_} = useLingui()
   const {isTablet} = useWebMediaQueries()
 
   const getProfileHandle = async () => {
@@ -222,7 +226,7 @@ function ComposeBtn() {
       style={[styles.newPostBtn]}
       onPress={onPressCompose}
       accessibilityRole="button"
-      accessibilityLabel="New post"
+      accessibilityLabel={_(msg`New post`)}
       accessibilityHint="">
       <View style={styles.newPostBtnIconWrapper}>
         <ComposeIcon2
@@ -232,7 +236,7 @@ function ComposeBtn() {
         />
       </View>
       <Text type="button" style={styles.newPostBtnLabel}>
-        New Post
+        <Trans>New Post</Trans>
       </Text>
     </TouchableOpacity>
   )
diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx
index caecea4a8..f54858b8a 100644
--- a/src/view/shell/desktop/Search.tsx
+++ b/src/view/shell/desktop/Search.tsx
@@ -9,10 +9,13 @@ import {MagnifyingGlassIcon2} from 'lib/icons'
 import {NavigationProp} from 'lib/routes/types'
 import {ProfileCard} from 'view/com/profile/ProfileCard'
 import {Text} from 'view/com/util/text/Text'
+import {Trans, msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
 export const DesktopSearch = observer(function DesktopSearch() {
   const store = useStores()
   const pal = usePalette('default')
+  const {_} = useLingui()
   const textInput = React.useRef<TextInput>(null)
   const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
   const [query, setQuery] = React.useState<string>('')
@@ -75,7 +78,7 @@ export const DesktopSearch = observer(function DesktopSearch() {
             onChangeText={onChangeQuery}
             onSubmitEditing={onSubmit}
             accessibilityRole="search"
-            accessibilityLabel="Search"
+            accessibilityLabel={_(msg`Search`)}
             accessibilityHint=""
           />
           {query ? (
@@ -83,11 +86,11 @@ export const DesktopSearch = observer(function DesktopSearch() {
               <TouchableOpacity
                 onPress={onPressCancelSearch}
                 accessibilityRole="button"
-                accessibilityLabel="Cancel search"
+                accessibilityLabel={_(msg`Cancel search`)}
                 accessibilityHint="Exits inputting search query"
                 onAccessibilityEscape={onPressCancelSearch}>
                 <Text type="lg" style={[pal.link]}>
-                  Cancel
+                  <Trans>Cancel</Trans>
                 </Text>
               </TouchableOpacity>
             </View>
@@ -106,7 +109,7 @@ export const DesktopSearch = observer(function DesktopSearch() {
           ) : (
             <View>
               <Text style={[pal.textLight, styles.noResults]}>
-                No results found for {autocompleteView.prefix}
+                <Trans>No results found for {autocompleteView.prefix}</Trans>
               </Text>
             </View>
           )}
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index 10489489e..792499521 100644
--- a/src/view/shell/index.web.tsx
+++ b/src/view/shell/index.web.tsx
@@ -17,6 +17,7 @@ import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
 import {useNavigation} from '@react-navigation/native'
 import {NavigationProp} from 'lib/routes/types'
 import {useAuxClick} from 'lib/hooks/useAuxClick'
+import {t} from '@lingui/macro'
 import {
   useIsDrawerOpen,
   useSetDrawerOpen,
@@ -73,7 +74,7 @@ const ShellInner = observer(function ShellInnerImpl() {
         <TouchableOpacity
           onPress={() => setDrawerOpen(false)}
           style={styles.drawerMask}
-          accessibilityLabel="Close navigation footer"
+          accessibilityLabel={t`Close navigation footer`}
           accessibilityHint="Closes bottom navigation bar">
           <View style={styles.drawerContainer}>
             <DrawerContent />