diff --git a/babel.config.js b/babel.config.js
index 924120495f..825916676a 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -45,6 +45,7 @@ module.exports = function (api) {
},
},
],
+ 'macros',
'react-native-reanimated/plugin', // NOTE: this plugin MUST be last
],
env: {
diff --git a/docs/internationalization.md b/docs/internationalization.md
new file mode 100644
index 0000000000..3c1af7a4dc
--- /dev/null
+++ b/docs/internationalization.md
@@ -0,0 +1,113 @@
+# Internationalization
+
+We want the official Bluesky app to be supported in as many languages as possible. If you want to help us translate the app, please open a PR or issue on the [Bluesky app repo on GitHub](https://github.com/bluesky-social/social-app)
+
+## Tools
+We are using Lingui to manage translations. You can find the documentation [here](https://lingui.dev/).
+
+### Adding new strings
+When adding a new string, do it as follows:
+```jsx
+// Before
+import { Text } from "react-native";
+
+Hello World
+```
+
+```jsx
+// After
+import { Text } from "react-native";
+import { Trans } from "@lingui/macro";
+
+Hello World
+```
+
+The `` macro will extract the string and add it to the catalog. It is not really a component, but a macro. Further reading [here](https://lingui.dev/ref/macro.html)
+
+However sometimes you will run into this case:
+```jsx
+// Before
+import { Text } from "react-native";
+
+const text = "Hello World";
+{text}
+```
+In this case, you cannot use the `useLingui()` hook:
+```jsx
+import { msg } from "@lingui/macro";
+import { useLingui } from "@lingui/react";
+
+const { _ } = useLingui();
+return {text}
+```
+
+If you want to do this outside of a React component, you can use the `t` macro instead (note: this won't react to changes if the locale is switched dynamically within the app):
+```jsx
+import { t } from "@lingui/macro";
+
+const text = t`Hello World`;
+```
+
+We can then run `yarn intl:extract` to update the catalog in `src/locale/locales/{locale}/messages.po`. This will add the new string to the catalog.
+We can then run `yarn intl:compile` to update the translation files in `src/locale/locales/{locale}/messages.js`. This will add the new string to the translation files.
+The configuration for translations is defined in `lingui.config.js`
+
+So the workflow is as follows:
+1. Wrap messages in Trans macro
+2. Run `yarn intl:extract` command to generate message catalogs
+3. Translate message catalogs (send them to translators usually)
+4. Run `yarn intl:compile` to create runtime catalogs
+5. Load runtime catalog
+6. Enjoy translated app!
+
+### Common pitfalls
+These pitfalls are memoization pitfalls that will cause the components to not re-render when the locale is changed -- causing stale translations to be shown.
+
+```jsx
+import { msg } from "@lingui/macro";
+import { i18n } from "@lingui/core";
+
+const welcomeMessage = msg`Welcome!`;
+
+// ❌ Bad! This code won't work
+export function Welcome() {
+ const buggyWelcome = useMemo(() => {
+ return i18n._(welcomeMessage);
+ }, []);
+
+ return
{buggyWelcome}
;
+}
+
+// ❌ Bad! This code won't work either because the reference to i18n does not change
+export function Welcome() {
+ const { i18n } = useLingui();
+
+ const buggyWelcome = useMemo(() => {
+ return i18n._(welcomeMessage);
+ }, [i18n]);
+
+ return
{buggyWelcome}
;
+}
+
+// ✅ Good! `useMemo` has i18n context in the dependency
+export function Welcome() {
+ const linguiCtx = useLingui();
+
+ const welcome = useMemo(() => {
+ return linguiCtx.i18n._(welcomeMessage);
+ }, [linguiCtx]);
+
+ return
{welcome}
;
+}
+
+// 🤩 Better! `useMemo` consumes the `_` function from the Lingui context
+export function Welcome() {
+ const { _ } = useLingui();
+
+ const welcome = useMemo(() => {
+ return _(welcomeMessage);
+ }, [_]);
+
+ return
{welcome}
;
+}
+```
\ No newline at end of file
diff --git a/lingui.config.js b/lingui.config.js
new file mode 100644
index 0000000000..a4219a1bd4
--- /dev/null
+++ b/lingui.config.js
@@ -0,0 +1,11 @@
+/** @type {import('@lingui/conf').LinguiConfig} */
+module.exports = {
+ locales: ['en', 'cs', 'fr', 'hi', 'es'],
+ catalogs: [
+ {
+ path: '/src/locale/locales/{locale}/messages',
+ include: ['src'],
+ },
+ ],
+ format: 'po',
+}
diff --git a/package.json b/package.json
index efb0942df4..585e1e23e0 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,9 @@
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
"perf:test:results": "NODE_ENV=test flashlight report .perf/results.json",
"perf:measure": "NODE_ENV=test flashlight measure",
- "build:apk": "eas build -p android --profile dev-android-apk"
+ "build:apk": "eas build -p android --profile dev-android-apk",
+ "intl:extract": "lingui extract",
+ "intl:compile": "lingui compile"
},
"dependencies": {
"@atproto/api": "^0.6.23",
@@ -42,6 +44,7 @@
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/react-native-fontawesome": "^0.3.0",
"@gorhom/bottom-sheet": "^4.5.1",
+ "@lingui/react": "^4.5.0",
"@mattermost/react-native-paste-input": "^0.6.4",
"@miblanchard/react-native-slider": "^2.3.1",
"@react-native-async-storage/async-storage": "1.18.2",
@@ -164,10 +167,12 @@
},
"devDependencies": {
"@atproto/dev-env": "^0.2.5",
- "@babel/core": "^7.20.0",
+ "@babel/core": "^7.23.2",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@did-plc/server": "^0.0.1",
+ "@lingui/cli": "^4.5.0",
+ "@lingui/macro": "^4.5.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
"@react-native-community/eslint-config": "^3.0.0",
"@testing-library/jest-native": "^5.4.1",
@@ -192,6 +197,7 @@
"@typescript-eslint/parser": "^5.48.2",
"babel-jest": "^29.4.2",
"babel-loader": "^9.1.2",
+ "babel-plugin-macros": "^3.1.0",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-react-native-web": "^0.18.12",
"detox": "^20.13.0",
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 9e5b99a9f1..ef275b3926 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() {
-
-
-
+
+
+
+
+
diff --git a/src/locale/i18n.ts b/src/locale/i18n.ts
new file mode 100644
index 0000000000..9c6a017ffb
--- /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 0000000000..8d85ab77c3
--- /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 0000000000..28ad5ba4c0
--- /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 0000000000..8d85ab77c3
--- /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 0000000000..5863035868
--- /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 0000000000..8d85ab77c3
--- /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 0000000000..daeb149122
--- /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 0000000000..8d85ab77c3
--- /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 0000000000..c7c8b38667
--- /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 0000000000..8d85ab77c3
--- /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 0000000000..f3241668eb
--- /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 67453f111a..05e72a2e68 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 (
- Bluesky
+
+ Bluesky
+
- See what's next
+ See what's next
@@ -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">
- Create a new account
+ Create a new account
- Sign In
+
+ Sign In
+
diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx
index cef9618efa..f10dc4f98b 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">
- Sign In
+
+ Sign In
+
diff --git a/src/view/com/auth/create/CreateAccount.tsx b/src/view/com/auth/create/CreateAccount.tsx
index c3cfb3ad39..8e2bbed856 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 (
+ title={_(msg`Create Account`)}
+ description={_(msg`We're so excited to have you join us!`)}>
@@ -88,7 +91,7 @@ export const CreateAccount = observer(function CreateAccountImpl({
testID="backBtn"
accessibilityRole="button">
- Back
+ Back
@@ -101,7 +104,7 @@ export const CreateAccount = observer(function CreateAccountImpl({
) : (
- Next
+ Next
)}
@@ -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">
- Retry
+ Retry
) : model.isFetchingServiceDescription ? (
<>
- Connecting...
+ Connecting...
>
) : undefined}
diff --git a/src/view/com/auth/create/Step1.tsx b/src/view/com/auth/create/Step1.tsx
index cdd5cb21d8..7e3ea062dc 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 (
-
+
- This is the service that keeps you online.
+ This is the service that keeps you online.
)
diff --git a/src/view/com/auth/create/Step2.tsx b/src/view/com/auth/create/Step2.tsx
index b2054150b3..3cc8ae9345 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 (
-
+
{model.isInviteCodeRequired && (
@@ -46,11 +49,11 @@ export const Step2 = observer(function Step2Impl({
@@ -61,10 +64,12 @@ export const Step2 = observer(function Step2Impl({
Don't have an invite code?{' '}
- Join the waitlist.
+
+ Join the waitlist.
+
@@ -72,16 +77,16 @@ export const Step2 = observer(function Step2Impl({
<>
- Email address
+ Email address
@@ -92,17 +97,17 @@ export const Step2 = observer(function Step2Impl({
type="md-medium"
style={[pal.text, s.mb2]}
nativeID="password">
- Password
+ Password
@@ -113,7 +118,7 @@ export const Step2 = observer(function Step2Impl({
type="md-medium"
style={[pal.text, s.mb2]}
nativeID="birthDate">
- Your birth date
+ Your birth date
diff --git a/src/view/com/auth/create/Step3.tsx b/src/view/com/auth/create/Step3.tsx
index beb756ac1d..09fba07141 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 (
-
+
- Your full handle will be{' '}
-
+ Your full handle will be
+
@{createFullHandle(model.handle, model.userDomain)}
diff --git a/src/view/com/auth/login/ChooseAccountForm.tsx b/src/view/com/auth/login/ChooseAccountForm.tsx
new file mode 100644
index 0000000000..596a8e4112
--- /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 (
+
+
+ Sign in as...
+
+ {store.session.accounts.map(account => (
+ onTryAccount(account)}
+ accessibilityRole="button"
+ accessibilityLabel={_(msg`Sign in as ${account.handle}`)}
+ accessibilityHint="Double tap to sign in">
+
+
+
+
+
+
+ {account.displayName || account.handle}{' '}
+
+
+ {account.handle}
+
+
+
+
+
+ ))}
+ onSelectAccount(undefined)}
+ accessibilityRole="button"
+ accessibilityLabel={_(msg`Login to account that is not listed`)}
+ accessibilityHint="">
+
+
+
+ Other account
+
+
+
+
+
+
+
+
+ Back
+
+
+
+ {isProcessing && }
+
+
+ )
+}
diff --git a/src/view/com/auth/login/ForgotPasswordForm.tsx b/src/view/com/auth/login/ForgotPasswordForm.tsx
new file mode 100644
index 0000000000..9bfab18b55
--- /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(false)
+ const [email, setEmail] = useState('')
+ 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 (
+ <>
+
+
+ Reset password
+
+
+
+ Enter the email you used to create your account. We'll send you a
+ "reset code" so you can set a new password.
+
+
+
+
+
+
+ {toNiceDomain(serviceUrl)}
+
+
+
+
+
+
+
+
+
+
+ {error ? (
+
+
+
+
+
+ {error}
+
+
+ ) : undefined}
+
+
+
+ Back
+
+
+
+ {!serviceDescription || isProcessing ? (
+
+ ) : !email ? (
+
+ Next
+
+ ) : (
+
+
+ Next
+
+
+ )}
+ {!serviceDescription || isProcessing ? (
+
+ Processing...
+
+ ) : undefined}
+
+
+ >
+ )
+}
diff --git a/src/view/com/auth/login/Login.tsx b/src/view/com/auth/login/Login.tsx
index 24a657c66c..401b7d980b 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('')
const [retryDescribeTrigger, setRetryDescribeTrigger] = useState({})
const [serviceUrl, setServiceUrl] = useState(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 ? (
+ title={_(msg`Sign in`)}
+ description={_(msg`Enter your username and password`)}>
void}) => {
{currentForm === Forms.ChooseAccount ? (
+ title={_(msg`Sign in as...`)}
+ description={_(msg`Select from an existing account`)}>
void}) => {
{currentForm === Forms.ForgotPassword ? (
+ title={_(msg`Forgot Password`)}
+ description={_(msg`Let's get your password reset!`)}>
void}) => {
{currentForm === Forms.SetNewPassword ? (
+ title={_(msg`Forgot Password`)}
+ description={_(msg`Let's get your password reset!`)}>
void}) => {
)
}
-
-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 (
-
-
- Sign in as...
-
- {store.session.accounts.map(account => (
- onTryAccount(account)}
- accessibilityRole="button"
- accessibilityLabel={`Sign in as ${account.handle}`}
- accessibilityHint="Double tap to sign in">
-
-
-
-
-
-
- {account.displayName || account.handle}{' '}
-
-
- {account.handle}
-
-
-
-
-
- ))}
- onSelectAccount(undefined)}
- accessibilityRole="button"
- accessibilityLabel="Login to account that is not listed"
- accessibilityHint="">
-
-
-
- Other account
-
-
-
-
-
-
-
-
- Back
-
-
-
- {isProcessing && }
-
-
- )
-}
-
-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(false)
- const [identifier, setIdentifier] = useState(initialHandle)
- const [password, setPassword] = useState('')
- const passwordInputRef = useRef(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 (
-
-
- Sign into
-
-
-
-
-
-
- {toNiceDomain(serviceUrl)}
-
-
-
-
-
-
-
-
- Account
-
-
-
-
- {
- 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"
- />
-
-
-
-
-
- Forgot
-
-
-
- {error ? (
-
-
-
-
-
- {error}
-
-
- ) : undefined}
-
-
-
- Back
-
-
-
- {!serviceDescription && error ? (
-
-
- Retry
-
-
- ) : !serviceDescription ? (
- <>
-
-
- Connecting...
-
- >
- ) : isProcessing ? (
-
- ) : isReady ? (
-
-
- Next
-
-
- ) : undefined}
-
-
- )
-}
-
-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(false)
- const [email, setEmail] = useState('')
- 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 (
- <>
-
-
- Reset password
-
-
- Enter the email you used to create your account. We'll send you a
- "reset code" so you can set a new password.
-
-
-
-
-
- {toNiceDomain(serviceUrl)}
-
-
-
-
-
-
-
-
-
-
- {error ? (
-
-
-
-
-
- {error}
-
-
- ) : undefined}
-
-
-
- Back
-
-
-
- {!serviceDescription || isProcessing ? (
-
- ) : !email ? (
-
- Next
-
- ) : (
-
-
- Next
-
-
- )}
- {!serviceDescription || isProcessing ? (
-
- Processing...
-
- ) : undefined}
-
-
- >
- )
-}
-
-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(false)
- const [resetCode, setResetCode] = useState('')
- const [password, setPassword] = useState('')
-
- 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 (
- <>
-
-
- Set new password
-
-
- You will receive an email with a "reset code." Enter that code here,
- then enter your new password.
-
-
-
-
-
-
-
-
-
-
-
- {error ? (
-
-
-
-
-
- {error}
-
-
- ) : undefined}
-
-
-
- Back
-
-
-
- {isProcessing ? (
-
- ) : !resetCode || !password ? (
-
- Next
-
- ) : (
-
-
- Next
-
-
- )}
- {isProcessing ? (
-
- Updating...
-
- ) : undefined}
-
-
- >
- )
-}
-
-const PasswordUpdatedForm = ({onPressNext}: {onPressNext: () => void}) => {
- const {screen} = useAnalytics()
-
- useEffect(() => {
- screen('Signin:PasswordUpdatedForm')
- }, [screen])
-
- const pal = usePalette('default')
- return (
- <>
-
-
- Password updated!
-
-
- You can now sign in with your new password.
-
-
-
-
-
- Okay
-
-
-
-
- >
- )
-}
-
-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 0000000000..9779b939ab
--- /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(false)
+ const [identifier, setIdentifier] = useState(initialHandle)
+ const [password, setPassword] = useState('')
+ const passwordInputRef = useRef(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 (
+
+
+ Sign into
+
+
+
+
+
+
+ {toNiceDomain(serviceUrl)}
+
+
+
+
+
+
+
+
+ Account
+
+
+
+
+ {
+ 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"
+ />
+
+
+
+
+
+
+ Forgot
+
+
+
+
+ {error ? (
+
+
+
+
+
+ {error}
+
+
+ ) : undefined}
+
+
+
+ Back
+
+
+
+ {!serviceDescription && error ? (
+
+
+ Retry
+
+
+ ) : !serviceDescription ? (
+ <>
+
+
+ Connecting...
+
+ >
+ ) : isProcessing ? (
+
+ ) : isReady ? (
+
+
+ Next
+
+
+ ) : undefined}
+
+
+ )
+}
diff --git a/src/view/com/auth/login/PasswordUpdatedForm.tsx b/src/view/com/auth/login/PasswordUpdatedForm.tsx
new file mode 100644
index 0000000000..1e07588a91
--- /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 (
+ <>
+
+
+ Password updated!
+
+
+ You can now sign in with your new password.
+
+
+
+
+
+ Okay
+
+
+
+
+ >
+ )
+}
diff --git a/src/view/com/auth/login/SetNewPasswordForm.tsx b/src/view/com/auth/login/SetNewPasswordForm.tsx
new file mode 100644
index 0000000000..04eaa28427
--- /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(false)
+ const [resetCode, setResetCode] = useState('')
+ const [password, setPassword] = useState('')
+
+ 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 (
+ <>
+
+
+ Set new password
+
+
+
+ You will receive an email with a "reset code." Enter that code here,
+ then enter your new password.
+
+
+
+
+
+
+
+
+
+
+
+
+ {error ? (
+
+
+
+
+
+ {error}
+
+
+ ) : undefined}
+
+
+
+ Back
+
+
+
+ {isProcessing ? (
+
+ ) : !resetCode || !password ? (
+
+ Next
+
+ ) : (
+
+
+ Next
+
+
+ )}
+ {isProcessing ? (
+
+ Updating...
+
+ ) : undefined}
+
+
+ >
+ )
+}
diff --git a/src/view/com/auth/login/styles.ts b/src/view/com/auth/login/styles.ts
new file mode 100644
index 0000000000..9dccc2803b
--- /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 f672372b8e..7ec78bd7fe 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 ? (
- Finding similar accounts...
+
+ Finding similar accounts...
+
) : null}
diff --git a/src/view/com/auth/onboarding/WelcomeMobile.tsx b/src/view/com/auth/onboarding/WelcomeMobile.tsx
index 1f0a64370a..ef70a1fe32 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}>
- Skip
+
+ Skip
+
Welcome to{' '}
- Bluesky
+
+ Bluesky
+
- Bluesky is public.
+ Bluesky is public.
- Your posts, likes, and blocks are public. Mutes are private.
+
+ Your posts, likes, and blocks are public. Mutes are private.
+
@@ -63,10 +70,10 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
- Bluesky is open.
+ Bluesky is open.
- Never lose access to your followers and data.
+ Never lose access to your followers and data.
@@ -74,11 +81,13 @@ export const WelcomeMobile = observer(function WelcomeMobileImpl({
- Bluesky is flexible.
+ Bluesky is flexible.
- Choose the algorithms that power your experience with custom
- feeds.
+
+ Choose the algorithms that power your experience with custom
+ feeds.
+
diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index cdc9768f76..8f8c2eea36 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">
- Cancel
+
+ Cancel
+
{isProcessing ? (
@@ -316,7 +321,9 @@ export const ComposePost = observer(function ComposePost({
) : (
- Post
+
+ Post
+
)}
>
@@ -332,7 +339,7 @@ export const ComposePost = observer(function ComposePost({
/>
- One or more images is missing alt text.
+ One or more images is missing alt text.
)}
@@ -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`}
/>
@@ -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}`}>
- Add link card:{' '}
- {toShortUrl(url)}
+ Add link card:
+ {toShortUrl(url)}
))}
diff --git a/src/view/com/composer/ExternalEmbed.tsx b/src/view/com/composer/ExternalEmbed.tsx
index c9200ec63d..502e4b4d2d 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
}
@@ -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}>
diff --git a/src/view/com/composer/Prompt.tsx b/src/view/com/composer/Prompt.tsx
index e54404f52c..5e8a01d96d 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 (
void}) {
style={[pal.view, pal.border, styles.prompt]}
onPress={() => onPressCompose()}
accessibilityRole="button"
- accessibilityLabel="Compose reply"
+ accessibilityLabel={_(msg`Compose reply`)}
accessibilityHint="Opens composer">
void}) {
pal.text,
isDesktop ? styles.labelDesktopWeb : styles.labelMobile,
]}>
- Write your reply
+ Write your reply
)
diff --git a/src/view/com/composer/labels/LabelsBtn.tsx b/src/view/com/composer/labels/LabelsBtn.tsx
index 4b6ad81c72..7d90774f24 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 069a054754..69c8debb02 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({
{
Keyboard.dismiss()
@@ -124,7 +127,7 @@ const GalleryInner = observer(function GalleryImpl({
}}
style={[styles.altTextControl, altTextControlStyle]}>
- ALT
+ ALT
{image.altText.length > 0 ? (
{
if (isNative) {
@@ -161,7 +164,7 @@ const GalleryInner = observer(function GalleryImpl({
gallery.remove(image)}
style={styles.imageControl}>
@@ -174,7 +177,7 @@ const GalleryInner = observer(function GalleryImpl({
{
Keyboard.dismiss()
@@ -203,8 +206,10 @@ const GalleryInner = observer(function GalleryImpl({
- Alt text describes images for blind and low-vision users, and helps
- give context to everyone.
+
+ Alt text describes images for blind and low-vision users, and helps
+ give context to everyone.
+
>
diff --git a/src/view/com/composer/photos/OpenCameraBtn.tsx b/src/view/com/composer/photos/OpenCameraBtn.tsx
index 99e820d51b..4eac7179e1 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">
{
@@ -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">
{postLanguagesPref.length > 0 ? (
diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx
index 1037007b77..044f69efe8 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={
>
- }, [isDesktop, pal, store, hasNew])
+ }, [isDesktop, pal.view, pal.text, pal.textLight, store, hasNew, _])
return (
@@ -188,7 +191,7 @@ export const FeedPage = observer(function FeedPageImpl({
{(isScrolledDown || hasNew) && (
)}
@@ -197,7 +200,7 @@ export const FeedPage = observer(function FeedPageImpl({
onPress={onPressCompose}
icon={}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
diff --git a/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx b/src/view/com/lightbox/ImageViewing/components/ImageDefaultHeader.tsx
index bb006d506c..c806bc6a6c 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}>
✕
diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx
index ddf965f424..331a2b8238 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(initialIndex)
const [isAltExpanded, setAltExpanded] = useState(false)
@@ -101,7 +104,7 @@ function LightboxInner({
@@ -117,7 +120,7 @@ function LightboxInner({
onPress={onPressLeft}
style={[styles.btn, styles.leftBtn]}
accessibilityRole="button"
- accessibilityLabel="Previous image"
+ accessibilityLabel={_(msg`Previous image`)}
accessibilityHint="">
{
setAltExpanded(!isAltExpanded)
diff --git a/src/view/com/lists/ListsList.tsx b/src/view/com/lists/ListsList.tsx
index 8c65108869..2883a31d52 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({
- You have no lists.
+
+ You have no lists.
+
)
} else if (item === ERROR_ITEM) {
diff --git a/src/view/com/modals/AddAppPasswords.tsx b/src/view/com/modals/AddAppPasswords.tsx
index 621c61b90e..095ad48bd2 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({}: {}) {
{!appPassword ? (
- Please enter a unique name for this App Password or use our randomly
- generated one.
+
+ Please enter a unique name for this App Password or use our
+ randomly generated one.
+
) : (
-
- Here is your app password.
- {' '}
- Use this to sign into the other app along with your handle.
+
+ Here is your app password.
+
+
+ Use this to sign into the other app along with your handle.
+
)}
{!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"
/>
@@ -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">
{appPassword}
{wasCopied ? (
- Copied
+
+ Copied
+
) : (
{appPassword ? (
- 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.
+
+ 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.
+
) : (
- Can only contain letters, numbers, spaces, dashes, and underscores.
- Must be at least 4 characters long, but no more than 32 characters
- long.
+
+ Can only contain letters, numbers, spaces, dashes, and underscores.
+ Must be at least 4 characters long, but no more than 32 characters
+ long.
+
)}
diff --git a/src/view/com/modals/AltImage.tsx b/src/view/com/modals/AltImage.tsx
index 9c377a1210..80130f43ad 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) {
- Save
+ Save
@@ -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}>
- Cancel
+ Cancel
diff --git a/src/view/com/modals/BirthDateSettings.tsx b/src/view/com/modals/BirthDateSettings.tsx
index 7b0778f83d..6655b7a6b1 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(
store.preferences.birthDate || new Date(),
@@ -49,12 +52,12 @@ export const Component = observer(function Component({}: {}) {
style={[pal.view, styles.container, isMobile && {paddingHorizontal: 18}]}>
- My Birthday
+ My Birthday
- This information is not shared with other users.
+ This information is not shared with other users.
@@ -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="">
- Save
+
+ Save
+
)}
diff --git a/src/view/com/modals/ChangeEmail.tsx b/src/view/com/modals/ChangeEmail.tsx
index ec37aeede1..710c0588ed 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.InputEmail)
const [email, setEmail] = useState(
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}]}>
- {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`) : ''}
{stage === Stages.InputEmail ? (
- <>Enter your new email address below.>
+ Enter your new email address below.
) : stage === Stages.ConfirmCode ? (
- <>
+
An email has been sent to your previous address,{' '}
{store.session.currentSession?.email || ''}. It includes a
confirmation code which you can enter below.
- >
+
) : (
- <>
+
Your email has been updated but not verified. As a next step,
please verify your new email.
- >
+
)}
@@ -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 6184cb3b76..c03ebafda2 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('')
const pal = usePalette('default')
const {track} = useAnalytics()
+ const {_} = useLingui()
const {closeModal} = useModalControls()
const [isProcessing, setProcessing] = useState(false)
@@ -141,7 +144,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
@@ -153,7 +156,7 @@ export function Component({onChanged}: {onChanged: () => void}) {
type="2xl-bold"
style={[styles.titleMiddle, pal.text]}
numberOfLines={1}>
- Change Handle
+ Change Handle
{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}`}>
Retry
@@ -173,10 +176,10 @@ export function Component({onChanged}: {onChanged: () => void}) {
- Save
+ Save
) : 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"
/>
- Your full handle will be{' '}
+ Your full handle will be
@{createFullHandle(handle, userDomain)}
@@ -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`)}>
- I have my own domain
+ I have my own domain
>
@@ -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('')
const [isDNSForm, setDNSForm] = React.useState(true)
@@ -367,7 +372,7 @@ function CustomHandleForm({
return (
<>
- Enter the domain you want to use
+ Enter the domain you want to use
@@ -413,7 +418,7 @@ function CustomHandleForm({
{isDNSForm ? (
<>
- Add the following DNS record to your domain:
+ Add the following DNS record to your domain:
@@ -451,7 +456,7 @@ function CustomHandleForm({
) : (
<>
- Upload a text file to:
+ Upload a text file to:
@@ -483,7 +488,7 @@ function CustomHandleForm({
{canSave === true && (
- Domain verified!
+ Domain verified!
)}
@@ -511,7 +516,7 @@ function CustomHandleForm({
Nevermind, create a handle for me
diff --git a/src/view/com/modals/Confirm.tsx b/src/view/com/modals/Confirm.tsx
index 6b942057ba..5e869f396c 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(false)
const [error, setError] = useState('')
@@ -69,7 +72,7 @@ export function Component({
onPress={onPress}
style={[styles.btn, confirmBtnStyle]}
accessibilityRole="button"
- accessibilityLabel="Confirm"
+ accessibilityLabel={_(msg`Confirm`)}
accessibilityHint="">
{confirmBtnText ?? 'Confirm'}
@@ -82,7 +85,7 @@ export function Component({
onPress={onPressCancel}
style={[styles.btnCancel, s.mt10]}
accessibilityRole="button"
- accessibilityLabel="Cancel"
+ accessibilityLabel={_(msg`Cancel`)}
accessibilityHint="">
{cancelBtnText ?? 'Cancel'}
diff --git a/src/view/com/modals/ContentFilteringSettings.tsx b/src/view/com/modals/ContentFilteringSettings.tsx
index 0891a64734..ad4a0fa521 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 (
- Content Filtering
+
+ Content Filtering
+
- Done
+
+ Done
+
diff --git a/src/view/com/modals/CreateOrEditList.tsx b/src/view/com/modals/CreateOrEditList.tsx
index cdad377707..cfd0f75697 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">
- {list ? 'Edit' : 'New'} {purposeLabel} List
+
+ {list ? 'Edit' : 'New'} {purposeLabel} List
+
{error !== '' && (
)}
- List Avatar
+
+ List Avatar
+
- List Name
+ List Name setName(enforceLen(v, MAX_NAME))}
accessible={true}
- accessibilityLabel="Name"
+ accessibilityLabel={_(msg`Name`)}
accessibilityHint=""
accessibilityLabelledBy="list-name"
/>
- Description
+ Description 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="">
- Save
+
+ Save
+
)}
@@ -249,11 +258,13 @@ export function Component({
style={s.mt5}
onPress={onPressCancel}
accessibilityRole="button"
- accessibilityLabel="Cancel"
+ accessibilityLabel={_(msg`Cancel`)}
accessibilityHint=""
onAccessibilityEscape={onPressCancel}>
- Cancel
+
+ Cancel
+
diff --git a/src/view/com/modals/DeleteAccount.tsx b/src/view/com/modals/DeleteAccount.tsx
index 9a8a8b4b05..624dbda2d8 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(false)
@@ -71,7 +74,7 @@ export function Component({}: {}) {
- Delete Account
+ Delete Account
@@ -95,8 +98,10 @@ export function Component({}: {}) {
{!isEmailSent ? (
<>
- For security reasons, we'll need to send a confirmation code to
- your email address.
+
+ For security reasons, we'll need to send a confirmation code to
+ your email address.
+
{error ? (
@@ -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">
- Send Email
+ Send Email
@@ -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}>
- Cancel
+ Cancel
>
@@ -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:
+
+ Check your inbox for an email with the confirmation code to
+ enter below:
+
- Please enter your password as well:
+ Please enter your password as well:
{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="">
- Delete my account
+ Delete my account
- Cancel
+ Cancel
>
diff --git a/src/view/com/modals/EditImage.tsx b/src/view/com/modals/EditImage.tsx
index a2a458f4c6..753907472d 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,
},
]}>
- Edit image
+
+ Edit image
+
{!isMobile ? (
- Ratios
+ Ratios
) : null}
@@ -263,7 +268,7 @@ export const Component = observer(function EditImageImpl({
{!isMobile ? (
- Transformations
+ Transformations
) : null}
@@ -291,7 +296,7 @@ export const Component = observer(function EditImageImpl({
- Accessibility
+ Accessibility 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({
- Cancel
+ Cancel
@@ -325,7 +330,7 @@ export const Component = observer(function EditImageImpl({
end={{x: 1, y: 1}}
style={[styles.btn]}>
- Done
+ Done
diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx
index f08bb2326b..eef408e982 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(false)
@@ -151,7 +154,9 @@ export function Component({
return (
- Edit my profile
+
+ Edit my profile
+
- Display Name
+
+ Display Name
+
- Description
+
+ Description
+ setDescription(enforceLen(v, MAX_DESCRIPTION))}
accessible={true}
- accessibilityLabel="Description"
+ accessibilityLabel={_(msg`Description`)}
accessibilityHint="Edit your profile description"
/>
@@ -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">
- Save Changes
+
+ Save Changes
+
)}
@@ -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}>
- Cancel
+
+ Cancel
+
)}
diff --git a/src/view/com/modals/InviteCodes.tsx b/src/view/com/modals/InviteCodes.tsx
index 227b252759..a90a9eab69 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({}: {}) {
- You don't have any invite codes yet! We'll send you some when you've
- been on Bluesky for a little longer.
+
+ You don't have any invite codes yet! We'll send you some when
+ you've been on Bluesky for a little longer.
+
@@ -63,10 +66,12 @@ export function Component({}: {}) {
return (
- Invite a Friend
+ Invite a Friend
- Each code works once. You'll receive more invite codes periodically.
+
+ Each code works once. You'll receive more invite codes periodically.
+
{store.me.invites.map((invite, i) => (
@@ -138,7 +143,9 @@ const InviteCode = observer(function InviteCodeImpl({
{!used && invitesState.copiedInvites.includes(invite.code) && (
- Copied
+
+ Copied
+
)}
{!used && (
- Used by:
+
+ Used by:
+
{invite.uses.map(use => (
{
@@ -45,26 +48,26 @@ export const Component = observer(function Component({
size={18}
/>
- Potentially Misleading Link
+ Potentially Misleading Link
>
) : (
- Leaving Bluesky
+ Leaving Bluesky
)}
- This link is taking you to the following website:
+ This link is taking you to the following website:
{potentiallyMisleading && (
- Make sure this is where you intend to go!
+ Make sure this is where you intend to go!
)}
@@ -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 8864ebc780..e59ab90dff 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({
@@ -136,7 +139,7 @@ export const Component = observer(function Component({
pal.textLight,
{paddingHorizontal: 12, paddingVertical: 16},
]}>
- No results found for {autocompleteView.prefix}
+ No results found for {autocompleteView.prefix}
)}
@@ -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 13728b62b2..a72da29b4a 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 '}>
- {!isReposted ? 'Repost' : 'Undo repost'}
+ {!isReposted ? 'Repost' : 'Undo repost'}
- Quote Post
+ Quote Post
@@ -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}>
- Cancel
+
+ Cancel
+
diff --git a/src/view/com/modals/SelfLabel.tsx b/src/view/com/modals/SelfLabel.tsx
index 242b6a38a4..f8b64085d2 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({
- Add a content warning
+ Add a content warning
@@ -70,7 +73,7 @@ export const Component = observer(function Component({
paddingBottom: 8,
}}>
- Adult Content
+ Adult Content
{hasAdultSelection ? (
) : null}
@@ -116,23 +119,25 @@ export const Component = observer(function Component({
{selected.includes('sexual') ? (
- <>Pictures meant for adults.>
+ Pictures meant for adults.
) : selected.includes('nudity') ? (
- <>Artistic or non-erotic nudity.>
+ Artistic or non-erotic nudity.
) : selected.includes('porn') ? (
- <>Sexual activity or erotic nudity.>
+ Sexual activity or erotic nudity.
) : (
- <>If none are selected, suitable for all ages.>
+ If none are selected, suitable for all ages.
)}
>
) : (
-
- Not Applicable
+
+ Not Applicable.
- . This warning is only available for posts with media attached.
+
+ This warning is only available for posts with media attached.
+
)}
@@ -147,9 +152,11 @@ export const Component = observer(function Component({
}}
style={styles.btn}
accessibilityRole="button"
- accessibilityLabel="Confirm"
+ accessibilityLabel={_(msg`Confirm`)}
accessibilityHint="">
- Done
+
+ Done
+
diff --git a/src/view/com/modals/ServerInput.tsx b/src/view/com/modals/ServerInput.tsx
index 0f8db30b63..09a460315e 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('')
+ const {_} = useLingui()
const {closeModal} = useModalControls()
const doSelect = (url: string) => {
@@ -32,7 +35,7 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
return (
- Choose Service
+ Choose Service
@@ -43,7 +46,9 @@ export function Component({onSelect}: {onSelect: (url: string) => void}) {
style={styles.btn}
onPress={() => doSelect(LOCAL_DEV_SERVICE)}
accessibilityRole="button">
- Local dev server
+
+ Local dev server
+ void}) {
style={styles.btn}
onPress={() => doSelect(STAGING_SERVICE)}
accessibilityRole="button">
- Staging
+
+ Staging
+ 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">
- Bluesky.Social
+
+ Bluesky.Social
+ void}) {
- Other service
+
+ Other service
+ 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 d5fa32692b..1d9457995c 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]}>
- Switch Account
+ Switch Account
{isSwitching ? (
@@ -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`}>
- Sign out
+ Sign out
diff --git a/src/view/com/modals/UserAddRemoveLists.tsx b/src/view/com/modals/UserAddRemoveLists.tsx
index f86e884391..efcfc43be5 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(
@@ -181,7 +184,7 @@ export const Component = observer(function UserAddRemoveListsImpl({
return (
- Update {displayName} in Lists
+ Update {displayName} in Lists(
showReminder ? Stages.Reminder : Stages.Email,
)
@@ -98,21 +101,21 @@ export const Component = observer(function Component({
{stage === Stages.Reminder ? (
- <>
+
Your email has not yet been verified. This is an important
security step which we recommend.
- >
+
) : stage === Stages.Email ? (
- <>
+
This is important in case you ever need to change your email or
reset your password.
- >
+
) : stage === Stages.ConfirmCode ? (
- <>
+
An email has been sent to{' '}
{store.session.currentSession?.email || ''}. It includes a
confirmation code which you can enter below.
- >
+
) : (
''
)}
@@ -132,7 +135,7 @@ export const Component = observer(function Component({
@@ -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({
diff --git a/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx b/src/view/com/modals/lang-settings/ContentLanguagesSettings.tsx
index 0b19abc686..b8c125b65c 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',
},
]}>
- Content Languages
+
+ Content Languages
+
- Which languages would you like to see in your algorithmic feeds?
+
+ Which languages would you like to see in your algorithmic feeds?
+
- Leave them all unchecked to see any language.
+ Leave them all unchecked to see any language.
{languages.map(lang => (
diff --git a/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx b/src/view/com/modals/lang-settings/PostLanguagesSettings.tsx
index 7ec26ca52a..7fcb24d584 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',
},
]}>
- Post Languages
+
+ Post Languages
+
- Which languages are used in this post?
+ Which languages are used in this post?
{languages.map(lang => {
diff --git a/src/view/com/modals/report/InputIssueDetails.tsx b/src/view/com/modals/report/InputIssueDetails.tsx
index 70a8f7b243..2f701b7995 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">
- Back
+
+ Back
+ {
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 (
<>
- Report {collectionName}
+
+ Report {collectionName}
+
- What is the issue with this {collectionName}?
+ What is the issue with this {collectionName}?
- Add details to report
+
+ Add details to report
+
>
) : undefined}
diff --git a/src/view/com/modals/report/SendReportButton.tsx b/src/view/com/modals/report/SendReportButton.tsx
index 82fb65f20c..40c239bffe 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`}>
- Send Report
+
+ Send Report
+
)
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx
index c38ab3fd50..0387ed38dd 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 ? (
<>
- and
+
+ and
+
{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 (
@@ -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">
- Hide
+ Hide
@@ -328,7 +334,7 @@ function CondensedAuthorsList({
}
return (
diff --git a/src/view/com/pager/FeedsTabBarMobile.tsx b/src/view/com/pager/FeedsTabBarMobile.tsx
index b33829ee59..791fe71be4 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}>
(null)
const hasScrolledIntoView = useRef(false)
@@ -197,7 +200,7 @@ export const PostThread = observer(function PostThread({
return (
- Deleted post.
+ Deleted post.
)
@@ -205,7 +208,7 @@ export const PostThread = observer(function PostThread({
return (
- Blocked post.
+ Blocked post.
)
@@ -214,7 +217,7 @@ export const PostThread = observer(function PostThread({
setMaxVisible(n => n + 50)}
style={[pal.border, pal.view, styles.itemContainer]}
- accessibilityLabel="Load more posts"
+ accessibilityLabel={_(msg`Load more posts`)}
accessibilityHint="">
- Load more posts
+ Load more posts
@@ -275,6 +278,7 @@ export const PostThread = observer(function PostThread({
posts,
onRefresh,
treeView,
+ _,
],
)
@@ -302,15 +306,15 @@ export const PostThread = observer(function PostThread({
- Post not found
+ Post not found
- The post may have been deleted.
+ The post may have been deleted.
- Back
+ Back
@@ -336,15 +340,18 @@ export const PostThread = observer(function PostThread({
- Post hidden
+ Post hidden
- You have blocked the author or you have been blocked by the author.
+
+ You have blocked the author or you have been blocked by the
+ author.
+
- Back
+ Back
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index b72121a375..49b769e13c 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}
/>
- This post has been deleted.
+
+ This post has been deleted.
+
)
}
@@ -650,9 +653,11 @@ function ExpandedPostDetails({
{niceDate(post.indexedAt)}
{needsTranslation && (
<>
- •
+ •
- Translate
+
+ Translate
+
>
)}
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 1ee2097856..d7b7b8ed79 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()
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">
- Edit Profile
+ Edit Profile
) : 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="">
- Unblock
+ Unblock
)
@@ -439,7 +442,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
size={14}
/>
- Following
+ Following
) : (
@@ -455,7 +458,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
style={[palInverted.text, s.mr5]}
/>
- Follow
+ Follow
)}
@@ -465,7 +468,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
@@ -488,7 +491,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
{view.viewer.followedBy && !blockHide ? (
- Follows you
+ Follows you
) : undefined}
@@ -533,7 +536,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
{following}{' '}
- following
+ following
@@ -572,7 +575,7 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
onPress={onPressBack}
hitSlop={BACK_HITSLOP}
accessibilityRole="button"
- accessibilityLabel="Back"
+ accessibilityLabel={_(msg`Back`)}
accessibilityHint="">
diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx
index 0b8015aa92..251d3141b2 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()
+ 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}}>
diff --git a/src/view/com/search/HeaderWithInput.tsx b/src/view/com/search/HeaderWithInput.tsx
index 1a6b427c61..04cbeab6ef 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(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">
@@ -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="">
- Cancel
+
+ Cancel
+
) : undefined}
diff --git a/src/view/com/util/AccountDropdownBtn.tsx b/src/view/com/util/AccountDropdownBtn.tsx
index 29571696b1..2042531e97 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}) {
void) | undefined,
@@ -29,7 +30,7 @@ export function createCustomBackdrop(
return (
{
if (onClose !== undefined) {
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index 9db4573251..9bbea1c145 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({
{avatar ? (
{banner ? (
@@ -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">
- Try again
+ Try again
diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx
index 1bed60b5d8..ad8f50f5e6 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 */}
diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx
index 45abed6473..a10841450d 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
}) {
const theme = useTheme()
+ const {_} = useLingui()
const defaultCtrlColor = theme.palette.default.postCtrl
const {openModal} = useModalControls()
@@ -152,7 +155,7 @@ export function PostDropdownBtn({
diff --git a/src/view/com/util/forms/SearchInput.tsx b/src/view/com/util/forms/SearchInput.tsx
index c1eb82bd49..02b462b55d 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(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({
}>) {
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="">
diff --git a/src/view/com/util/moderation/PostAlerts.tsx b/src/view/com/util/moderation/PostAlerts.tsx
index 2c9a718590..bc5bf9b325 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
}) {
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]}>
{desc.name}{' '}
- Learn More
+ Learn More
diff --git a/src/view/com/util/moderation/PostHider.tsx b/src/view/com/util/moderation/PostHider.tsx
index a9ccf2ebdb..c2b857f54c 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 {
@@ -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="">
diff --git a/src/view/com/util/moderation/ProfileHeaderAlerts.tsx b/src/view/com/util/moderation/ProfileHeaderAlerts.tsx
index d2406e7ae9..d2675ca545 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
}) {
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]}>
@@ -49,7 +52,7 @@ export function ProfileHeaderAlerts({
{desc.name}
- Learn More
+ Learn More
)
diff --git a/src/view/com/util/moderation/ScreenHider.tsx b/src/view/com/util/moderation/ScreenHider.tsx
index c3d23b84d1..946f937e9e 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()
const {isMobile} = useWebMediaQueries()
@@ -62,14 +66,13 @@ export function ScreenHider({
- Content Warning
+ Content Warning
- This {screenDescription} has been flagged:{' '}
-
- {desc.name}
+ This {screenDescription} has been flagged:
+
+ {desc.name}.
- .{' '}
{
openModal({
@@ -79,10 +82,10 @@ export function ScreenHider({
})
}}
accessibilityRole="button"
- accessibilityLabel="Learn more about this warning"
+ accessibilityLabel={_(msg`Learn more about this warning`)}
accessibilityHint="">
- Learn More
+ Learn More
@@ -99,7 +102,7 @@ export function ScreenHider({
}}
style={styles.btn}>
- Go back
+ Go back
{!moderation.noOverride && (
@@ -108,7 +111,7 @@ export function ScreenHider({
onPress={() => setOverride(v => !v)}
style={styles.btn}>
- Show anyway
+ Show anyway
)}
diff --git a/src/view/com/util/post-ctrls/RepostButton.web.tsx b/src/view/com/util/post-ctrls/RepostButton.web.tsx
index 57f544d416..70f7229d4c 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 = ({
- You have not created any app passwords yet. You can create one by
- pressing the button below.
+
+ You have not created any app passwords yet. You can create one
+ by pressing the button below.
+
{!isTabletOrDesktop && }
@@ -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.
+
+ Use app passwords to login to other Bluesky clients without giving
+ full access to your account or password.
+
>
)
@@ -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="">
diff --git a/src/view/screens/Feeds.tsx b/src/view/screens/Feeds.tsx
index 169660a8f3..c2ec9208f4 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
@@ -34,6 +36,7 @@ export const FeedsScreen = withAuthRequired(
observer(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">
)
- }, [pal])
+ }, [pal, _])
const onRefresh = React.useCallback(() => {
myFeeds.refresh()
@@ -124,11 +127,11 @@ export const FeedsScreen = withAuthRequired(
},
]}>
- My Feeds
+ My Feeds
@@ -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) => (
))}
>
@@ -161,7 +164,7 @@ export const FeedsScreen = withAuthRequired(
},
]}>
- Discover new feeds
+ Discover new feeds
{!isMobile && (
- No results found for "{query}"
+ No results found for "{query}"
)
}
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={}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
@@ -289,7 +300,7 @@ function SavedFeed({feed}: {feed: FeedSourceModel}) {
{feed.error ? (
- Feed offline
+ Feed offline
) : null}
diff --git a/src/view/screens/Log.tsx b/src/view/screens/Log.tsx
index f524279a50..69c07edae0 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([])
@@ -47,7 +50,7 @@ export const LogScreen = observer(function Log({}: NativeStackScreenProps<
{entry.level === 'debug' ? (
diff --git a/src/view/screens/PreferencesHomeFeed.tsx b/src/view/screens/PreferencesHomeFeed.tsx
index 21c15931ff..da99dc16f7 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},
]}>
- Fine-tune the content you see on your home screen.
+ Fine-tune the content you see on your home screen.
@@ -92,10 +95,12 @@ export const PreferencesHomeFeed = observer(function PreferencesHomeFeedImpl({
- Show Replies
+ Show Replies
- Set this setting to "No" to hide all replies from your feed.
+
+ Set this setting to "No" to hide all replies from your feed.
+
- Reply Filters
+ Reply Filters
- Enable this setting to only see replies between people you follow.
+
+ Enable this setting to only see replies between people you
+ follow.
+
- Adjust the number of likes a reply must have to be shown in your
- feed.
+
+ Adjust the number of likes a reply must have to be shown in your
+ feed.
+
- Show Reposts
+ Show Reposts
- Set this setting to "No" to hide all reposts from your feed.
+
+ Set this setting to "No" to hide all reposts from your feed.
+
- Show Quote Posts
+ Show Quote Posts
- Set this setting to "No" to hide all quote posts from your feed.
- Reposts will still be visible.
+
+ Set this setting to "No" to hide all quote posts from your feed.
+ Reposts will still be visible.
+
- Show
- Posts from My Feeds
+
+ Show Posts from My Feeds
- Set this setting to "Yes" to show samples of your saved feeds in
- your following feed. This is an experimental feature.
+
+ Set this setting to "Yes" to show samples of your saved feeds in
+ your following feed. This is an experimental feature.
+
- Done
+
+ Done
+
diff --git a/src/view/screens/PreferencesThreads.tsx b/src/view/screens/PreferencesThreads.tsx
index af98a1833e..8a2db13ce2 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
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},
]}>
- Fine-tune the discussion threads.
+ Fine-tune the discussion threads.
@@ -45,10 +48,10 @@ export const PreferencesThreads = observer(function PreferencesThreadsImpl({
- Sort Replies
+ Sort Replies
- Sort replies to the same post by:
+ Sort replies to the same post by:
- Prioritize Your Follows
+ Prioritize Your Follows
- Show replies by people you follow before all other replies.
+
+ Show replies by people you follow before all other replies.
+
- Threaded
- Mode
+ {' '}
+ Threaded Mode
- Set this setting to "Yes" to show replies in a threaded view. This
- is an experimental feature.
+
+ Set this setting to "Yes" to show replies in a threaded view.
+ This is an experimental feature.
+
- Done
+
+ Done
+
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 9a25612add..f2aa7f05d2 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
@@ -38,6 +40,7 @@ export const ProfileScreen = withAuthRequired(
const store = useStores()
const setMinimalShellMode = useSetMinimalShellMode()
const {screen, track} = useAnalytics()
+ const {_} = useLingui()
const viewSelectorRef = React.useRef(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 - end of feed -
+ return (
+
+ - end of feed -
+
+ )
} else if (item === ProfileUiModel.LOADING_ITEM) {
return
} else if (item._reactKey === '__error__') {
@@ -296,7 +303,7 @@ export const ProfileScreen = withAuthRequired(
onPress={onPressCompose}
icon={}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx
index 3d10816420..8a8851c97a 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()
const {name: handleOrDid} = props.route.params
@@ -98,7 +101,7 @@ export const ProfileFeedScreen = withAuthRequired(
- Could not load feed
+ Could not load feed
{error}
@@ -107,12 +110,12 @@ export const ProfileFeedScreen = withAuthRequired(
@@ -142,6 +145,7 @@ export const ProfileFeedScreenInner = observer(
const pal = usePalette('default')
const store = useStores()
const {track} = useAnalytics()
+ const {_} = useLingui()
const feedSectionRef = React.useRef(null)
const {rkey, name: handleOrDid} = route.params
const uri = useMemo(
@@ -313,7 +317,7 @@ export const ProfileFeedScreenInner = observer(
}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
@@ -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({
/>
) : (
- No description
+ No description
)}
@@ -246,7 +249,7 @@ export const ProfileListScreenInner = observer(
/>
}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint=""
/>
@@ -270,6 +273,7 @@ const Header = observer(function HeaderImpl({
}) {
const pal = usePalette('default')
const palInverted = usePalette('inverted')
+ const {_} = useLingui()
const navigation = useNavigation()
const {openModal, closeModal} = useModalControls()
@@ -526,10 +530,12 @@ const Header = observer(function HeaderImpl({
- Subscribe
+
+ Subscribe
+
)
@@ -537,7 +543,7 @@ const Header = observer(function HeaderImpl({
@@ -624,6 +630,7 @@ const AboutSection = React.forwardRef(
ref,
) {
const pal = usePalette('default')
+ const {_} = useLingui()
const {isMobile} = useWebMediaQueries()
const scrollElRef = React.useRef(null)
@@ -662,7 +669,7 @@ const AboutSection = React.forwardRef(
testID="listDescriptionEmpty"
type="lg"
style={[{fontStyle: 'italic'}, pal.textLight]}>
- No description
+ No description
)}
@@ -688,12 +695,14 @@ const AboutSection = React.forwardRef(
paddingBottom: isMobile ? 14 : 18,
},
]}>
- Users
+
+ Users
+
{isOwner && (
@@ -702,7 +711,9 @@ const AboutSection = React.forwardRef(
color={pal.colors.link}
size={16}
/>
- Add
+
+ Add
+
)}
@@ -717,6 +728,7 @@ const AboutSection = React.forwardRef(
isCurateList,
isOwner,
onPressAddUser,
+ _,
])
const renderEmptyState = useCallback(() => {
@@ -757,6 +769,7 @@ const AboutSection = React.forwardRef(
function ErrorScreen({error}: {error: string}) {
const pal = usePalette('default')
const navigation = useNavigation()
+ const {_} = useLingui()
const onPressBack = useCallback(() => {
if (navigation.canGoBack()) {
navigation.goBack()
@@ -778,7 +791,7 @@ function ErrorScreen({error}: {error: string}) {
},
]}>
- Could not load list
+ Could not load list
{error}
@@ -787,12 +800,12 @@ function ErrorScreen({error}: {error: string}) {
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index f912996ef9..010de23dba 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
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 ? (
<>
- Account
+ Account
@@ -233,17 +236,17 @@ export const SettingsScreen = withAuthRequired(
openModal({name: 'change-email'})}>
- Change
+ Change
- Birthday:{' '}
+ Birthday:
openModal({name: 'birth-date-settings'})}>
- Show
+ Show
@@ -253,7 +256,7 @@ export const SettingsScreen = withAuthRequired(
) : null}
- Signed in as
+ Signed in as
@@ -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`}>
- Sign out
+ Sign out
@@ -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">
- Add account
+ Add account
- Invite a Friend
+ Invite a Friend
- Accessibility
+ Accessibility
- Appearance
+ Appearance
@@ -415,7 +418,7 @@ export const SettingsScreen = withAuthRequired(
- Basics
+ Basics
+ accessibilityLabel={_(msg`Opens the home feed preferences`)}>
- Home Feed Preferences
+ Home Feed Preferences
+ accessibilityLabel={_(msg`Opens the threads preferences`)}>
- Thread Preferences
+ Thread Preferences
- My Saved Feeds
+ My Saved Feeds
+ accessibilityLabel={_(msg`Opens configurable language settings`)}>
- Languages
+ Languages
+ accessibilityLabel={_(msg`Opens moderation settings`)}>
- Moderation
+ Moderation
- Advanced
+ Advanced
+ accessibilityLabel={_(msg`Opens the app password settings page`)}>
- App passwords
+ App passwords
- Change handle
+ Change handle
- Danger Zone
+ Danger Zone
- Delete my account…
+ Delete my account…
- Developer Tools
+ Developer Tools
+ accessibilityLabel={_(msg`Opens the system log page`)}>
- System log
+ System log
{__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`)}>
- Storybook
+ Storybook
+ accessibilityLabel={_(msg`Resets the preferences state`)}>
- Reset preferences state
+ Reset preferences state
+ accessibilityLabel={_(msg`Resets the onboarding state`)}>
- Reset onboarding state
+ Reset onboarding state
>
@@ -620,7 +623,9 @@ export const SettingsScreen = withAuthRequired(
accessibilityRole="button"
onPress={onPressBuildInfo}>
- Build version {AppInfo.appVersion} {AppInfo.updateChannel}
+
+ Build version {AppInfo.appVersion} {AppInfo.updateChannel}
+
@@ -630,7 +635,7 @@ export const SettingsScreen = withAuthRequired(
accessibilityRole="button"
onPress={onPressStatusPage}>
- Status page
+ Status page
@@ -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 (
- Verify email
+ Verify email openModal({name: 'verify-email'})}>
- Verify My Email
+ Verify My Email
- Protect your account by verifying your email.
+ Protect your account by verifying your email.
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index c8b3e09178..99e1d7d98a 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()
const {track} = useAnalytics()
@@ -158,7 +161,7 @@ export const DrawerContent = observer(function DrawerContentImpl() {
}
label="Lists"
- accessibilityLabel="Lists"
+ accessibilityLabel={_(msg`Lists`)}
accessibilityHint=""
onPress={onPressLists}
/>
}
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() {
- Feedback
+ Feedback
- Help
+ Help
diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx
index db4fa9d717..69a7c4c0e1 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=""
/>
diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx
index 39271605cd..b85823b6f8 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()
+ 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="">
{
@@ -222,7 +226,7 @@ function ComposeBtn() {
style={[styles.newPostBtn]}
onPress={onPressCompose}
accessibilityRole="button"
- accessibilityLabel="New post"
+ accessibilityLabel={_(msg`New post`)}
accessibilityHint="">
- New Post
+ New Post
)
diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx
index caecea4a8b..f54858b8a1 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(null)
const [isInputFocused, setIsInputFocused] = React.useState(false)
const [query, setQuery] = React.useState('')
@@ -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() {
- Cancel
+ Cancel
@@ -106,7 +109,7 @@ export const DesktopSearch = observer(function DesktopSearch() {
) : (
- No results found for {autocompleteView.prefix}
+ No results found for {autocompleteView.prefix}
)}
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index 10489489e9..792499521f 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() {
setDrawerOpen(false)}
style={styles.drawerMask}
- accessibilityLabel="Close navigation footer"
+ accessibilityLabel={t`Close navigation footer`}
accessibilityHint="Closes bottom navigation bar">
diff --git a/yarn.lock b/yarn.lock
index cd4f71a7a4..fd7cd19bed 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -353,6 +353,14 @@
"@babel/highlight" "^7.22.10"
chalk "^2.4.2"
+"@babel/code-frame@^7.22.13":
+ version "7.22.13"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
+ integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
+ dependencies:
+ "@babel/highlight" "^7.22.13"
+ chalk "^2.4.2"
+
"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
@@ -379,6 +387,27 @@
json5 "^2.2.2"
semver "^6.3.1"
+"@babel/core@^7.21.0", "@babel/core@^7.23.2":
+ version "7.23.2"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94"
+ integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.22.13"
+ "@babel/generator" "^7.23.0"
+ "@babel/helper-compilation-targets" "^7.22.15"
+ "@babel/helper-module-transforms" "^7.23.0"
+ "@babel/helpers" "^7.23.2"
+ "@babel/parser" "^7.23.0"
+ "@babel/template" "^7.22.15"
+ "@babel/traverse" "^7.23.2"
+ "@babel/types" "^7.23.0"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
"@babel/eslint-parser@^7.16.3", "@babel/eslint-parser@^7.18.2":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.10.tgz#bfdf3d1b32ad573fe7c1c3447e0b485e3a41fd09"
@@ -398,6 +427,16 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
+"@babel/generator@^7.21.1", "@babel/generator@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
+ integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
+ dependencies:
+ "@babel/types" "^7.23.0"
+ "@jridgewell/gen-mapping" "^0.3.2"
+ "@jridgewell/trace-mapping" "^0.3.17"
+ jsesc "^2.5.1"
+
"@babel/helper-annotate-as-pure@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
@@ -423,6 +462,17 @@
lru-cache "^5.1.1"
semver "^6.3.1"
+"@babel/helper-compilation-targets@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
+ integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==
+ dependencies:
+ "@babel/compat-data" "^7.22.9"
+ "@babel/helper-validator-option" "^7.22.15"
+ browserslist "^4.21.9"
+ lru-cache "^5.1.1"
+ semver "^6.3.1"
+
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.10", "@babel/helper-create-class-features-plugin@^7.22.5":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz#dd2612d59eac45588021ac3d6fa976d08f4e95a3"
@@ -463,6 +513,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
+"@babel/helper-environment-visitor@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
+ integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
+
"@babel/helper-function-name@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
@@ -471,6 +526,14 @@
"@babel/template" "^7.22.5"
"@babel/types" "^7.22.5"
+"@babel/helper-function-name@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
+ integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
+ dependencies:
+ "@babel/template" "^7.22.15"
+ "@babel/types" "^7.23.0"
+
"@babel/helper-hoist-variables@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
@@ -492,6 +555,13 @@
dependencies:
"@babel/types" "^7.22.5"
+"@babel/helper-module-imports@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0"
+ integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==
+ dependencies:
+ "@babel/types" "^7.22.15"
+
"@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129"
@@ -503,6 +573,17 @@
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.5"
+"@babel/helper-module-transforms@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz#3ec246457f6c842c0aee62a01f60739906f7047e"
+ integrity sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-module-imports" "^7.22.15"
+ "@babel/helper-simple-access" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/helper-validator-identifier" "^7.22.20"
+
"@babel/helper-optimise-call-expression@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e"
@@ -559,11 +640,21 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+"@babel/helper-validator-identifier@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
+ integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
+
"@babel/helper-validator-identifier@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==
+"@babel/helper-validator-option@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
+ integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==
+
"@babel/helper-validator-option@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
@@ -587,6 +678,15 @@
"@babel/traverse" "^7.22.10"
"@babel/types" "^7.22.10"
+"@babel/helpers@^7.23.2":
+ version "7.23.2"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767"
+ integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==
+ dependencies:
+ "@babel/template" "^7.22.15"
+ "@babel/traverse" "^7.23.2"
+ "@babel/types" "^7.23.0"
+
"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.10":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7"
@@ -596,11 +696,25 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
+"@babel/highlight@^7.22.13":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
+ integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.20"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+
"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.22.10", "@babel/parser@^7.22.5":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55"
integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
+"@babel/parser@^7.21.2", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
+ integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
+
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e"
@@ -1517,7 +1631,7 @@
dependencies:
regenerator-runtime "^0.14.0"
-"@babel/runtime@^7.21.0":
+"@babel/runtime@^7.20.13", "@babel/runtime@^7.21.0":
version "7.23.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885"
integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==
@@ -1533,6 +1647,15 @@
"@babel/parser" "^7.22.5"
"@babel/types" "^7.22.5"
+"@babel/template@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
+ integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
+ dependencies:
+ "@babel/code-frame" "^7.22.13"
+ "@babel/parser" "^7.22.15"
+ "@babel/types" "^7.22.15"
+
"@babel/traverse@^7.20.0", "@babel/traverse@^7.22.10", "@babel/traverse@^7.7.2", "@babel/traverse@^7.7.4":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa"
@@ -1549,6 +1672,22 @@
debug "^4.1.0"
globals "^11.1.0"
+"@babel/traverse@^7.23.2":
+ version "7.23.2"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+ integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
+ dependencies:
+ "@babel/code-frame" "^7.22.13"
+ "@babel/generator" "^7.23.0"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/parser" "^7.23.0"
+ "@babel/types" "^7.23.0"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
version "7.22.10"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03"
@@ -1558,6 +1697,15 @@
"@babel/helper-validator-identifier" "^7.22.5"
to-fast-properties "^2.0.0"
+"@babel/types@^7.21.2", "@babel/types@^7.22.15", "@babel/types@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
+ integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
+ dependencies:
+ "@babel/helper-string-parser" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.20"
+ to-fast-properties "^2.0.0"
+
"@bam.tech/react-native-image-resizer@^3.0.4":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@bam.tech/react-native-image-resizer/-/react-native-image-resizer-3.0.5.tgz#6661ba020de156268f73bdc92fbb93ef86f88a13"
@@ -1788,6 +1936,116 @@
resolved "https://registry.yarnpkg.com/@emoji-mart/react/-/react-1.1.1.tgz#ddad52f93a25baf31c5383c3e7e4c6e05554312a"
integrity sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==
+"@esbuild/android-arm64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd"
+ integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==
+
+"@esbuild/android-arm@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d"
+ integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==
+
+"@esbuild/android-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1"
+ integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==
+
+"@esbuild/darwin-arm64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276"
+ integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==
+
+"@esbuild/darwin-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb"
+ integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==
+
+"@esbuild/freebsd-arm64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2"
+ integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==
+
+"@esbuild/freebsd-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4"
+ integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==
+
+"@esbuild/linux-arm64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb"
+ integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==
+
+"@esbuild/linux-arm@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a"
+ integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==
+
+"@esbuild/linux-ia32@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a"
+ integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==
+
+"@esbuild/linux-loong64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72"
+ integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==
+
+"@esbuild/linux-mips64el@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289"
+ integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==
+
+"@esbuild/linux-ppc64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7"
+ integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==
+
+"@esbuild/linux-riscv64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09"
+ integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==
+
+"@esbuild/linux-s390x@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829"
+ integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==
+
+"@esbuild/linux-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4"
+ integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==
+
+"@esbuild/netbsd-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462"
+ integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==
+
+"@esbuild/openbsd-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691"
+ integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==
+
+"@esbuild/sunos-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273"
+ integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==
+
+"@esbuild/win32-arm64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f"
+ integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==
+
+"@esbuild/win32-ia32@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03"
+ integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==
+
+"@esbuild/win32-x64@0.17.19":
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061"
+ integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==
+
"@eslint-community/eslint-utils@^4.2.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@@ -2842,6 +3100,103 @@
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
+"@lingui/babel-plugin-extract-messages@4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-4.5.0.tgz#71e56cc2eae73890caeea15a00ae4965413430ec"
+ integrity sha512-jZq3Gbi691jsHyQ4+OPnGgIqZt5eKEGnmI75akYlZpwTPxF7n+hiuKlQS+YB3xfKvcvlAED76ZAMCcwYG5fNrQ==
+
+"@lingui/cli@^4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/cli/-/cli-4.5.0.tgz#fb8685cb682cf624b6e5b6d1207f8127b98ed95a"
+ integrity sha512-MzhxNUNd+YYEmK79TwmneUow5BuLwpOlrUrZq9EyIAWUM4N6kkCVkZ8VIMYCL4TXGQ4kBQjstgDpkF8wdFRtNg==
+ dependencies:
+ "@babel/core" "^7.21.0"
+ "@babel/generator" "^7.21.1"
+ "@babel/parser" "^7.21.2"
+ "@babel/runtime" "^7.21.0"
+ "@babel/types" "^7.21.2"
+ "@lingui/babel-plugin-extract-messages" "4.5.0"
+ "@lingui/conf" "4.5.0"
+ "@lingui/core" "4.5.0"
+ "@lingui/format-po" "4.5.0"
+ "@lingui/message-utils" "4.5.0"
+ babel-plugin-macros "^3.0.1"
+ chalk "^4.1.0"
+ chokidar "3.5.1"
+ cli-table "0.3.6"
+ commander "^10.0.0"
+ convert-source-map "^2.0.0"
+ date-fns "^2.16.1"
+ esbuild "^0.17.10"
+ glob "^7.1.4"
+ inquirer "^7.3.3"
+ micromatch "4.0.2"
+ normalize-path "^3.0.0"
+ ora "^5.1.0"
+ pathe "^1.1.0"
+ pkg-up "^3.1.0"
+ pofile "^1.1.4"
+ pseudolocale "^2.0.0"
+ ramda "^0.27.1"
+ source-map "^0.8.0-beta.0"
+
+"@lingui/conf@4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/conf/-/conf-4.5.0.tgz#09b39de3a03a9017cd8299b1d8df923c78447ebf"
+ integrity sha512-OBm4RQQtbpvmuazLWVpvpaOpt/xvu1PBv8WUX8QoW1vsROe/3P5BpRHRYFyMeZz5mhORJgis9lQtDTq145Ruug==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ chalk "^4.1.0"
+ cosmiconfig "^8.0.0"
+ jest-validate "^29.4.3"
+ jiti "^1.17.1"
+ lodash.get "^4.4.2"
+
+"@lingui/core@4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/core/-/core-4.5.0.tgz#8b907238bd0b420b372272d0a757c56bed3aed14"
+ integrity sha512-8zTuIXJo5Qvjato7LWE6Q4RHiO4LjTBVOoRlqfOGYDp8VZ9w9P7Z7IJgxI7UP5Z1wiuEvnMdVF9I1C4acqXGlQ==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@lingui/message-utils" "4.5.0"
+ unraw "^3.0.0"
+
+"@lingui/format-po@4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/format-po/-/format-po-4.5.0.tgz#88dabeaa565ce5e4ff2a1b9865da7759b393af27"
+ integrity sha512-xQNzZ4RCQfh6TjzjUsyHz3B0R9FJuzhBit9R37NyMn6mL3kBTCUExpPczknm8gWZjtfFO4T8EH5eJhhC5vgJYg==
+ dependencies:
+ "@lingui/conf" "4.5.0"
+ "@lingui/message-utils" "4.5.0"
+ date-fns "^2.29.3"
+ pofile "^1.1.4"
+
+"@lingui/macro@^4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/macro/-/macro-4.5.0.tgz#4e779f4652200b7ecc6f3364fda840ae365fb996"
+ integrity sha512-6qha9YXuNnta4HCR+g6J6UPaAuAFlM1duqgznh4X7hHSsFG+m6oX7/srAMfU41Z8lbDmgXc3raqHLXFSdUNbYQ==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@babel/types" "^7.20.7"
+ "@lingui/conf" "4.5.0"
+ "@lingui/core" "4.5.0"
+ "@lingui/message-utils" "4.5.0"
+
+"@lingui/message-utils@4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/message-utils/-/message-utils-4.5.0.tgz#7ae9dc6cb65cbb5e2dc1b8cdcc4c8b92d5c7189f"
+ integrity sha512-iRqh2wvNtzJO3NStB77nEXEfeI53aVVjzD7/mBrEm/P0lC7sqPHk0WBQCfzE0N9xm6a+XHmHu3J+x2nnQ2OjcA==
+ dependencies:
+ "@messageformat/parser" "^5.0.0"
+
+"@lingui/react@^4.5.0":
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/@lingui/react/-/react-4.5.0.tgz#1cae72e89890f8d270b37cdde051a3c69df97727"
+ integrity sha512-dv/oxBshyaVJ3XzbPDnWn3abhwtaS1sx8cEO2qDjs+OhW0AeWD9hyVDrduf5SBIuXFJfJQNNA8+2P2nO0lxRbQ==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@lingui/core" "4.5.0"
+
"@lukeed/csprng@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@lukeed/csprng/-/csprng-1.1.0.tgz#1e3e4bd05c1cc7a0b2ddbd8a03f39f6e4b5e6cfe"
@@ -2861,6 +3216,13 @@
dependencies:
semver "7.5.4"
+"@messageformat/parser@^5.0.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.1.0.tgz#05e4851c782d633ad735791dd0a68ee65d2a7201"
+ integrity sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==
+ dependencies:
+ moo "^0.5.1"
+
"@miblanchard/react-native-slider@^2.3.1":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@miblanchard/react-native-slider/-/react-native-slider-2.3.1.tgz#79e0f1f9b1ce43ef25ee51ee9256c012e5dfa412"
@@ -6183,7 +6545,7 @@ any-promise@^1.0.0:
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
-anymatch@^3.0.3, anymatch@~3.1.2:
+anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
@@ -6578,7 +6940,7 @@ babel-plugin-jest-hoist@^29.6.3:
"@types/babel__core" "^7.1.14"
"@types/babel__traverse" "^7.0.6"
-babel-plugin-macros@^3.1.0:
+babel-plugin-macros@^3.0.1, babel-plugin-macros@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
@@ -6945,7 +7307,7 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
-braces@^3.0.2, braces@~3.0.2:
+braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@@ -7235,6 +7597,11 @@ char-regex@^2.0.0:
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e"
integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==
+chardet@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+ integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
charenc@0.0.2, charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@@ -7254,6 +7621,21 @@ child-process-promise@^2.2.0:
node-version "^1.0.0"
promise-polyfill "^6.0.1"
+chokidar@3.5.1:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
+ integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
+ dependencies:
+ anymatch "~3.1.1"
+ braces "~3.0.2"
+ glob-parent "~5.1.0"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.5.0"
+ optionalDependencies:
+ fsevents "~2.3.1"
+
chokidar@^3.4.2, chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
@@ -7344,6 +7726,13 @@ cli-spinners@^2.0.0, cli-spinners@^2.5.0:
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db"
integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==
+cli-table@0.3.6:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.6.tgz#e9d6aa859c7fe636981fd3787378c2a20bce92fc"
+ integrity sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==
+ dependencies:
+ colors "1.0.3"
+
cli-truncate@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389"
@@ -7352,6 +7741,11 @@ cli-truncate@^3.1.0:
slice-ansi "^5.0.0"
string-width "^5.0.0"
+cli-width@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
+ integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+
cliui@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
@@ -7477,6 +7871,11 @@ colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.20:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+colors@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+ integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==
+
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -7499,7 +7898,7 @@ commander@2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
-commander@^10.0.1:
+commander@^10.0.0, commander@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
@@ -7710,6 +8109,16 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
+cosmiconfig@^8.0.0:
+ version "8.3.6"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3"
+ integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==
+ dependencies:
+ import-fresh "^3.3.0"
+ js-yaml "^4.1.0"
+ parse-json "^5.2.0"
+ path-type "^4.0.0"
+
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -8021,7 +8430,7 @@ data-urls@^3.0.2:
whatwg-mimetype "^3.0.0"
whatwg-url "^11.0.0"
-date-fns@^2.30.0:
+date-fns@^2.16.1, date-fns@^2.29.3, date-fns@^2.30.0:
version "2.30.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
@@ -8817,6 +9226,34 @@ es6-object-assign@^1.1.0:
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==
+esbuild@^0.17.10:
+ version "0.17.19"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955"
+ integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==
+ optionalDependencies:
+ "@esbuild/android-arm" "0.17.19"
+ "@esbuild/android-arm64" "0.17.19"
+ "@esbuild/android-x64" "0.17.19"
+ "@esbuild/darwin-arm64" "0.17.19"
+ "@esbuild/darwin-x64" "0.17.19"
+ "@esbuild/freebsd-arm64" "0.17.19"
+ "@esbuild/freebsd-x64" "0.17.19"
+ "@esbuild/linux-arm" "0.17.19"
+ "@esbuild/linux-arm64" "0.17.19"
+ "@esbuild/linux-ia32" "0.17.19"
+ "@esbuild/linux-loong64" "0.17.19"
+ "@esbuild/linux-mips64el" "0.17.19"
+ "@esbuild/linux-ppc64" "0.17.19"
+ "@esbuild/linux-riscv64" "0.17.19"
+ "@esbuild/linux-s390x" "0.17.19"
+ "@esbuild/linux-x64" "0.17.19"
+ "@esbuild/netbsd-x64" "0.17.19"
+ "@esbuild/openbsd-x64" "0.17.19"
+ "@esbuild/sunos-x64" "0.17.19"
+ "@esbuild/win32-arm64" "0.17.19"
+ "@esbuild/win32-ia32" "0.17.19"
+ "@esbuild/win32-x64" "0.17.19"
+
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@@ -9603,6 +10040,15 @@ express@^4.17.2, express@^4.17.3, express@^4.18.2:
utils-merge "1.0.1"
vary "~1.1.2"
+external-editor@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+ integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+ dependencies:
+ chardet "^0.7.0"
+ iconv-lite "^0.4.24"
+ tmp "^0.0.33"
+
fast-base64-decode@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418"
@@ -9741,6 +10187,13 @@ fetch-retry@^4.1.1:
resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-4.1.1.tgz#fafe0bb22b54f4d0a9c788dff6dd7f8673ca63f3"
integrity sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==
+figures@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
+ integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@@ -10068,7 +10521,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-fsevents@^2.3.2, fsevents@~2.3.2:
+fsevents@^2.3.2, fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
@@ -10183,7 +10636,7 @@ github-from-package@0.0.0:
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==
-glob-parent@^5.1.2, glob-parent@~5.1.2:
+glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -10674,7 +11127,7 @@ hyphenate-style-name@^1.0.0, hyphenate-style-name@^1.0.3:
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
-iconv-lite@0.4.24:
+iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -10740,7 +11193,7 @@ import-fresh@^2.0.0:
caller-path "^2.0.0"
resolve-from "^3.0.0"
-import-fresh@^3.1.0, import-fresh@^3.2.1:
+import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
@@ -10802,6 +11255,25 @@ inline-style-prefixer@^6.0.1:
css-in-js-utils "^3.1.0"
fast-loops "^1.1.3"
+inquirer@^7.3.3:
+ version "7.3.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
+ integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ chalk "^4.1.0"
+ cli-cursor "^3.1.0"
+ cli-width "^3.0.0"
+ external-editor "^3.0.3"
+ figures "^3.0.0"
+ lodash "^4.17.19"
+ mute-stream "0.0.8"
+ run-async "^2.4.0"
+ rxjs "^6.6.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+ through "^2.3.6"
+
internal-ip@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
@@ -12113,6 +12585,18 @@ jest-validate@^29.2.1, jest-validate@^29.6.3:
leven "^3.1.0"
pretty-format "^29.6.3"
+jest-validate@^29.4.3:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
+ integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ leven "^3.1.0"
+ pretty-format "^29.7.0"
+
jest-watch-select-projects@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/jest-watch-select-projects/-/jest-watch-select-projects-2.0.0.tgz#4373d7e4de862aae28b46e036b669a4c913ea867"
@@ -12250,6 +12734,11 @@ jimp-compact@0.16.1:
resolved "https://registry.yarnpkg.com/jimp-compact/-/jimp-compact-0.16.1.tgz#9582aea06548a2c1e04dd148d7c3ab92075aefa3"
integrity sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==
+jiti@^1.17.1:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
+ integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
+
jiti@^1.18.2:
version "1.19.3"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.3.tgz#ef554f76465b3c2b222dc077834a71f0d4a37569"
@@ -12803,6 +13292,11 @@ lodash.defaults@^4.2.0:
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
+
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
@@ -13447,6 +13941,14 @@ metro@0.76.8:
ws "^7.5.1"
yargs "^17.6.2"
+micromatch@4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
+ integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
+ dependencies:
+ braces "^3.0.1"
+ picomatch "^2.0.5"
+
micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
@@ -13618,6 +14120,11 @@ moment@^2.19.3:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
+moo@^0.5.1:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
+ integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -13659,6 +14166,11 @@ multipipe@^4.0.0:
duplexer2 "^0.1.2"
object-assign "^4.1.0"
+mute-stream@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+ integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
mv@~2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2"
@@ -14150,7 +14662,7 @@ ora@3.4.0:
strip-ansi "^5.2.0"
wcwidth "^1.0.1"
-ora@^5.4.1:
+ora@^5.1.0, ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
@@ -14447,6 +14959,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+pathe@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a"
+ integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==
+
peek-readable@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
@@ -14525,7 +15042,7 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1:
+picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -14669,6 +15186,11 @@ pngjs@^3.3.0:
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
+pofile@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.1.4.tgz#eab7e29f5017589b2a61b2259dff608c0cad76a2"
+ integrity sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g==
+
postcss-attribute-case-insensitive@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741"
@@ -15343,6 +15865,15 @@ pretty-format@^29.0.0, pretty-format@^29.0.3, pretty-format@^29.6.3:
ansi-styles "^5.0.0"
react-is "^18.0.0"
+pretty-format@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
+ integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -15580,6 +16111,13 @@ proxy-from-env@^1.1.0:
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+pseudolocale@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pseudolocale/-/pseudolocale-2.0.0.tgz#4dbe725a6b5a6fb71aba8ba64ae2be71f5267316"
+ integrity sha512-g1K9tCQYY4e3UGtnW8qs3kGWAOONxt7i5wuOFvf3N1EIIRhiLVIhZ9AM/ZyGTxsp231JbFywJU/EbJ5ZoqnZdg==
+ dependencies:
+ commander "^10.0.0"
+
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
@@ -15664,6 +16202,11 @@ raf@^3.4.1:
dependencies:
performance-now "^2.1.0"
+ramda@^0.27.1:
+ version "0.27.2"
+ resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1"
+ integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==
+
randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -16200,6 +16743,13 @@ readable-web-to-node-stream@^3.0.0:
dependencies:
readable-stream "^3.6.0"
+readdirp@~3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
+ integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
+ dependencies:
+ picomatch "^2.2.1"
+
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@@ -16606,6 +17156,11 @@ rtl-detect@^1.0.2:
resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6"
integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==
+run-async@^2.4.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+ integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@@ -16613,6 +17168,13 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
+rxjs@^6.6.0:
+ version "6.6.7"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
+ integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
+ dependencies:
+ tslib "^1.9.0"
+
rxjs@^7.5.2:
version "7.8.1"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
@@ -17854,7 +18416,7 @@ through2@^2.0.1:
readable-stream "~2.3.6"
xtend "~4.0.1"
-through@2:
+through@2, through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
@@ -18017,7 +18579,7 @@ tsconfig-paths@^3.14.2:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^1.8.1, tslib@^1.9.3:
+tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -18300,6 +18862,11 @@ unquote@~1.1.1:
resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544"
integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==
+unraw@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/unraw/-/unraw-3.0.0.tgz#73443ed70d2ab09ccbac2b00525602d5991fbbe3"
+ integrity sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg==
+
upath@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"