personal fork of bluesky app bsky.kelinci.net
0

Configure Feed

Select the types of activity you want to include in your feed.

refactor: reorganize and dedupe message catalog

dissolve the namespace-artifact files (view.action/label/empty) and the
misc aggregation files (components/screens/view.misc) into feature-named
files, so every key's prefix matches its filename. relocate or rename the
contained keys to their feature home, splitting out 14 new per-component
and per-screen files. merge duplicate and near-duplicate strings onto a
single key (generic errors, audience-option labels, casing/apostrophe
drift, etc.). the three large files (composer, messages, settings) are
deliberately kept whole.

paraglide:compile and typecheck pass.

+331 -336
+29 -2
messages/en/common.json
··· 1 1 { 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "common.a11y.avatar": "{name}'s avatar", 3 4 "common.a11y.closeDialog": "Close dialog", 4 5 "common.a11y.goBack": "Returns to previous page", 6 + "common.a11y.goHome": "Returns to home page", 5 7 "common.a11y.moreOptions": "More options", 6 8 "common.a11y.openDrawerMenu": "Open drawer menu", 7 9 "common.a11y.openEmojiPicker": "Open emoji picker", ··· 13 15 "common.a11y.textInput": "Text input field", 14 16 "common.account.action.addAnother": "Add another account", 15 17 "common.account.action.switch": "Switch account", 18 + "common.account.action.switchTo": "Switch to {handle}", 16 19 "common.account.automated": "Automated account", 17 20 "common.account.deleted": "Deleted Account", 18 21 "common.account.privacy": "Account & privacy", 22 + "common.account.switcher.label": "Switch accounts", 19 23 "common.action.add": "Add", 20 24 "common.action.addPeople": "Add people", 21 25 "common.action.back": "Back", ··· 48 52 "common.action.submit": "Submit", 49 53 "common.action.translate": "Translate", 50 54 "common.action.tryAgain": "Try again", 55 + "common.action.undo": "Undo", 51 56 "common.action.uploadFromFiles": "Upload from Files", 52 57 "common.altText.badge": "ALT", 53 58 "common.altText.label": "Alt text", ··· 70 75 "common.block.byList.title": "User Blocked by List", 71 76 "common.block.byYou.message": "You have blocked this user. You cannot view their content.", 72 77 "common.block.byYou.title": "User Blocked", 78 + "common.block.empty": "You have not blocked any accounts yet. To block an account, go to their profile and select \\\"Block account\\\" from the menu on their account.", 73 79 "common.block.interactionError": "Cannot interact with a blocked user", 74 80 "common.block.unblockedToast": "Account unblocked", 75 81 "common.block.unblockHint": "The account will be able to interact with you after unblocking.", ··· 108 114 "common.chat.settingsTitle": "Group chat settings", 109 115 "common.compose.action.compose": "Compose new post", 110 116 "common.compose.action.new": "New post", 117 + "common.compose.action.photo": "Post a photo", 118 + "common.compose.action.video": "Post a video", 111 119 "common.compose.action.write": "Write post", 120 + "common.compose.action.writePost": "Write a post", 112 121 "common.compose.placeholder": "What's up?", 113 122 "common.compose.replyPlaceholder": "Write your reply", 114 123 "common.compose.sayHello": "Say hello!", ··· 117 126 "common.discardChanges.title": "Discard changes?", 118 127 "common.embed.content": "(contains embedded content)", 119 128 "common.error.connection": "There was a problem with your internet connection, please try again", 120 - "common.error.generic": "An issue occurred, please try again.", 129 + "common.error.generic": "Something went wrong. Please try again.", 121 130 "common.error.heading": "Error", 122 131 "common.error.issueConnection": "There was an issue. Please check your internet connection and try again.", 123 132 "common.error.issueWithDetail": "There was an issue! {error}", ··· 200 209 } 201 210 ], 202 211 "common.follow.followsYou": "Follows you", 212 + "common.follow.knownFollowers.empty": "Not followed by anyone you’re following", 203 213 "common.follow.noLongerFollowing": "No longer following {name}", 204 214 "common.gif.a11y.pause": "Pause GIF", 205 215 "common.gif.a11y.play": "Play GIF", ··· 226 236 } 227 237 ], 228 238 "common.like.likedByTitle": "Liked By", 239 + "common.list.action.new": "New list", 229 240 "common.list.byCreator": "List by {handle}", 241 + "common.list.create": "Create a list", 242 + "common.list.description": "Lists allow you to see content from your favorite people.", 230 243 "common.list.empty": "You have no lists.", 244 + "common.list.emptyUser": "No lists", 245 + "common.list.endOfList": "You have reached the end", 231 246 "common.list.fetchError": "There was an issue fetching your lists. Tap here to try again.", 247 + "common.list.hidden": "Hidden list", 232 248 "common.list.label": "Lists", 249 + "common.list.moderation.description": "Public, sharable lists of users to mute or block in bulk.", 250 + "common.list.moderationBy": "Moderation list by {handle}", 251 + "common.list.noResults": "No results found", 233 252 "common.liveNow.report": "Report this livestream", 253 + "common.media.empty": "No media yet", 234 254 "common.media.label": "Media", 235 255 "common.mention.label": "Mentions", 236 256 "common.moderation.accountHint": "This moderation was applied to the entire user account and will appear on all posts.", ··· 257 277 "common.mute.byList.title": "Account Muted by List", 258 278 "common.mute.byYou.message": "You have muted this account.", 259 279 "common.mute.byYou.title": "Account Muted", 280 + "common.mute.empty": "You have not muted any accounts yet. To mute an account, go to their profile and select \\\"Mute account\\\" from the menu on their account.", 260 281 "common.mute.mutedToast": "Account muted", 261 282 "common.mute.status": "Muted", 262 283 "common.mute.unmutedToast": "Account unmuted", ··· 287 308 "common.nav.home": "Home", 288 309 "common.nav.notifications": "Notifications", 289 310 "common.nav.profile": "Profile", 311 + "common.nav.saved": "Saved", 290 312 "common.nav.settings": "Settings", 291 313 "common.notifications.loadSettingsError": "Failed to load notification settings.", 292 314 "common.notifications.settingsTitle": "Notification settings", ··· 303 325 "common.profile.action.view": "View profile", 304 326 "common.quote.label": "Quotes", 305 327 "common.quote.post": "Quote post", 328 + "common.reply.empty": "No replies yet", 306 329 "common.reply.label": "Replies", 307 330 "common.requests.action.request": "Request to join", 308 331 "common.requests.action.rescind": "Rescind request", ··· 331 354 "common.share.action.copyLink": "Copy link", 332 355 "common.share.action.share": "Share", 333 356 "common.share.copiedToast": "Copied to clipboard", 357 + "common.sourceCode": "Source code", 334 358 "common.starterPack.action.add": "Add to starter packs", 335 - "common.starterPack.action.create": "Create a starter pack", 359 + "common.starterPack.action.create": "Create a Starter Pack", 336 360 "common.starterPack.byYou": "Starter pack by you", 361 + "common.starterPack.empty": "No Starter Packs yet", 337 362 "common.starterPack.label": "Starter Pack", 338 363 "common.starterPack.sectionTitle": "Starter Packs", 339 364 "common.status.all": "All", ··· 358 383 "common.time.forever": "Forever", 359 384 "common.time.hours24": "24 hours", 360 385 "common.verification.settingsTitle": "Verification Settings", 386 + "common.video.empty": "No video posts yet", 387 + "common.video.label": "Videos", 361 388 "common.video.loading": "Loading video" 362 389 }
+7
messages/en/components.accountList.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.accountList.a11y.continueAs": "Continue as {handle} (currently signed in)", 4 + "components.accountList.a11y.signInAs": "Sign in as {handle}", 5 + "components.accountList.a11y.signInOther": "Sign in to account that is not listed", 6 + "components.accountList.other": "Other account" 7 + }
+5
messages/en/components.appLanguageDropdown.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.appLanguageDropdown.a11y.change": "Change app language", 4 + "components.appLanguageDropdown.a11y.select": "Select an app language" 5 + }
+6
messages/en/components.botAccountAlert.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.botAccountAlert.descriptionByOwner": "This account has been marked as automated by its owner.", 4 + "components.botAccountAlert.descriptionByYou": "You have marked this account as automated. You can remove it at any time from your account settings.", 5 + "components.botAccountAlert.openSettings": "Open settings" 6 + }
+5 -1
messages/en/components.dialogs.json
··· 157 157 "components.dialogs.starterPack.error.add": "Failed to add to starter pack", 158 158 "components.dialogs.starterPack.error.remove": "Failed to remove from starter pack", 159 159 "components.dialogs.starterPack.newTitle": "New starter pack", 160 - "components.dialogs.starterPack.removedToast": "Removed from starter pack" 160 + "components.dialogs.starterPack.removedToast": "Removed from starter pack", 161 + "components.dialogs.suggestedFollows.a11y.searchTab": "Search for \\\"{interestsDisplayName}\\\"", 162 + "components.dialogs.suggestedFollows.a11y.searchTabActive": "Search for \\\"{interestsDisplayName}\\\" (active)", 163 + "components.dialogs.suggestedFollows.searchPlaceholder": "Search by name or interest", 164 + "components.dialogs.suggestedFollows.title": "Find people to follow" 161 165 }
-5
messages/en/components.dms.json
··· 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 3 "components.dms.account.tooNew.message": "Your account must be at least 7 days old to create a new group chat.", 4 4 "components.dms.account.tooNew.title": "Your account is too new", 5 - "components.dms.block.action.afterReport": "Block user", 6 5 "components.dms.block.action.block": "Block user", 7 6 "components.dms.block.hiddenBlockingYou": "Messages from this person are hidden while they are blocking you.", 8 7 "components.dms.block.hiddenYouBlocking": "Messages from this person are hidden while you are blocking them.", ··· 30 29 "components.dms.chat.action.markAsRead": "Mark as read", 31 30 "components.dms.chat.action.message": "Message {handle}", 32 31 "components.dms.chat.action.start": "Start chat", 33 - "components.dms.chat.error.network": "We’re having network issues, try again", 34 32 "components.dms.chat.error.open": "An issue occurred while trying to open the chat", 35 33 "components.dms.chat.error.recipientNotFollowed": "Chat recipient is not followed by the sender.", 36 34 "components.dms.chat.error.start": "An issue occurred starting the chat, please try again.", 37 35 "components.dms.chat.error.suspended": "Suspended accounts cannot participate in chat.", 38 36 "components.dms.chat.error.userDisabled": "This user has disabled chat and cannot be messaged.", 39 37 "components.dms.chat.readOnlyHint": "You can read chat history but can't send new messages.", 40 - "components.dms.delete.action.conversation": "Delete Conversation", 41 38 "components.dms.delete.action.forMe": "Delete for me", 42 39 "components.dms.delete.action.message": "Delete message", 43 40 "components.dms.delete.action.messageForMe": "Delete message for me", ··· 63 60 "components.dms.invite.edited": "Invite link edited", 64 61 "components.dms.invite.enabled": "Invite link enabled", 65 62 "components.dms.invite.requested": "Requested", 66 - "components.dms.leave.action.afterReport": "Leave conversation", 67 63 "components.dms.leave.action.conversation": "Leave conversation", 68 64 "components.dms.leave.conversationLeft": "Conversation left", 69 65 "components.dms.leave.error.leave": "Could not leave chat", ··· 124 120 "components.dms.reaction.title": "Reactions", 125 121 "components.dms.recipient.error.blockedYou": "One of the selected recipients has blocked you and cannot be messaged.", 126 122 "components.dms.recipient.error.cannotAdd": "{handle} can’t be added", 127 - "components.dms.recipient.error.cannotMessage": "{handle} can’t be messaged", 128 123 "components.dms.recipient.error.noGroups": "One of the selected recipients does not allow group chats.", 129 124 "components.dms.recipient.error.notFollowed": "A selected recipient is not followed by the sender.", 130 125 "components.dms.recipient.error.notFound": "Unable to find a selected recipient.",
+5
messages/en/components.editableBanner.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.editableBanner.edit": "Edit banner", 4 + "components.editableBanner.remove": "Remove Banner" 5 + }
+5
messages/en/components.editableUserAvatar.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.editableUserAvatar.edit": "Edit avatar", 4 + "components.editableUserAvatar.remove": "Remove Avatar" 5 + }
+8
messages/en/components.feedInterstitials.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.feedInterstitials.action.browseMore": "Browse more accounts", 4 + "components.feedInterstitials.action.dismiss": "Dismiss this suggestion", 5 + "components.feedInterstitials.action.seeMore": "See more", 6 + "components.feedInterstitials.seeMoreA11y": "See more suggested profiles", 7 + "components.feedInterstitials.title": "Suggested for you" 8 + }
-49
messages/en/components.misc.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "components.accountList.a11y.continueAs": "Continue as {handle} (currently signed in)", 4 - "components.accountList.a11y.signInAs": "Sign in as {handle}", 5 - "components.accountList.a11y.signInOther": "Sign in to account that is not listed", 6 - "components.accountList.other": "Other account", 7 - "components.appLanguageDropdown.a11y.change": "Change app language", 8 - "components.appLanguageDropdown.a11y.select": "Select an app language", 9 - "components.botAccountAlert.descriptionByOwner": "This account has been marked as automated by its owner.", 10 - "components.botAccountAlert.descriptionByYou": "You have marked this account as automated. You can remove it at any time from your account settings.", 11 - "components.botAccountAlert.openSettings": "Open settings", 12 - "components.clampedPostText.action.expand": "Expand post text", 13 - "components.clampedPostText.action.showMore": "Show More", 14 - "components.dialog.close": "Close active dialog", 15 - "components.editableBanner.edit": "Edit banner", 16 - "components.editableBanner.remove": "Remove Banner", 17 - "components.editableUserAvatar.edit": "Edit avatar", 18 - "components.editableUserAvatar.remove": "Remove Avatar", 19 - "components.externalEmbed.a11y.play": "Play {title}", 20 - "components.externalEmbed.a11y.player": "Embedded player", 21 - "components.externalEmbed.a11y.playVideo": "Play Video", 22 - "components.feedInterstitials.a11y.seeMore": "See more suggested profiles", 23 - "components.feedInterstitials.action.browseMore": "Browse more accounts", 24 - "components.feedInterstitials.action.dismiss": "Dismiss this suggestion", 25 - "components.feedInterstitials.action.seeMore": "See more", 26 - "components.feedInterstitials.title": "Suggested for you", 27 - "components.forms.clearSearch": "Clear search query", 28 - "components.imageEmbed.a11y.carousel": "carousel", 29 - "components.imageEmbed.a11y.gallery": "Image gallery, {count} images", 30 - "components.imageEmbed.a11y.imagePosition": "Image {index} of {imageCount}", 31 - "components.imageEmbed.a11y.slide": "slide", 32 - "components.interestTabs.a11y.categoryActive": "\\\"{interestsDisplayName}\\\" category (active)", 33 - "components.interestTabs.a11y.categorySelect": "Select \\\"{interestsDisplayName}\\\" category", 34 - "components.knownFollowers.empty": "Not followed by anyone you’re following", 35 - "components.listCard.hidden": "Hidden list", 36 - "components.listCard.moderationListBy": "Moderation list by {handle}", 37 - "components.lists.endOfList": "You have reached the end", 38 - "components.lists.error": "Something went wrong!", 39 - "components.lists.noResults": "No results found", 40 - "components.suggestedFollowsDialog.a11y.searchTab": "Search for \\\"{interestsDisplayName}\\\"", 41 - "components.suggestedFollowsDialog.a11y.searchTabActive": "Search for \\\"{interestsDisplayName}\\\" (active)", 42 - "components.suggestedFollowsDialog.searchPlaceholder": "Search by name or interest", 43 - "components.suggestedFollowsDialog.title": "Find people to follow", 44 - "components.trendingTopics.a11y.browseAbout": "Browse posts about {displayName}", 45 - "components.trendingTopics.a11y.browseStarterPack": "Browse starter pack {displayName}", 46 - "components.trendingTopics.a11y.browseTag": "Browse posts tagged with {displayName}", 47 - "components.trendingTopics.a11y.browseTopic": "Browse topic {displayName}", 48 - "components.userAvatar.avatar": "{name}'s avatar" 49 - }
+3 -2
messages/en/components.moderation.json
··· 18 18 "components.moderation.block.noSeePosts": "They can't see your posts and you won't see theirs or any replies to them", 19 19 "components.moderation.block.unblockTitle": "Unblock account?", 20 20 "components.moderation.chat.current": "Current chat", 21 - "components.moderation.chat.error.leave": "Could not leave chat.", 22 21 "components.moderation.chat.error.mustBeOwnerToRemove": "You must be a chat owner to remove a member.", 23 22 "components.moderation.chat.error.notFound": "Chat not found.", 24 23 "components.moderation.chat.error.ownerCannotLeave": "Chat owners cannot leave a group chat.", ··· 29 28 "components.moderation.chat.mutualGroups": "Mutual group chats", 30 29 "components.moderation.chat.theyOwn": "They own this chat", 31 30 "components.moderation.chat.youOwn": "You own this chat", 32 - "components.moderation.error.generic": "Something went wrong. Please try again.", 33 31 "components.moderation.label.accountSuffix": "{name} (Account)", 34 32 "components.moderation.label.appliedByYou": "This label was applied by you.", 35 33 "components.moderation.label.appliedToAccount": "The following labels were applied to your account.", ··· 146 144 "components.moderation.report.message": "Report this message", 147 145 "components.moderation.report.post": "Report this post", 148 146 "components.moderation.report.reportingFor": "Reporting for", 147 + "components.moderation.report.retry": "Retry loading report options", 149 148 "components.moderation.report.reviewPrompt.conversation": "Why should this conversation be reviewed?", 150 149 "components.moderation.report.reviewPrompt.feed": "Why should this feed be reviewed?", 151 150 "components.moderation.report.reviewPrompt.list": "Why should this list be reviewed?", ··· 158 157 "components.moderation.report.starterPack": "Report this starter pack", 159 158 "components.moderation.report.submit": "Submit report", 160 159 "components.moderation.report.user": "Report this user", 160 + "components.moderation.screenHider.profile": "profile", 161 + "components.moderation.screenHider.user": "user", 161 162 "components.moderation.service.change.a11yLabel": "Change moderation service", 162 163 "components.moderation.service.change.label": "Change", 163 164 "components.moderation.service.choose": "Choose a moderation service",
+8
messages/en/components.post.json
··· 1 1 { 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.post.external.a11y.play": "Play {title}", 4 + "components.post.external.a11y.player": "Embedded player", 5 + "components.post.image.a11y.carousel": "carousel", 6 + "components.post.image.a11y.gallery": "Image gallery, {count} images", 7 + "components.post.image.a11y.imagePosition": "Image {index} of {imageCount}", 8 + "components.post.image.a11y.slide": "slide", 3 9 "components.post.publication.action.subscribe": "Subscribe on {name}", 4 10 "components.post.publication.action.subscribeTo": "Subscribe to {publicationTitle} on {name}", 5 11 "components.post.publication.action.view": "View publication", ··· 24 30 "components.post.state.deleted": "Deleted", 25 31 "components.post.state.removedByAuthor": "Removed by author", 26 32 "components.post.state.removedByYou": "Removed by you", 33 + "components.post.text.expand": "Expand post text", 34 + "components.post.text.showMore": "Show More", 27 35 "components.post.video.a11y.pause": "Pause video", 28 36 "components.post.video.a11y.play": "Play video", 29 37 "components.post.video.a11y.player": "Embedded video player",
-1
messages/en/components.postControls.json
··· 80 80 "components.postControls.repost.action.undo": "Undo repost", 81 81 "components.postControls.save.action": "Add to saved posts", 82 82 "components.postControls.save.toast": "Post saved", 83 - "components.postControls.save.undo": "Undo", 84 83 "components.postControls.share.a11y": "Open share menu", 85 84 "components.postControls.share.sendViaDm": "Send via direct message", 86 85 "components.postControls.thread.mute.action": "Mute thread",
+1 -2
messages/en/components.starterPack.json
··· 14 14 "components.starterPack.create.another": "Create another", 15 15 "components.starterPack.edit.feeds": "Edit Feeds", 16 16 "components.starterPack.edit.people": "Edit People", 17 - "components.starterPack.list.empty": "Starter packs let you share your favorite feeds and people with your friends.", 17 + "components.starterPack.list.empty": "Starter Packs let you share your favorite feeds and people with your friends.", 18 18 "components.starterPack.list.error": "There was an issue fetching your starter packs. Tap here to try again.", 19 19 "components.starterPack.membership.action.add": "Add {displayName} to starter pack", 20 20 "components.starterPack.membership.action.remove": "Remove {displayName} from starter pack", 21 21 "components.starterPack.share.a11yLabel": "Share link dialog", 22 - "components.starterPack.share.copyLink": "Copy Link", 23 22 "components.starterPack.share.invitePrompt": "Invite people to this starter pack!", 24 23 "components.starterPack.share.message": "Share this starter pack and help people join your community on Bluesky." 25 24 }
+11
messages/en/components.trendingTopics.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "components.trendingTopics.a11y.browseAbout": "Browse posts about {displayName}", 4 + "components.trendingTopics.a11y.browseStarterPack": "Browse starter pack {displayName}", 5 + "components.trendingTopics.a11y.browseTag": "Browse posts tagged with {displayName}", 6 + "components.trendingTopics.a11y.browseTopic": "Browse topic {displayName}", 7 + "components.trendingTopics.a11y.options": "Trending options", 8 + "components.trendingTopics.hide.message": "You can update this later from your settings.", 9 + "components.trendingTopics.hide.title": "Hide trending topics?", 10 + "components.trendingTopics.title": "Trending" 11 + }
+1 -1
messages/en/features.liveNow.json
··· 42 42 "features.liveNow.duration.select": "Select duration", 43 43 "features.liveNow.expiry.none": "No expiry set", 44 44 "features.liveNow.expiry.value": "Expires in {duration} at {time}", 45 - "features.liveNow.goLive.confirm": "Go Live", 45 + "features.liveNow.goLive.confirm": "Go live", 46 46 "features.liveNow.goLive.description": "Add a temporary live status to your profile. When someone clicks on your avatar, they’ll see information about your live event.", 47 47 "features.liveNow.goLive.disabled": "Going live is currently disabled for your account", 48 48 "features.liveNow.goLive.ended": "You are no longer live",
+1 -3
messages/en/lib.json
··· 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 3 "lib.account.error.deactivated": "Account is deactivated", 4 4 "lib.account.error.suspended": "Account has been suspended", 5 - "lib.appPassword.featureUnavailable": "This feature is not available while using an app password. Please sign in with your main password.", 6 - "lib.appPassword.featureUnavailableCap": "This feature is not available while using an App Password. Please sign in with your main password.", 5 + "lib.appPassword.featureUnavailable": "This feature is not available while using an App Password. Please sign in with your main password.", 7 6 "lib.error.connectionFailed": "Unable to connect. Please check your internet connection and try again.", 8 7 "lib.error.handleResolveFailed": "Unable to resolve handle", 9 8 "lib.error.rateLimit": "You've reached the maximum number of requests allowed. Please try again later.", ··· 43 42 "lib.moderation.noNudity": "Does not include nudity.", 44 43 "lib.moderation.sexuallySuggestive": "Sexually Suggestive", 45 44 "lib.moderation.signedInOnly": "This user has requested that their content only be shown to signed-in users.", 46 - "lib.moderation.youHidden": "You have hidden this post", 47 45 "lib.moderation.youMuted": "You have muted this user", 48 46 "lib.profile.notFound": "Profile not found", 49 47 "lib.search.focusSearch": "Focus the search field",
+1
messages/en/navigation.json
··· 4 4 "navigation.chat.title": "Messages", 5 5 "navigation.developer.log.title": "Log", 6 6 "navigation.developer.storybook.title": "Storybook", 7 + "navigation.drawer.title": "Menu", 7 8 "navigation.feed.title": "Feed", 8 9 "navigation.followers.title": "Followers", 9 10 "navigation.hashtag.title": "Hashtag",
+6
messages/en/screens.bookmarks.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.bookmarks.backHome": "Button to go back to the home timeline", 4 + "screens.bookmarks.deletedPost": "This post was deleted by its author", 5 + "screens.bookmarks.empty": "Nothing saved yet" 6 + }
+7
messages/en/screens.feeds.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.feeds.action.addFollowing": "Add the default feed of only people you follow", 4 + "screens.feeds.action.useRecommended": "Use recommended", 5 + "screens.feeds.missingFollowing": "Looks like you're missing a following feed. {#t0}Click here to add one.{/t0}", 6 + "screens.feeds.noSaved": "Looks like you haven't saved any feeds! Use our recommendations or browse more below." 7 + }
+5
messages/en/screens.hashtag.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.hashtag.empty": "We couldn't find any results for that tag.", 4 + "screens.hashtag.fromAuthor": "From @{sanitizedAuthor}" 5 + }
+6
messages/en/screens.home.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.home.action.addRecommendedFeeds": "Add recommended feeds", 4 + "screens.home.action.browseOtherFeeds": "Browse other feeds", 5 + "screens.home.empty": "Looks like you unpinned all your feeds. But don't worry, you can add some below 😄" 6 + }
+5
messages/en/screens.log.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.log.entry.openDetails": "Opens additional details for a debug entry", 4 + "screens.log.entry.view": "View debug entry" 5 + }
-7
messages/en/screens.messages.json
··· 59 59 "screens.messages.deleteChat.deletedToast": "Chat deleted", 60 60 "screens.messages.deleteChat.error": "Failed to delete chat", 61 61 "screens.messages.deletedAccount.message": "This conversation is with a deleted or a deactivated account. Press for options", 62 - "screens.messages.dmSettings.everyone": "Everyone", 63 - "screens.messages.dmSettings.following": "People I follow", 64 62 "screens.messages.dmSettings.hint": "You can continue ongoing conversations regardless of which setting you choose.", 65 63 "screens.messages.dmSettings.label": "Allow direct messages from", 66 - "screens.messages.dmSettings.noOne": "No one", 67 - "screens.messages.error.generic": "Something went wrong", 68 64 "screens.messages.export.action": "Export chat data", 69 65 "screens.messages.follow.action": "Follow {displayName}", 70 66 "screens.messages.follow.following": "Following {displayName}", ··· 100 96 "screens.messages.inviteLink.privacy": "Your name, avatar, the name of the group chat, and the number of members will be visible to everyone.", 101 97 "screens.messages.inviteLink.view.a11y": "Click here to view the invite link for this group chat", 102 98 "screens.messages.inviteLink.view.hint": "View the invite link for this group chat", 103 - "screens.messages.inviteSettings.everyone": "Everyone", 104 - "screens.messages.inviteSettings.following": "People I follow", 105 99 "screens.messages.inviteSettings.label": "Allow group chat invites from", 106 - "screens.messages.inviteSettings.noOne": "No one", 107 100 "screens.messages.joinSettings.anyoneInstant": "Anyone can join instantly", 108 101 "screens.messages.joinSettings.anyoneRequest": "Anyone can request to join", 109 102 "screens.messages.joinSettings.followingInstant": "People I follow can join instantly",
-53
messages/en/screens.misc.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "screens.bookmarks.backHome": "Button to go back to the home timeline", 4 - "screens.bookmarks.deletedPost": "This post was deleted by its author", 5 - "screens.bookmarks.empty": "Nothing saved yet", 6 - "screens.feeds.action.addFollowing": "Add the default feed of only people you follow", 7 - "screens.feeds.action.useRecommended": "Use recommended", 8 - "screens.feeds.missingFollowing": "Looks like you're missing a following feed. {#t0}Click here to add one.{/t0}", 9 - "screens.feeds.noSaved": "Looks like you haven't saved any feeds! Use our recommendations or browse more below.", 10 - "screens.hashtag.empty": "We couldn't find any results for that tag.", 11 - "screens.hashtag.fromAuthor": "From @{sanitizedAuthor}", 12 - "screens.home.action.addRecommendedFeeds": "Add recommended feeds", 13 - "screens.home.action.browseOtherFeeds": "Browse other feeds", 14 - "screens.home.empty": "Looks like you unpinned all your feeds. But don't worry, you can add some below 😄", 15 - "screens.log.openDetails": "Opens additional details for a debug entry", 16 - "screens.log.viewEntry": "View debug entry", 17 - "screens.moderationInteractionSettings.description": "The following settings will be used as your defaults when creating new posts. You can edit these for a specific post from the composer.", 18 - "screens.moderationInteractionSettings.save.error": "Failed to save settings. Please try again.", 19 - "screens.moderationInteractionSettings.save.success": "Settings saved", 20 - "screens.notifications.empty": "No posts here", 21 - "screens.post.like.count": [ 22 - { 23 - "declarations": ["input count", "local cp = count: plural"], 24 - "selectors": ["cp"], 25 - "match": { 26 - "cp=one": "{count} like", 27 - "cp=other": "{count} likes" 28 - } 29 - } 30 - ], 31 - "screens.post.quote.count": [ 32 - { 33 - "declarations": ["input count", "local cp = count: plural"], 34 - "selectors": ["cp"], 35 - "match": { 36 - "cp=one": "{count} quote", 37 - "cp=other": "{count} quotes" 38 - } 39 - } 40 - ], 41 - "screens.post.repost.by": "Reposted By", 42 - "screens.post.repost.count": [ 43 - { 44 - "declarations": ["input count", "local cp = count: plural"], 45 - "selectors": ["cp"], 46 - "match": { 47 - "cp=one": "{count} repost", 48 - "cp=other": "{count} reposts" 49 - } 50 - } 51 - ], 52 - "screens.topic.empty": "We couldn't find any results for that topic." 53 - }
+5 -1
messages/en/screens.moderation.json
··· 6 6 "screens.moderation.adultContent.toggleA11y": "Toggle to enable or disable adult content", 7 7 "screens.moderation.advanced": "Advanced", 8 8 "screens.moderation.block.description": "View your blocked accounts", 9 + "screens.moderation.block.hint": "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours.", 9 10 "screens.moderation.block.title": "Blocked accounts", 10 - "screens.moderation.error.generic": "Something went wrong, please try again.", 11 + "screens.moderation.interaction.defaultsHint": "The following settings will be used as your defaults when creating new posts. You can edit these for a specific post from the composer.", 11 12 "screens.moderation.interaction.description": "View your default post interaction settings", 13 + "screens.moderation.interaction.savedToast": "Settings saved", 14 + "screens.moderation.interaction.saveError": "Failed to save settings. Please try again.", 12 15 "screens.moderation.interaction.title": "Interaction settings", 13 16 "screens.moderation.labeler.byCreator": "By {handle}", 14 17 "screens.moderation.labeler.loadError": "We were unable to load your configured labelers at this time.", ··· 18 21 "screens.moderation.labeler.viewA11y": "View the labeling service provided by @{handle}", 19 22 "screens.moderation.moderationList.description": "View your moderation lists", 20 23 "screens.moderation.mute.description": "View your muted accounts", 24 + "screens.moderation.mute.hint": "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private.", 21 25 "screens.moderation.mute.title": "Muted accounts", 22 26 "screens.moderation.mutedWord.changeDuration": "Change duration", 23 27 "screens.moderation.mutedWord.description": "View your muted words",
+34
messages/en/screens.post.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.post.like.count": [ 4 + { 5 + "declarations": ["input count", "local cp = count: plural"], 6 + "selectors": ["cp"], 7 + "match": { 8 + "cp=one": "{count} like", 9 + "cp=other": "{count} likes" 10 + } 11 + } 12 + ], 13 + "screens.post.quote.count": [ 14 + { 15 + "declarations": ["input count", "local cp = count: plural"], 16 + "selectors": ["cp"], 17 + "match": { 18 + "cp=one": "{count} quote", 19 + "cp=other": "{count} quotes" 20 + } 21 + } 22 + ], 23 + "screens.post.repost.count": [ 24 + { 25 + "declarations": ["input count", "local cp = count: plural"], 26 + "selectors": ["cp"], 27 + "match": { 28 + "cp=one": "{count} repost", 29 + "cp=other": "{count} reposts" 30 + } 31 + } 32 + ], 33 + "screens.post.repost.title": "Reposted By" 34 + }
+5
messages/en/screens.postThread.json
··· 26 26 } 27 27 } 28 28 ], 29 + "screens.postThread.engagement.quote.empty": "No quotes yet", 30 + "screens.postThread.engagement.quote.emptyPrompt": "Nobody has quoted this yet. Maybe you should be the first!", 31 + "screens.postThread.engagement.quote.endOfFeed": "That's all, folks!", 29 32 "screens.postThread.engagement.quote.title": "Quotes of this post", 30 33 "screens.postThread.engagement.repost.count": [ 31 34 { ··· 37 40 } 38 41 } 39 42 ], 43 + "screens.postThread.engagement.repost.empty": "No reposts yet", 44 + "screens.postThread.engagement.repost.emptyPrompt": "Nobody has reposted this yet. Maybe you should be the first!", 40 45 "screens.postThread.engagement.repost.title": "Reposts of this post", 41 46 "screens.postThread.engagement.save.count": [ 42 47 {
-3
messages/en/screens.profile.json
··· 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 3 "screens.profile.action.gotIt": "Got it", 4 4 "screens.profile.action.ok": "OK", 5 - "screens.profile.action.undo": "Undo", 6 5 "screens.profile.action.unlike": "Unlike", 7 6 "screens.profile.avatar.a11y.view": "View {handle}'s avatar", 8 7 "screens.profile.avatar.a11y.viewProfile": "View {handle}'s profile", 9 8 "screens.profile.banner.a11y.placeholder": "Profile banner placeholder", 10 9 "screens.profile.banner.a11y.view": "View profile banner", 11 - "screens.profile.block.unblock.title": "Unblock Account?", 12 10 "screens.profile.editProfile.action": "Edit profile", 13 11 "screens.profile.editProfile.bio.hint": "Tell us a bit about yourself", 14 12 "screens.profile.editProfile.bio.tooLong": [ ··· 39 37 "screens.profile.feed.a11y.openInfo": "Open feed info screen", 40 38 "screens.profile.feed.a11y.openOptions": "Open feed options menu", 41 39 "screens.profile.feed.action.like": "Like this feed", 42 - "screens.profile.feed.action.pin": "Pin to Home", 43 40 "screens.profile.feed.action.report": "Report feed", 44 41 "screens.profile.feed.action.save": "Save to my feeds", 45 42 "screens.profile.feed.action.share": "Share this feed",
+1
messages/en/screens.profileList.json
··· 18 18 "screens.profileList.hide.hiddenToast": "List Hidden", 19 19 "screens.profileList.members.add": "Add a user to this list", 20 20 "screens.profileList.members.empty": "This list is empty.", 21 + "screens.profileList.members.fetchError": "There was an issue fetching the list. Tap here to try again.", 21 22 "screens.profileList.members.startAdding": "Start adding people", 22 23 "screens.profileList.members.startAddingCta": "Start adding people!", 23 24 "screens.profileList.mute.action.accounts": "Mute accounts",
-2
messages/en/screens.search.json
··· 1 1 { 2 2 "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "screens.search.account.empty": "No results.", 4 3 "screens.search.account.emptyInterest": "No results for \\\"{interest}\\\".", 5 4 "screens.search.account.loadError": "Failed to load suggested follows", 6 5 "screens.search.account.searchMore": "Search for more accounts", ··· 23 22 "screens.search.results.loading": "Loading search results", 24 23 "screens.search.starterPack.additionalCount": "+{computedTotal}", 25 24 "screens.search.starterPack.open": "Open pack", 26 - "screens.search.trending.browse": "Browse topic {displayName}", 27 25 "screens.search.trending.entertainment": "Entertainment", 28 26 "screens.search.trending.hot": "Hot", 29 27 "screens.search.trending.rank": "{rank}.",
+1
messages/en/screens.settings.json
··· 4 4 "screens.settings.accessibility.requireAltText": "Require alt text before posting", 5 5 "screens.settings.accessibility.title": "Accessibility", 6 6 "screens.settings.account.options": "Account options", 7 + "screens.settings.account.privacyLink": "Account and privacy settings", 7 8 "screens.settings.account.privacyTitle": "Account and privacy", 8 9 "screens.settings.account.quickAccess.remove.message": "This will remove @{handle} from the quick access list.", 9 10 "screens.settings.account.quickAccess.remove.title": "Remove from quick access?",
+4
messages/en/screens.topic.json
··· 1 + { 2 + "$schema": "https://inlang.com/schema/inlang-message-format", 3 + "screens.topic.empty": "We couldn't find any results for that topic." 4 + }
-12
messages/en/view.action.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "view.action.createStarterPack": "Create a Starter Pack", 4 - "view.action.newList": "New list", 5 - "view.action.postPhoto": "Post a photo", 6 - "view.action.postVideo": "Post a video", 7 - "view.action.retryReportOptions": "Retry loading report options", 8 - "view.action.searchFeeds": "Search feeds", 9 - "view.action.switchAccounts": "Switch accounts", 10 - "view.action.switchTo": "Switch to {handle}", 11 - "view.action.writePost": "Write a post" 12 - }
+2 -1
messages/en/view.auth.json
··· 9 9 "view.auth.signIn.a11yHint": "Opens flow to sign in to your existing Bluesky account", 10 10 "view.auth.signIn.accountInactiveError": "This account is not active.", 11 11 "view.auth.signIn.failedError": "Sign in failed. Please try again.", 12 - "view.auth.signIn.inProgress": "Signing in..." 12 + "view.auth.signIn.inProgress": "Signing in...", 13 + "view.auth.signIn.prompt": "Join the conversation" 13 14 }
-10
messages/en/view.empty.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "view.empty.blocked": "You have not blocked any accounts yet. To block an account, go to their profile and select \\\"Block account\\\" from the menu on their account.", 4 - "view.empty.media": "No media yet", 5 - "view.empty.muted": "You have not muted any accounts yet. To mute an account, go to their profile and select \\\"Mute account\\\" from the menu on their account.", 6 - "view.empty.noResults": "No results found for \\\"{query}\\\"", 7 - "view.empty.replies": "No replies yet", 8 - "view.empty.starterPacks": "No Starter Packs yet", 9 - "view.empty.videos": "No video posts yet" 10 - }
+7 -1
messages/en/view.feeds.json
··· 6 6 "view.feeds.composer.a11y": "Opens the post composer", 7 7 "view.feeds.discover.browse": "Browse custom feeds", 8 8 "view.feeds.discover.description": "Choose your own timeline! Feeds built by the community help you find content you love.", 9 + "view.feeds.discover.empty": "No results found for \\\"{query}\\\"", 10 + "view.feeds.discover.title": "Discover New Feeds", 11 + "view.feeds.explore.a11y": "View your feeds and explore more", 9 12 "view.feeds.feed.a11y.creator": "Feed creator", 10 13 "view.feeds.feed.a11y.identifier": "Feed identifier", 11 14 "view.feeds.feed.a11y.label": "{name}, a feed by {creator}, liked by {likeCount}", 15 + "view.feeds.feed.a11y.opens": "Opens {name} feed", 12 16 "view.feeds.feed.error.connect": "Could not connect to custom feed", 13 17 "view.feeds.feed.error.connectService": "Could not connect to feed service", 14 18 "view.feeds.feed.loadingMore": "Loading more feeds", ··· 25 29 "view.feeds.profile.notFound": "Could not find profile", 26 30 "view.feeds.saved.description": "All the feeds you've saved, right in one place.", 27 31 "view.feeds.saved.empty.message": "You haven't made any custom feeds yet.", 28 - "view.feeds.saved.empty.title": "No custom feeds yet" 32 + "view.feeds.saved.empty.title": "No custom feeds yet", 33 + "view.feeds.saved.title": "My Feeds", 34 + "view.feeds.search.placeholder": "Search feeds" 29 35 }
-10
messages/en/view.label.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "view.label.accountPrivacySettings": "Account and privacy settings", 4 - "view.label.menu": "Menu", 5 - "view.label.profile": "profile", 6 - "view.label.saved": "Saved", 7 - "view.label.sourceCode": "Source code", 8 - "view.label.trending": "Trending", 9 - "view.label.user": "user" 10 - }
-28
messages/en/view.misc.json
··· 1 - { 2 - "$schema": "https://inlang.com/schema/inlang-message-format", 3 - "view.block.description": "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours.", 4 - "view.error.generic": "Something went wrong, please try again", 5 - "view.feeds.discover.title": "Discover New Feeds", 6 - "view.feeds.exploreLabel": "View your feeds and explore more", 7 - "view.feeds.opensFeed": "Opens {name} feed", 8 - "view.feeds.saved.title": "My Feeds", 9 - "view.home.returnsHome": "Returns to home page", 10 - "view.list.create": "Create a list", 11 - "view.list.description": "Lists allow you to see content from your favorite people.", 12 - "view.list.empty": "You haven't created any lists yet.", 13 - "view.list.emptyTitle": "No lists", 14 - "view.list.fetchError": "There was an issue fetching the list. Tap here to try again.", 15 - "view.list.moderation.description": "Public, sharable lists of users to mute or block in bulk.", 16 - "view.mute.description": "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private.", 17 - "view.settings.updateLater": "You can update this later from your settings.", 18 - "view.starterPack.description": "Starter Packs let you share your favorite feeds and people with your friends.", 19 - "view.thread.endOfFeed": "That's all, folks!", 20 - "view.thread.joinConversation": "Join the conversation", 21 - "view.thread.quote.empty": "Nobody has quoted this yet. Maybe you should be the first!", 22 - "view.thread.quote.emptyTitle": "No quotes yet", 23 - "view.thread.repost.empty": "Nobody has reposted this yet. Maybe you should be the first!", 24 - "view.thread.repost.emptyTitle": "No reposts yet", 25 - "view.trending.hide.title": "Hide trending topics?", 26 - "view.trending.options": "Trending options", 27 - "view.video.title": "Videos" 28 - }
+1 -10
messages/en/view.notifications.json
··· 3 3 "view.notifications.a11y.collapseUsers": "Collapse list of users", 4 4 "view.notifications.a11y.expandUsers": "Expand list of users", 5 5 "view.notifications.a11y.goToProfile": "Go to {firstAuthorName}'s profile", 6 + "view.notifications.activity.empty": "No posts here", 6 7 "view.notifications.contact.singleLink": "Your contact {#authorLink}{firstAuthorName}{/authorLink} is on Bluesky", 7 8 "view.notifications.contact.singleName": "Your contact {firstAuthorName} is on Bluesky", 8 9 "view.notifications.empty": "No notifications yet!", ··· 305 306 "match": { 306 307 "cp=one": "{notificationCount} unread item", 307 308 "cp=other": "{notificationCount} unread items" 308 - } 309 - } 310 - ], 311 - "view.notifications.unreadCount.label": [ 312 - { 313 - "declarations": ["input count", "local cp = count: plural"], 314 - "selectors": ["cp"], 315 - "match": { 316 - "cp=one": "{count} unread item", 317 - "cp=other": "{count} unread items" 318 309 } 319 310 } 320 311 ],
-1
messages/en/view.profile.json
··· 38 38 "view.profile.list.moderationBy": "Moderation list by {#t0/}", 39 39 "view.profile.list.moderationByYou": "Moderation list by you", 40 40 "view.profile.liveStatus.action.edit": "Edit live status", 41 - "view.profile.liveStatus.action.goLive": "Go live", 42 41 "view.profile.liveStatus.action.goLiveDisabled": "Go live (disabled)", 43 42 "view.profile.sharing.action.copyDid": "Copy DID", 44 43 "view.profile.sharing.action.copyLink": "Copy link to profile",
+14 -6
project.inlang/settings.json
··· 6 6 "plugin.inlang.messageFormat": { 7 7 "pathPattern": [ 8 8 "./messages/{locale}/common.json", 9 + "./messages/{locale}/components.accountList.json", 9 10 "./messages/{locale}/components.activityNotifications.json", 11 + "./messages/{locale}/components.appLanguageDropdown.json", 12 + "./messages/{locale}/components.botAccountAlert.json", 10 13 "./messages/{locale}/components.dialogs.json", 11 14 "./messages/{locale}/components.dms.json", 15 + "./messages/{locale}/components.editableBanner.json", 16 + "./messages/{locale}/components.editableUserAvatar.json", 12 17 "./messages/{locale}/components.emojiPicker.json", 18 + "./messages/{locale}/components.feedInterstitials.json", 13 19 "./messages/{locale}/components.intents.json", 14 20 "./messages/{locale}/components.lightbox.json", 15 - "./messages/{locale}/components.misc.json", 16 21 "./messages/{locale}/components.moderation.json", 17 22 "./messages/{locale}/components.newskieDialog.json", 18 23 "./messages/{locale}/components.post.json", 19 24 "./messages/{locale}/components.postControls.json", 20 25 "./messages/{locale}/components.richTextTag.json", 21 26 "./messages/{locale}/components.starterPack.json", 27 + "./messages/{locale}/components.trendingTopics.json", 22 28 "./messages/{locale}/components.verification.json", 23 29 "./messages/{locale}/components.web.json", 24 30 "./messages/{locale}/components.whoCanReply.json", ··· 26 32 "./messages/{locale}/features.liveNow.json", 27 33 "./messages/{locale}/lib.json", 28 34 "./messages/{locale}/navigation.json", 35 + "./messages/{locale}/screens.bookmarks.json", 36 + "./messages/{locale}/screens.feeds.json", 37 + "./messages/{locale}/screens.hashtag.json", 38 + "./messages/{locale}/screens.home.json", 29 39 "./messages/{locale}/screens.list.json", 40 + "./messages/{locale}/screens.log.json", 30 41 "./messages/{locale}/screens.messages.json", 31 - "./messages/{locale}/screens.misc.json", 32 42 "./messages/{locale}/screens.moderation.json", 43 + "./messages/{locale}/screens.post.json", 33 44 "./messages/{locale}/screens.postThread.json", 34 45 "./messages/{locale}/screens.profile.json", 35 46 "./messages/{locale}/screens.profileList.json", ··· 37 48 "./messages/{locale}/screens.search.json", 38 49 "./messages/{locale}/screens.settings.json", 39 50 "./messages/{locale}/screens.starterPack.json", 51 + "./messages/{locale}/screens.topic.json", 40 52 "./messages/{locale}/state.json", 41 - "./messages/{locale}/view.action.json", 42 53 "./messages/{locale}/view.auth.json", 43 54 "./messages/{locale}/view.composer.json", 44 - "./messages/{locale}/view.empty.json", 45 55 "./messages/{locale}/view.feeds.json", 46 - "./messages/{locale}/view.label.json", 47 - "./messages/{locale}/view.misc.json", 48 56 "./messages/{locale}/view.notifications.json", 49 57 "./messages/{locale}/view.posts.json", 50 58 "./messages/{locale}/view.profile.json"
+2 -2
src/components/ClampedPostText.tsx
··· 32 32 <button 33 33 type="button" 34 34 className={css.showMore} 35 - aria-label={m['components.clampedPostText.action.expand']()} 35 + aria-label={m['components.post.text.expand']()} 36 36 onClick={() => setLimitLines(false)} 37 37 > 38 38 {/* the button hosts the link text directly, so the *Text-returns-<Text> rule doesn't apply */} 39 39 {} 40 - {m['components.clampedPostText.action.showMore']()} 40 + {m['components.post.text.showMore']()} 41 41 </button> 42 42 )} 43 43 </div>
+2 -2
src/components/Dialog/index.tsx
··· 123 123 <RemoveScrollBar /> 124 124 <Pressable 125 125 accessibilityHint={undefined} 126 - accessibilityLabel={m['components.dialog.close']()} 126 + accessibilityLabel={m['common.a11y.closeDialog']()} 127 127 onPress={(e) => void handleBackgroundPress(e)} 128 128 > 129 129 <View ··· 308 308 color="secondary" 309 309 shape="round" 310 310 onPress={() => close()} 311 - label={m['components.dialog.close']()} 311 + label={m['common.a11y.closeDialog']()} 312 312 > 313 313 <ButtonIcon icon={X} size="md" /> 314 314 </Button>
+1 -1
src/components/ExternalEmbed/ExternalGif.tsx
··· 57 57 <button 58 58 type="button" 59 59 className={styles.button} 60 - aria-label={m['components.externalEmbed.a11y.play']({ title: link.title })} 60 + aria-label={m['components.post.external.a11y.play']({ title: link.title })} 61 61 onClick={onPlayPress} 62 62 > 63 63 <img className={styles.image} src={src} alt={link.title} />
+2 -2
src/components/ExternalEmbed/ExternalPlayer.tsx
··· 86 86 <button 87 87 type="button" 88 88 className={styles.overlay} 89 - aria-label={m['components.externalEmbed.a11y.playVideo']()} 89 + aria-label={m['components.post.video.a11y.play']()} 90 90 onClick={onPlayPress} 91 91 > 92 92 {!isActive ? <PlayButtonIcon /> : <Spinner label={m['common.video.loading']()} />} ··· 106 106 onLoad={() => setIsLoading(false)} 107 107 allow="autoplay; encrypted-media; fullscreen; picture-in-picture" 108 108 allowFullScreen 109 - title={link.title || m['components.externalEmbed.a11y.player']()} 109 + title={link.title || m['components.post.external.a11y.player']()} 110 110 /> 111 111 </div> 112 112 ) : null}
+1 -1
src/components/FeedInterstitials.tsx
··· 294 294 {m['components.feedInterstitials.title']()} 295 295 </Text> 296 296 <Button 297 - label={m['components.feedInterstitials.a11y.seeMore']()} 297 + label={m['components.feedInterstitials.seeMoreA11y']()} 298 298 onPress={() => { 299 299 followDialogControl.open(); 300 300 }}
+4 -4
src/components/ImageEmbed/Gallery.tsx
··· 136 136 <div 137 137 ref={scrollRef} 138 138 role="group" 139 - aria-roledescription={m['components.imageEmbed.a11y.carousel']()} 140 - aria-label={m['components.imageEmbed.a11y.gallery']({ count: images.length })} 139 + aria-roledescription={m['components.post.image.a11y.carousel']()} 140 + aria-label={m['components.post.image.a11y.gallery']({ count: images.length })} 141 141 className={styles.scroll} 142 142 style={{ 143 143 marginLeft: -insetLeft, ··· 218 218 // border-width wider than `dims.width`, drifting the snap anchor by that much per image. 219 219 style={{ height: dims.height, width: dims.width }} 220 220 tabIndex={index === 0 ? 0 : -1} 221 - aria-roledescription={m['components.imageEmbed.a11y.slide']()} 221 + aria-roledescription={m['components.post.image.a11y.slide']()} 222 222 aria-label={ 223 - image.alt || m['components.imageEmbed.a11y.imagePosition']({ index: index + 1, imageCount }) 223 + image.alt || m['components.post.image.a11y.imagePosition']({ index: index + 1, imageCount }) 224 224 } 225 225 onPointerDown={onPressIn} 226 226 >
+2 -2
src/components/InterestTabs.tsx
··· 327 327 }) { 328 328 const t = useTheme(); 329 329 const label = active 330 - ? m['components.interestTabs.a11y.categoryActive']({ interestsDisplayName }) 331 - : m['components.interestTabs.a11y.categorySelect']({ interestsDisplayName }); 330 + ? m['components.web.category.a11y.active']({ displayName: interestsDisplayName }) 331 + : m['components.web.category.a11y.select']({ displayName: interestsDisplayName }); 332 332 333 333 return ( 334 334 <View
+1 -1
src/components/KnownFollowers.tsx
··· 278 278 279 279 return ( 280 280 <Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}> 281 - {m['components.knownFollowers.empty']()} 281 + {m['common.follow.knownFollowers.empty']()} 282 282 </Text> 283 283 ); 284 284 }
+2 -2
src/components/ListCard.tsx
··· 142 142 > 143 143 <Hider.Mask> 144 144 <Text className={css.italic} numberOfLines={1} weight="medium"> 145 - {m['components.listCard.hidden']()} 145 + {m['common.list.hidden']()} 146 146 </Text> 147 147 </Hider.Mask> 148 148 <Hider.Content> ··· 154 154 {creator && ( 155 155 <Text color="textContrastMedium" numberOfLines={1} size="md_sub"> 156 156 {purpose === MODLIST 157 - ? m['components.listCard.moderationListBy']({ handle: sanitizeHandle(creator.handle, '@') }) 157 + ? m['common.list.moderationBy']({ handle: sanitizeHandle(creator.handle, '@') }) 158 158 : m['common.list.byCreator']({ handle: sanitizeHandle(creator.handle, '@') })} 159 159 </Text> 160 160 )}
+4 -4
src/components/Lists.tsx
··· 47 47 <ListFooterError error={error} onRetry={onRetry} /> 48 48 ) : !hasNextPage && showEndMessage ? ( 49 49 <Text color="textContrastLow" size="sm"> 50 - {endMessageText ?? m['components.lists.endOfList']()} 50 + {endMessageText ?? m['common.list.endOfList']()} 51 51 </Text> 52 52 ) : null} 53 53 </div> ··· 131 131 return ( 132 132 <Error 133 133 title={errorTitle ?? m['common.error.oops']()} 134 - message={errorMessage ?? m['components.lists.error']()} 134 + message={errorMessage ?? m['common.error.generic']()} 135 135 onRetry={onRetry} 136 136 onGoBack={onGoBack} 137 137 sideBorders={sideBorders} ··· 147 147 icon={emptyStateIcon} 148 148 message={ 149 149 emptyMessage ?? 150 - (emptyType === 'results' ? m['components.lists.noResults']() : m['common.error.pageNotFound']()) 150 + (emptyType === 'results' ? m['common.list.noResults']() : m['common.error.pageNotFound']()) 151 151 } 152 152 button={emptyStateButton} 153 153 /> ··· 160 160 <Error 161 161 title={ 162 162 emptyTitle ?? 163 - (emptyType === 'results' ? m['components.lists.noResults']() : m['common.error.pageNotFound']()) 163 + (emptyType === 'results' ? m['common.list.noResults']() : m['common.error.pageNotFound']()) 164 164 } 165 165 message={emptyMessage ?? m['common.error.notFoundDescription']()} 166 166 onRetry={onRetry}
+1 -1
src/components/PostControls/useBookmark.tsx
··· 22 22 23 23 const isBookmarked = !!post.viewer?.bookmarked; 24 24 25 - const undoLabel = m['components.postControls.save.undo'](); 25 + const undoLabel = m['common.action.undo'](); 26 26 27 27 const save = async ({ disableUndo }: { disableUndo?: boolean } = {}) => { 28 28 try {
+1 -1
src/components/StarterPack/ShareDialog.tsx
··· 68 68 variant="solid" 69 69 > 70 70 <ButtonIcon icon={ChainLinkIcon} /> 71 - <ButtonText>{m['components.starterPack.share.copyLink']()}</ButtonText> 71 + <ButtonText>{m['common.share.action.copyLink']()}</ButtonText> 72 72 </Button> 73 73 </div> 74 74 </div>
+2 -2
src/components/UserAvatar.tsx
··· 246 246 ) : isTouchLive ? ( 247 247 <button 248 248 type="button" 249 - aria-label={m['components.userAvatar.avatar']({ name })} 249 + aria-label={m['common.a11y.avatar']({ name })} 250 250 className={styles.preview} 251 251 style={assignInlineVars({ [styles.previewRadiusVar]: radius })} 252 252 tabIndex={tabIndex} ··· 257 257 ) : ( 258 258 <Link 259 259 className={styles.preview} 260 - label={m['components.userAvatar.avatar']({ name })} 260 + label={m['common.a11y.avatar']({ name })} 261 261 onPress={() => { 262 262 onBeforePress?.(); 263 263 unstableCacheProfileView(queryClient, profile);
+1 -1
src/components/dms/AddMembersFlow.tsx
··· 171 171 _items.push({ 172 172 type: 'empty', 173 173 key: 'empty', 174 - message: m['components.dms.chat.error.network'](), 174 + message: m['components.dialogs.error.network'](), 175 175 }); 176 176 } else if (searchText.length) { 177 177 if (autocompleteResults?.length) {
+2 -2
src/components/dms/AfterReportConversationDialog.tsx
··· 143 143 btnText = m['components.dms.block.orLeave.confirm'](); 144 144 toastMsg = m['components.dms.leave.conversationLeft'](); 145 145 } else if (actions.includes('leave')) { 146 - btnText = m['components.dms.leave.action.afterReport'](); 146 + btnText = m['components.dms.leave.action.conversation'](); 147 147 toastMsg = m['components.dms.leave.conversationLeft'](); 148 148 } else if (actions.includes('block')) { 149 149 // shouldn't be able to reach this, but here for completeness 150 - btnText = m['components.dms.block.action.afterReport'](); 150 + btnText = m['components.dms.block.action.block'](); 151 151 toastMsg = m['components.dms.block.userBlocked'](); 152 152 } 153 153
+1 -1
src/components/dms/AfterReportDialog.tsx
··· 129 129 btnText = m['components.dms.block.orDelete.confirm'](); 130 130 toastMsg = m['components.dms.delete.conversationDeleted'](); 131 131 } else if (actions.includes('leave')) { 132 - btnText = m['components.dms.delete.action.conversation'](); 132 + btnText = m['common.chat.action.deleteConversation'](); 133 133 toastMsg = m['components.dms.delete.conversationDeleted'](); 134 134 } else if (actions.includes('block')) { 135 135 btnText = m['components.dms.block.title']();
+2 -2
src/components/dms/InitiateChatFlow.tsx
··· 260 260 _items.push({ 261 261 type: 'empty', 262 262 key: 'empty', 263 - message: m['components.dms.chat.error.network'](), 263 + message: m['components.dialogs.error.network'](), 264 264 }); 265 265 } else if (chatState === ChatState.GROUP_NAME) { 266 266 _items = groupChatProfiles.map((profile) => ({ ··· 754 754 <ProfileCard.Handle profile={profile} /> 755 755 ) : ( 756 756 <Text style={[a.leading_snug, t.atoms.text_contrast_high]} numberOfLines={2}> 757 - {m['components.dms.recipient.error.cannotMessage']({ handle })} 757 + {m['components.dialogs.chat.cannotMessage']({ handle })} 758 758 </Text> 759 759 )} 760 760 </View>
+1 -1
src/components/forms/SearchInput.tsx
··· 69 69 <Button 70 70 testID="searchTextInputClearBtn" 71 71 onPress={onClearText} 72 - label={m['components.forms.clearSearch']()} 72 + label={m['common.search.action.clear']()} 73 73 hitSlop={HITSLOP_10} 74 74 size="tiny" 75 75 shape="round"
+1 -1
src/components/moderation/BlockDialog.tsx
··· 247 247 onError: (error) => { 248 248 onRestoreConvo(view.id); 249 249 logger.error('Error leaving group chat', { message: error }); 250 - let errorMessage = m['components.moderation.chat.error.leave'](); 250 + let errorMessage = m['components.dms.leave.error.leave'](); 251 251 if (isNetworkError(error)) { 252 252 errorMessage = m['common.error.network'](); 253 253 } else if (error instanceof ClientResponseError && error.error === 'InvalidConvo') {
+1 -1
src/components/moderation/ReportDialog/index.tsx
··· 249 249 close(); 250 250 } catch (e) { 251 251 logger.error(e instanceof Error ? e : String(e), { source: 'ReportDialog' }); 252 - dispatch({ type: 'setError', error: m['components.moderation.error.generic']() }); 252 + dispatch({ type: 'setError', error: m['common.error.generic']() }); 253 253 } finally { 254 254 setIsPending(false); 255 255 }
+4 -4
src/components/suggested-follows-dialog.tsx
··· 313 313 return ( 314 314 <View style={[a.px_lg, a.relative, a.flex_row, a.justify_between, a.align_center]}> 315 315 <Text style={[a.z_10, a.text_lg, a.font_bold, a.leading_tight, t.atoms.text_contrast_high]}> 316 - {m['components.suggestedFollowsDialog.title']()} 316 + {m['components.dialogs.suggestedFollows.title']()} 317 317 </Text> 318 318 { 319 319 <Button ··· 349 349 }): React.ReactNode => { 350 350 const t = useTheme(); 351 351 const label = active 352 - ? m['components.suggestedFollowsDialog.a11y.searchTabActive']({ interestsDisplayName }) 353 - : m['components.suggestedFollowsDialog.a11y.searchTab']({ interestsDisplayName }); 352 + ? m['components.dialogs.suggestedFollows.a11y.searchTabActive']({ interestsDisplayName }) 353 + : m['components.dialogs.suggestedFollows.a11y.searchTab']({ interestsDisplayName }); 354 354 return ( 355 355 <View 356 356 key={interest} ··· 474 474 <SearchIcon size="md" fill={interacted ? colors.primary_500 : colors.contrast_300} /> 475 475 <TextInput 476 476 ref={inputRef} 477 - placeholder={m['components.suggestedFollowsDialog.searchPlaceholder']()} 477 + placeholder={m['components.dialogs.suggestedFollows.searchPlaceholder']()} 478 478 defaultValue={defaultValue} 479 479 onChangeText={onChangeText} 480 480 onFocus={onFocus}
+1 -1
src/lib/moderation/useModerationCauseDescription.ts
··· 114 114 return { 115 115 icon: EyeSlash, 116 116 name: m['common.thread.postHiddenByYou'](), 117 - description: m['lib.moderation.youHidden'](), 117 + description: m['common.thread.youHidPost'](), 118 118 }; 119 119 } 120 120 case ModerationCauseType.Label: {
+1 -1
src/lib/strings/errors.ts
··· 50 50 return m['lib.error.serverIssues'](); 51 51 } 52 52 if (str.includes('Bad token scope') || str.includes('Bad token method')) { 53 - return m['lib.appPassword.featureUnavailableCap'](); 53 + return m['lib.appPassword.featureUnavailable'](); 54 54 } 55 55 if (str.includes('Account has been suspended')) { 56 56 return m['lib.account.error.suspended']();
+2 -2
src/screens/Log.tsx
··· 65 65 a.gap_sm, 66 66 ]} 67 67 onPress={toggler(entry.id)} 68 - accessibilityLabel={m['screens.log.viewEntry']()} 69 - accessibilityHint={m['screens.log.openDetails']()} 68 + accessibilityLabel={m['screens.log.entry.view']()} 69 + accessibilityHint={m['screens.log.entry.openDetails']()} 70 70 > 71 71 {entry.level === LogLevel.Warn || entry.level === LogLevel.Error ? ( 72 72 <WarningIcon size="sm" fill={colors.negative_500} />
+1 -1
src/screens/Messages/Conversation.tsx
··· 97 97 <MessagesListHeader convo={convo} /> 98 98 </Layout.Center> 99 99 <Error 100 - title={m['screens.messages.error.generic']()} 100 + title={m['common.error.generic']()} 101 101 message={m['screens.messages.conversation.loadError']()} 102 102 onRetry={() => convoState.error.retry()} 103 103 sideBorders={false}
+1 -1
src/screens/Messages/ConversationSettings/index.tsx
··· 113 113 if (error) { 114 114 return ( 115 115 <Error 116 - title={m['screens.messages.error.generic']()} 116 + title={m['common.error.generic']()} 117 117 message={m['screens.messages.chatSettings.loadError']()} 118 118 onRetry={() => refetch()} 119 119 sideBorders={false}
+1 -1
src/screens/Messages/JoinRequests.tsx
··· 66 66 <> 67 67 <Header /> 68 68 <Error 69 - title={m['screens.messages.error.generic']()} 69 + title={m['common.error.generic']()} 70 70 message={m['screens.messages.requests.error.load']()} 71 71 onRetry={() => convoState.error.retry()} 72 72 sideBorders={false}
+6 -6
src/screens/Messages/Settings.tsx
··· 46 46 const allowMessagesFromOptions: { name: AllowIncoming; label: string }[] = [ 47 47 { 48 48 name: 'all', 49 - label: m['screens.messages.dmSettings.everyone'](), 49 + label: m['screens.settings.audience.everyone'](), 50 50 }, 51 51 { 52 52 name: 'following', 53 - label: m['screens.messages.dmSettings.following'](), 53 + label: m['screens.settings.audience.peopleIFollow'](), 54 54 }, 55 55 { 56 56 name: 'none', 57 - label: m['screens.messages.dmSettings.noOne'](), 57 + label: m['screens.settings.audience.noOne'](), 58 58 }, 59 59 ]; 60 60 61 61 const allowGroupInvitesFromOptions: { name: AllowIncoming; label: string }[] = [ 62 62 { 63 63 name: 'all', 64 - label: m['screens.messages.inviteSettings.everyone'](), 64 + label: m['screens.settings.audience.everyone'](), 65 65 }, 66 66 { 67 67 name: 'following', 68 - label: m['screens.messages.inviteSettings.following'](), 68 + label: m['screens.settings.audience.peopleIFollow'](), 69 69 }, 70 70 { 71 71 name: 'none', 72 - label: m['screens.messages.inviteSettings.noOne'](), 72 + label: m['screens.settings.audience.noOne'](), 73 73 }, 74 74 ]; 75 75
+1 -3
src/screens/Moderation/index.tsx
··· 76 76 </div> 77 77 ) : error || !preferences ? ( 78 78 <Settings.List> 79 - <Admonition type="error"> 80 - {error?.toString() || m['screens.moderation.error.generic']()} 81 - </Admonition> 79 + <Admonition type="error">{error?.toString() || m['common.error.generic']()}</Admonition> 82 80 </Settings.List> 83 81 ) : ( 84 82 <ModerationScreenInner preferences={preferences} />
+3 -3
src/screens/ModerationInteractionSettings/index.tsx
··· 36 36 </Layout.Header.Outer> 37 37 <Layout.Content> 38 38 <div className={styles.content}> 39 - <Admonition type="tip">{m['screens.moderationInteractionSettings.description']()}</Admonition> 39 + <Admonition type="tip">{m['screens.moderation.interaction.defaultsHint']()}</Admonition> 40 40 {preferences ? ( 41 41 <Inner preferences={preferences} /> 42 42 ) : ( ··· 87 87 postgateEmbeddingRules: maybeEditedPostgate.embeddingRules ?? [], 88 88 threadgateAllowRules: threadgateAllowUISettingToAllowRecordValue(maybeEditedAllowUI), 89 89 }); 90 - Toast.show(m['screens.moderationInteractionSettings.save.success']()); 90 + Toast.show(m['screens.moderation.interaction.savedToast']()); 91 91 } catch (e) { 92 92 logger.error(`Failed to save post interaction settings`, { 93 93 safeMessage: e instanceof Error ? e.message : String(e), 94 94 source: 'ModerationInteractionSettingsScreen', 95 95 }); 96 - setError(m['screens.moderationInteractionSettings.save.error']()); 96 + setError(m['screens.moderation.interaction.saveError']()); 97 97 } 98 98 }, [maybeEditedPostgate, maybeEditedAllowUI, setPostInteractionSettings]); 99 99
+1 -1
src/screens/Notifications/ActivityList.tsx
··· 30 30 feed={`posts|${posts}`} 31 31 disablePoll 32 32 renderEmptyState={() => ( 33 - <EmptyState icon={EditIcon} iconSize="2xl" message={m['screens.notifications.empty']()} /> 33 + <EmptyState icon={EditIcon} iconSize="2xl" message={m['view.notifications.activity.empty']()} /> 34 34 )} 35 35 renderEndOfFeed={() => <ListFooter />} 36 36 />
+1 -1
src/screens/Post/PostRepostedBy.tsx
··· 30 30 <Layout.Header.Content> 31 31 {post && ( 32 32 <> 33 - <Layout.Header.TitleText>{m['screens.post.repost.by']()}</Layout.Header.TitleText> 33 + <Layout.Header.TitleText>{m['screens.post.repost.title']()}</Layout.Header.TitleText> 34 34 <Layout.Header.SubtitleText> 35 35 {m['screens.post.repost.count']({ count: quoteCount ?? 0 })} 36 36 </Layout.Header.SubtitleText>
+1 -1
src/screens/Profile/Header/Actions.tsx
··· 90 90 description={m['common.block.unblockHint']()} 91 91 handle={unblockHandle} 92 92 onConfirm={() => void actions.unblock()} 93 - title={m['screens.profile.block.unblock.title']()} 93 + title={m['components.moderation.block.unblockTitle']()} 94 94 /> 95 95 </> 96 96 );
+1 -1
src/screens/Profile/Sections/Labels.tsx
··· 116 116 if (labelerError || !labelerInfo) { 117 117 return ( 118 118 <View style={[a.w_full, a.align_center, a.py_4xl]}> 119 - <ErrorState error={labelerError?.toString() || m['screens.moderation.error.generic']()} /> 119 + <ErrorState error={labelerError?.toString() || m['common.error.generic']()} /> 120 120 </View> 121 121 ); 122 122 }
+1 -1
src/screens/Profile/components/GermButton.tsx
··· 155 155 void queryClient.refetchQueries({ queryKey: RQKEY(did) }); 156 156 Toast.show(m['screens.profile.germDm.disconnectedToast'](), { 157 157 action: previousRecord 158 - ? { label: m['screens.profile.action.undo'](), onPress: () => void undo() } 158 + ? { label: m['common.action.undo'](), onPress: () => void undo() } 159 159 : undefined, 160 160 }); 161 161 });
+1 -1
src/screens/Profile/components/ProfileFeedHeader.tsx
··· 231 231 </Menu.Root> 232 232 ) : ( 233 233 <Button 234 - label={m['screens.profile.feed.action.pin']()} 234 + label={m['screens.profileList.pin.action.pinToHome']()} 235 235 size="small" 236 236 variant="ghost" 237 237 shape="round"
+1 -1
src/screens/Search/Explore.tsx
··· 675 675 ? m['screens.search.account.emptyInterest']({ 676 676 interest: interestsDisplayNames[selectedInterest] ?? '', 677 677 }) 678 - : m['screens.search.account.empty']()} 678 + : m['common.search.empty']()} 679 679 </Admonition> 680 680 </div> 681 681 );
+1 -1
src/screens/Search/modules/ExploreTrendingTopics.tsx
··· 69 69 return ( 70 70 <Link 71 71 className={css.row} 72 - label={m['screens.search.trending.browse']({ displayName: trend.displayName })} 72 + label={m['components.trendingTopics.a11y.browseTopic']({ displayName: trend.displayName })} 73 73 to={trend.link} 74 74 > 75 75 <div className={css.main}>
+1 -1
src/screens/Settings/AccountSettings.tsx
··· 137 137 case 'mutuals': 138 138 return m['screens.settings.audience.onlyFollowersIFollow'](); 139 139 case 'none': 140 - return m['screens.messages.inviteSettings.noOne'](); 140 + return m['screens.settings.audience.noOne'](); 141 141 case 'followers': 142 142 default: 143 143 return m['screens.settings.audience.anyoneWhoFollowsMe']();
+1 -1
src/screens/Settings/components/ActivitySubscriptionDialog.tsx
··· 74 74 <Toggle.RadioItem label={m['screens.settings.audience.noOne']()} value="none"> 75 75 <Toggle.Panel> 76 76 <Toggle.RadioIndicator /> 77 - <Toggle.PanelText>{m['screens.messages.inviteSettings.noOne']()}</Toggle.PanelText> 77 + <Toggle.PanelText>{m['screens.settings.audience.noOne']()}</Toggle.PanelText> 78 78 </Toggle.Panel> 79 79 </Toggle.RadioItem> 80 80 </Toggle.Group>
+1 -1
src/view/com/home/HomeHeaderLayout.tsx
··· 47 47 <Link 48 48 to="/feeds" 49 49 hitSlop={HITSLOP_10} 50 - label={m['view.feeds.exploreLabel']()} 50 + label={m['view.feeds.explore.a11y']()} 51 51 size="small" 52 52 variant="ghost" 53 53 color="secondary"
+1 -1
src/view/com/home/HomeHeaderLayoutMobile.tsx
··· 51 51 testID="viewHeaderHomeFeedPrefsBtn" 52 52 to={{ screen: 'Feeds' }} 53 53 hitSlop={HITSLOP_10} 54 - label={m['view.feeds.exploreLabel']()} 54 + label={m['view.feeds.explore.a11y']()} 55 55 size="small" 56 56 variant="ghost" 57 57 color="secondary"
+6 -1
src/view/com/lists/ListMembers.tsx
··· 141 141 return <ErrorMessage message={cleanError(error)} onPressTryAgain={onPressTryAgain} />; 142 142 } 143 143 if (item === LOAD_MORE_ERROR_ITEM) { 144 - return <LoadMoreRetryBtn label={m['view.list.fetchError']()} onPress={onPressRetryLoadMore} />; 144 + return ( 145 + <LoadMoreRetryBtn 146 + label={m['screens.profileList.members.fetchError']()} 147 + onPress={onPressRetryLoadMore} 148 + /> 149 + ); 145 150 } 146 151 if (item === LOADING_ITEM) { 147 152 return <ProfileCardFeedLoadingPlaceholder />;
+2 -2
src/view/com/lists/MyLists.tsx
··· 49 49 const emptyText = (() => { 50 50 switch (filter) { 51 51 case 'curate': 52 - return m['view.list.description'](); 52 + return m['common.list.description'](); 53 53 case 'mod': 54 - return m['view.list.moderation.description'](); 54 + return m['common.list.moderation.description'](); 55 55 default: 56 56 return m['common.list.empty'](); 57 57 }
+3 -3
src/view/com/lists/ProfileLists.tsx
··· 106 106 return ( 107 107 <EmptyState 108 108 icon={ListIcon} 109 - message={isSelf ? m['view.list.empty']() : m['view.list.emptyTitle']()} 109 + message={isSelf ? m['common.list.empty']() : m['common.list.emptyUser']()} 110 110 messageColor="textContrastMedium" 111 111 button={ 112 112 isSelf 113 113 ? { 114 - label: m['view.list.create'](), 115 - text: m['view.list.create'](), 114 + label: m['common.list.create'](), 115 + text: m['common.list.create'](), 116 116 onPress: () => navigation.navigate('Lists' as never), 117 117 size: 'small', 118 118 color: 'primary',
+3 -3
src/view/com/post-thread/PostQuotes.tsx
··· 84 84 isLoading={isLoadingUri || isLoadingQuotes} 85 85 isError={isError} 86 86 emptyType="results" 87 - emptyTitle={m['view.thread.quote.emptyTitle']()} 88 - emptyMessage={m['view.thread.quote.empty']()} 87 + emptyTitle={m['screens.postThread.engagement.quote.empty']()} 88 + emptyMessage={m['screens.postThread.engagement.quote.emptyPrompt']()} 89 89 errorMessage={cleanError(resolveError || error)} 90 90 sideBorders={false} 91 91 /> ··· 109 109 error={cleanError(error)} 110 110 onRetry={fetchNextPage} 111 111 showEndMessage 112 - endMessageText={m['view.thread.endOfFeed']()} 112 + endMessageText={m['screens.postThread.engagement.quote.endOfFeed']()} 113 113 /> 114 114 } 115 115 // @ts-ignore our .web version only -prf
+2 -2
src/view/com/post-thread/PostRepostedBy.tsx
··· 74 74 isLoading={isLoadingUri || isLoadingRepostedBy} 75 75 isError={isError} 76 76 emptyType="results" 77 - emptyTitle={m['view.thread.repost.emptyTitle']()} 78 - emptyMessage={m['view.thread.repost.empty']()} 77 + emptyTitle={m['screens.postThread.engagement.repost.empty']()} 78 + emptyMessage={m['screens.postThread.engagement.repost.emptyPrompt']()} 79 79 errorMessage={cleanError(resolveError || error)} 80 80 sideBorders={false} 81 81 />
+2 -2
src/view/com/profile/ProfileMenu.tsx
··· 287 287 ? m['view.profile.liveStatus.action.goLiveDisabled']() 288 288 : status.isActive 289 289 ? m['view.profile.liveStatus.action.edit']() 290 - : m['view.profile.liveStatus.action.goLive']() 290 + : m['features.liveNow.goLive.confirm']() 291 291 } 292 292 onClick={() => { 293 293 if (status.isDisabled) { ··· 302 302 ? m['view.profile.liveStatus.action.goLiveDisabled']() 303 303 : status.isActive 304 304 ? m['view.profile.liveStatus.action.edit']() 305 - : m['view.profile.liveStatus.action.goLive']()} 305 + : m['features.liveNow.goLive.confirm']()} 306 306 </Menu.ItemText> 307 307 <Menu.ItemIcon icon={LiveIcon} /> 308 308 </Menu.Item>
+1 -1
src/view/screens/DebugMod.tsx
··· 796 796 return ( 797 797 <View style={[t.atoms.border_contrast_medium, a.border, a.mb_md]}> 798 798 <ScreenHider 799 - screenDescription={m['view.label.profile']()} 799 + screenDescription={m['components.moderation.screenHider.profile']()} 800 800 modui={getDisplayRestrictions(moderation, DisplayContext.ProfileView)} 801 801 > 802 802 <StandardProfileHeader
+3 -3
src/view/screens/Feeds.tsx
··· 273 273 <FeedsAboutHeader /> 274 274 <div ref={searchAnchorRef} className={css.searchWrapper}> 275 275 <SearchInput 276 - label={m['view.action.searchFeeds']()} 276 + label={m['view.feeds.search.placeholder']()} 277 277 onChangeText={onChangeQuery} 278 278 onClear={onPressCancelSearch} 279 279 onFocus={onFocusSearch} 280 - placeholder={m['view.action.searchFeeds']()} 280 + placeholder={m['view.feeds.search.placeholder']()} 281 281 value={query} 282 282 /> 283 283 </div> ··· 291 291 return ( 292 292 <div className={css.noResults}> 293 293 <Text color="textContrastMedium" size="lg"> 294 - {m['view.empty.noResults']({ query })} 294 + {m['view.feeds.discover.empty']({ query })} 295 295 </Text> 296 296 </div> 297 297 );
+1 -1
src/view/screens/Lists.tsx
··· 44 44 <Layout.Header.TitleText>{m['common.list.label']()}</Layout.Header.TitleText> 45 45 </Layout.Header.Content> 46 46 <Button 47 - label={m['view.action.newList']()} 47 + label={m['common.list.action.new']()} 48 48 color="secondary" 49 49 size="small" 50 50 variant="solid"
+2 -2
src/view/screens/ModerationBlockedAccounts.tsx
··· 134 134 ]} 135 135 > 136 136 <Text style={[a.text_sm, a.text_center, t.atoms.text_contrast_high]}> 137 - {m['view.empty.blocked']()} 137 + {m['common.block.empty']()} 138 138 </Text> 139 139 </View> 140 140 </View> ··· 157 157 ]} 158 158 > 159 159 <Text style={[a.text_center, a.text_sm, t.atoms.text_contrast_high]}> 160 - {m['view.block.description']()} 160 + {m['screens.moderation.block.hint']()} 161 161 </Text> 162 162 </View> 163 163 );
+1 -1
src/view/screens/ModerationModlists.tsx
··· 44 44 <Layout.Header.TitleText>{m['common.moderation.listsTitle']()}</Layout.Header.TitleText> 45 45 </Layout.Header.Content> 46 46 <Button 47 - label={m['view.action.newList']()} 47 + label={m['common.list.action.new']()} 48 48 color="secondary" 49 49 variant="solid" 50 50 size="small"
+2 -2
src/view/screens/ModerationMutedAccounts.tsx
··· 137 137 { maxWidth: 400 }, 138 138 ]} 139 139 > 140 - <Text style={[a.text_sm, a.text_center, t.atoms.text_contrast_high]}>{m['view.empty.muted']()}</Text> 140 + <Text style={[a.text_sm, a.text_center, t.atoms.text_contrast_high]}>{m['common.mute.empty']()}</Text> 141 141 </View> 142 142 </View> 143 143 ); ··· 159 159 ]} 160 160 > 161 161 <Text style={[a.text_center, a.text_sm, t.atoms.text_contrast_high]}> 162 - {m['view.mute.description']()} 162 + {m['screens.moderation.mute.hint']()} 163 163 </Text> 164 164 </View> 165 165 );
+1 -1
src/view/screens/NotFound.tsx
··· 46 46 size="small" 47 47 label={canGoBack ? m['common.action.goBack']() : m['common.action.goHome']()} 48 48 accessibilityLabel={canGoBack ? m['common.action.goBack']() : m['common.action.goHome']()} 49 - accessibilityHint={canGoBack ? m['common.a11y.goBack']() : m['view.home.returnsHome']()} 49 + accessibilityHint={canGoBack ? m['common.a11y.goBack']() : m['common.a11y.goHome']()} 50 50 onPress={onPressHome} 51 51 > 52 52 <ButtonText>{canGoBack ? m['common.action.goBack']() : m['common.action.goHome']()}</ButtonText>
+16 -14
src/view/screens/Profile.tsx
··· 250 250 emptyStateButton={ 251 251 isMe 252 252 ? { 253 - label: m['view.action.writePost'](), 254 - text: m['view.action.writePost'](), 253 + label: m['common.compose.action.writePost'](), 254 + text: m['common.compose.action.writePost'](), 255 255 onPress: () => openComposer({ logContext: 'ProfileFeed' }), 256 256 size: 'small', 257 257 color: 'primary', ··· 269 269 feed={`author|${profile.did}|posts_with_replies`} 270 270 isFocused={isFocused} 271 271 ignoreFilterFor={profile.did} 272 - emptyStateMessage={m['view.empty.replies']()} 272 + emptyStateMessage={m['common.reply.empty']()} 273 273 emptyStateIcon={MessageIcon} 274 274 /> 275 275 ), ··· 282 282 feed={`author|${profile.did}|posts_with_media`} 283 283 isFocused={isFocused} 284 284 ignoreFilterFor={profile.did} 285 - emptyStateMessage={m['view.empty.media']()} 285 + emptyStateMessage={m['common.media.empty']()} 286 286 emptyStateButton={ 287 287 isMe 288 288 ? { 289 - label: m['view.action.postPhoto'](), 290 - text: m['view.action.postPhoto'](), 289 + label: m['common.compose.action.photo'](), 290 + text: m['common.compose.action.photo'](), 291 291 onPress: () => openComposer({ logContext: 'ProfileFeed' }), 292 292 size: 'small', 293 293 color: 'primary', ··· 300 300 }, 301 301 showVideosTab && { 302 302 id: 'videos', 303 - label: m['view.video.title'](), 303 + label: m['common.video.label'](), 304 304 render: (isFocused: boolean) => ( 305 305 <ProfileFeedSection 306 306 feed={`author|${profile.did}|posts_with_video`} 307 307 isFocused={isFocused} 308 308 ignoreFilterFor={profile.did} 309 - emptyStateMessage={m['view.empty.videos']()} 309 + emptyStateMessage={m['common.video.empty']()} 310 310 emptyStateButton={ 311 311 isMe 312 312 ? { 313 - label: m['view.action.postVideo'](), 314 - text: m['view.action.postVideo'](), 313 + label: m['common.compose.action.video'](), 314 + text: m['common.compose.action.video'](), 315 315 onPress: () => openComposer({ logContext: 'ProfileFeed' }), 316 316 size: 'small', 317 317 color: 'primary', ··· 351 351 isMe={isMe} 352 352 enabled={isFocused} 353 353 starterPackCount={starterPackCount} 354 - emptyStateMessage={isMe ? m['view.starterPack.description']() : m['view.empty.starterPacks']()} 354 + emptyStateMessage={ 355 + isMe ? m['components.starterPack.list.empty']() : m['common.starterPack.empty']() 356 + } 355 357 emptyStateButton={ 356 358 isMe 357 359 ? { 358 - label: m['view.action.createStarterPack'](), 359 - text: m['view.action.createStarterPack'](), 360 + label: m['common.starterPack.action.create'](), 361 + text: m['common.starterPack.action.create'](), 360 362 onPress: navToWizard, 361 363 color: 'primary', 362 364 size: 'small', ··· 385 387 return ( 386 388 <ScreenHider 387 389 className={css.container} 388 - screenDescription={m['view.label.user']()} 390 + screenDescription={m['components.moderation.screenHider.user']()} 389 391 modui={getDisplayRestrictions(moderation, DisplayContext.ProfileView)} 390 392 > 391 393 <Tabs
+3 -3
src/view/screens/Storybook/Admonitions.tsx
··· 42 42 <AdmonitionRow> 43 43 <AdmonitionIcon /> 44 44 <AdmonitionContent> 45 - <AdmonitionText>{m['view.error.generic']()}</AdmonitionText> 45 + <AdmonitionText>{m['common.error.generic']()}</AdmonitionText> 46 46 </AdmonitionContent> 47 47 <AdmonitionButton 48 48 color="negative_subtle" 49 - label={m['view.action.retryReportOptions']()} 49 + label={m['components.moderation.report.retry']()} 50 50 onPress={() => {}} 51 51 > 52 52 <ButtonText>{m['common.action.retry']()}</ButtonText> ··· 75 75 markup={{ 76 76 t0: ({ children }) => ( 77 77 <InlineLinkText 78 - label={m['view.label.accountPrivacySettings']()} 78 + label={m['screens.settings.account.privacyLink']()} 79 79 to={{ screen: 'AccountSettings' }} 80 80 style={[a.font_bold]} 81 81 >
+2 -2
src/view/shell/Drawer.tsx
··· 71 71 <BaseDrawer.Popup className={styles.popup}> 72 72 {/* Drawer.Title is itself the heading text host (an <h2>) */} 73 73 {} 74 - <BaseDrawer.Title className={styles.srOnly}>{m['view.label.menu']()}</BaseDrawer.Title> 74 + <BaseDrawer.Title className={styles.srOnly}>{m['navigation.drawer.title']()}</BaseDrawer.Title> 75 75 <BaseDrawer.Content className={styles.content}> 76 76 <DrawerContent /> 77 77 </BaseDrawer.Content> ··· 180 180 activeIcon={BookmarkFilled} 181 181 inactiveIcon={Bookmark} 182 182 isActive={isAtBookmarks} 183 - label={m['view.label.saved']()} 183 + label={m['common.nav.saved']()} 184 184 onPress={() => navigateAndClose('Bookmarks')} 185 185 /> 186 186 <MenuItem
+1 -1
src/view/shell/desktop/Feeds.tsx
··· 110 110 value={feedInfo.feedDescriptor} 111 111 className={css.item} 112 112 aria-label={feedInfo.displayName} 113 - title={m['view.feeds.opensFeed']({ name: feedInfo.displayName })} 113 + title={m['view.feeds.feed.a11y.opens']({ name: feedInfo.displayName })} 114 114 > 115 115 {isFollowing ? ( 116 116 <span className={css.followingIcon}>
+7 -5
src/view/shell/desktop/LeftNav.tsx
··· 104 104 render={ 105 105 <button 106 106 type="button" 107 - aria-label={m['view.action.switchAccounts']()} 107 + aria-label={m['common.account.switcher.label']()} 108 108 className={clsx(css.profileTrigger, minimal && css.profileTriggerMinimal)} 109 109 > 110 110 <div className={css.avatarWrap}> ··· 174 174 }; 175 175 176 176 return ( 177 - <Menu.Popup label={m['view.action.switchAccounts']()} minWidth={150}> 177 + <Menu.Popup label={m['common.account.switcher.label']()} minWidth={150}> 178 178 {accounts && accounts.length > 0 && ( 179 179 <> 180 180 <Menu.Group> ··· 260 260 return ( 261 261 <Menu.Item 262 262 disabled={!!pendingDid} 263 - label={m['view.action.switchTo']({ handle: sanitizeHandle(profile?.handle ?? account.handle, '@') })} 263 + label={m['common.account.action.switchTo']({ 264 + handle: sanitizeHandle(profile?.handle ?? account.handle, '@'), 265 + })} 264 266 onClick={() => void onPressSwitchAccount(account)} 265 267 > 266 268 <UserAvatar ··· 326 328 <Icon aria-hidden={true} width={NAV_ICON_WIDTH} fill={colors.text} /> 327 329 {typeof count === 'string' && count ? ( 328 330 <Text 329 - aria-label={m['view.notifications.unreadCount.label']({ count })} 331 + aria-label={m['view.notifications.unreadCount.a11y']({ count })} 330 332 size="sm" 331 333 weight="semiBold" 332 334 color="white" ··· 491 493 active: BookmarkFilledIcon, 492 494 inactive: BookmarkIcon, 493 495 }} 494 - label={m['view.label.saved']()} 496 + label={m['common.nav.saved']()} 495 497 /> 496 498 <NavItem 497 499 href={currentAccount ? makeProfileLink(currentAccount) : '/'}
+2 -2
src/view/shell/desktop/RightNav.tsx
··· 53 53 href={SOURCE_CODE_URL} 54 54 color="textContrastMedium" 55 55 size="sm" 56 - label={m['view.label.sourceCode']()} 56 + label={m['common.sourceCode']()} 57 57 > 58 - {m['view.label.sourceCode']()} 58 + {m['common.sourceCode']()} 59 59 </ExternalInlineLinkText> 60 60 61 61 {!hasSession && leftNavMinimal && <AppLanguageDropdown />}
+4 -4
src/view/shell/desktop/SidebarTrendingTopics.tsx
··· 44 44 <div className={css.header}> 45 45 <TrendingIcon width={16} height={16} fill={colors.text} /> 46 46 <Text size="md" weight="semiBold" className={css.title}> 47 - {m['view.label.trending']()} 47 + {m['components.trendingTopics.title']()} 48 48 </Text> 49 49 <Button 50 50 variant="ghost" 51 51 size="tiny" 52 52 color="secondary" 53 53 shape="round" 54 - label={m['view.trending.options']()} 54 + label={m['components.trendingTopics.a11y.options']()} 55 55 onClick={() => trendingPrompt.open(null)} 56 56 className={css.optionsButton} 57 57 > ··· 76 76 </div> 77 77 <Prompt.Basic 78 78 handle={trendingPrompt} 79 - title={m['view.trending.hide.title']()} 80 - description={m['view.settings.updateLater']()} 79 + title={m['components.trendingTopics.hide.title']()} 80 + description={m['components.trendingTopics.hide.message']()} 81 81 confirmButtonCta={m['common.action.hide']()} 82 82 onConfirm={onConfirmHide} 83 83 />
+1 -1
src/view/shell/nav-sign-in-card.tsx
··· 27 27 </Link> 28 28 <View style={[a.pt_lg]}> 29 29 <Text style={[a.text_3xl, a.font_bold, { lineHeight: a.text_3xl.fontSize }]}> 30 - {m['view.thread.joinConversation']()} 30 + {m['view.auth.signIn.prompt']()} 31 31 </Text> 32 32 </View> 33 33 <View style={[a.flex_row, a.flex_wrap, a.gap_sm, a.pt_md]}>