diff --git a/.eslintrc.js b/.eslintrc.js index aac5995fa..c12341232 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -69,6 +69,10 @@ module.exports = { eqeqeq: 'error', indent: ['error', 2], 'jsx-quotes': ['error', 'prefer-single'], + 'key-spacing': [ + 'error', + { mode: 'minimum' }, + ], 'no-catch-shadow': 'error', 'no-cond-assign': 'error', 'no-console': [ @@ -111,6 +115,13 @@ module.exports = { 'prefer-const': 'error', quotes: ['error', 'single'], semi: 'error', + 'space-unary-ops': [ + 'error', + { + words: true, + nonwords: false, + }, + ], strict: 'off', 'valid-typeof': 'error', @@ -212,6 +223,23 @@ module.exports = { ], 'import/no-unresolved': 'error', 'import/no-webpack-loader-syntax': 'error', + 'import/order': [ + 'error', + { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + 'type', + ], + 'newlines-between': 'always', + alphabetize: { order: 'asc' }, + }, + ], 'promise/catch-or-return': 'error', diff --git a/.gitignore b/.gitignore index ce9648b2d..29918f5d8 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,12 @@ yarn-error.log* /static-test/ /public/ /dist/ + +.idea +.DS_Store + +# surge.sh +CNAME +AUTH +CORS +ROUTER diff --git a/app/images/avatar-missing.png b/app/images/avatar-missing.png new file mode 100644 index 000000000..b3e6b5709 Binary files /dev/null and b/app/images/avatar-missing.png differ diff --git a/app/images/avatar-missing.svg b/app/images/avatar-missing.svg new file mode 100644 index 000000000..7eb156089 --- /dev/null +++ b/app/images/avatar-missing.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/images/soapbox-logo.svg b/app/images/soapbox-logo.svg new file mode 100644 index 000000000..270b7b810 --- /dev/null +++ b/app/images/soapbox-logo.svg @@ -0,0 +1 @@ + diff --git a/app/index.ejs b/app/index.ejs index 8229b0ef8..735f6e7a0 100644 --- a/app/index.ejs +++ b/app/index.ejs @@ -5,6 +5,7 @@ + diff --git a/app/soapbox/__fixtures__/fedibird-quote-of-quote-post.json b/app/soapbox/__fixtures__/fedibird-quote-of-quote-post.json new file mode 100644 index 000000000..c00c81860 --- /dev/null +++ b/app/soapbox/__fixtures__/fedibird-quote-of-quote-post.json @@ -0,0 +1,109 @@ +{ + "id": "107673570598783346", + "created_at": "2022-01-23T20:05:01.372Z", + "in_reply_to_id": null, + "in_reply_to_account_id": null, + "sensitive": false, + "spoiler_text": "", + "visibility": "public", + "language": "en", + "uri": "https://fedibird.com/users/alex/statuses/107673570598783346", + "url": "https://fedibird.com/@alex/107673570598783346", + "replies_count": 0, + "reblogs_count": 0, + "favourites_count": 0, + "emoji_reactions_count": 0, + "emoji_reactions": [], + "content": "

test quote of a quote
QT: https://fedibird.com/@alex/107673570082615319

", + "quote_id": "107673570082615319", + "reblog": null, + "application": { + "name": "Web", + "website": null + }, + "account": { + "id": "66768", + "username": "alex", + "acct": "alex", + "display_name": "", + "locked": false, + "bot": false, + "discoverable": null, + "group": false, + "created_at": "2020-01-27T00:00:00.000Z", + "note": "

", + "url": "https://fedibird.com/@alex", + "avatar": "https://fedibird.com/avatars/original/missing.png", + "avatar_static": "https://fedibird.com/avatars/original/missing.png", + "header": "https://fedibird.com/headers/original/missing.png", + "header_static": "https://fedibird.com/headers/original/missing.png", + "followers_count": 0, + "following_count": 1, + "subscribing_count": 0, + "statuses_count": 3, + "last_status_at": "2022-01-23", + "emojis": [], + "fields": [] + }, + "media_attachments": [], + "mentions": [], + "tags": [], + "emojis": [], + "card": null, + "poll": null, + "quote": { + "id": "107673570082615319", + "created_at": "2022-01-23T20:04:53.494Z", + "in_reply_to_id": null, + "in_reply_to_account_id": null, + "sensitive": false, + "spoiler_text": "", + "visibility": "public", + "language": "en", + "uri": "https://fedibird.com/users/alex/statuses/107673570082615319", + "url": "https://fedibird.com/@alex/107673570082615319", + "replies_count": 0, + "reblogs_count": 0, + "favourites_count": 0, + "emoji_reactions_count": 0, + "emoji_reactions": [], + "content": "

test quote
QT: https://fedibird.com/@alex/107673569214329435

", + "quote_id": "107673569214329435", + "quote": null, + "reblog": null, + "application": { + "name": "Web", + "website": null + }, + "account": { + "id": "66768", + "username": "alex", + "acct": "alex", + "display_name": "", + "locked": false, + "bot": false, + "discoverable": null, + "group": false, + "created_at": "2020-01-27T00:00:00.000Z", + "note": "

", + "url": "https://fedibird.com/@alex", + "avatar": "https://fedibird.com/avatars/original/missing.png", + "avatar_static": "https://fedibird.com/avatars/original/missing.png", + "header": "https://fedibird.com/headers/original/missing.png", + "header_static": "https://fedibird.com/headers/original/missing.png", + "followers_count": 0, + "following_count": 1, + "subscribing_count": 0, + "statuses_count": 3, + "last_status_at": "2022-01-23", + "emojis": [], + "fields": [] + }, + "media_attachments": [], + "mentions": [], + "tags": [], + "emojis": [], + "card": null, + "poll": null + } +} diff --git a/app/soapbox/__fixtures__/fedibird-quote-post.json b/app/soapbox/__fixtures__/fedibird-quote-post.json new file mode 100644 index 000000000..610ab45c6 --- /dev/null +++ b/app/soapbox/__fixtures__/fedibird-quote-post.json @@ -0,0 +1,108 @@ +{ + "id": "107673570082615319", + "created_at": "2022-01-23T20:04:53.494Z", + "in_reply_to_id": null, + "in_reply_to_account_id": null, + "sensitive": false, + "spoiler_text": "", + "visibility": "public", + "language": "en", + "uri": "https://fedibird.com/users/alex/statuses/107673570082615319", + "url": "https://fedibird.com/@alex/107673570082615319", + "replies_count": 0, + "reblogs_count": 0, + "favourites_count": 0, + "emoji_reactions_count": 0, + "emoji_reactions": [], + "content": "

test quote
QT: https://fedibird.com/@alex/107673569214329435

", + "quote_id": "107673569214329435", + "reblog": null, + "application": { + "name": "Web", + "website": null + }, + "account": { + "id": "66768", + "username": "alex", + "acct": "alex", + "display_name": "", + "locked": false, + "bot": false, + "discoverable": null, + "group": false, + "created_at": "2020-01-27T00:00:00.000Z", + "note": "

", + "url": "https://fedibird.com/@alex", + "avatar": "https://fedibird.com/avatars/original/missing.png", + "avatar_static": "https://fedibird.com/avatars/original/missing.png", + "header": "https://fedibird.com/headers/original/missing.png", + "header_static": "https://fedibird.com/headers/original/missing.png", + "followers_count": 0, + "following_count": 1, + "subscribing_count": 0, + "statuses_count": 3, + "last_status_at": "2022-01-23", + "emojis": [], + "fields": [] + }, + "media_attachments": [], + "mentions": [], + "tags": [], + "emojis": [], + "card": null, + "poll": null, + "quote": { + "id": "107673569214329435", + "created_at": "2022-01-23T20:04:40.249Z", + "in_reply_to_id": null, + "in_reply_to_account_id": null, + "sensitive": false, + "spoiler_text": "", + "visibility": "public", + "language": "en", + "uri": "https://fedibird.com/users/alex/statuses/107673569214329435", + "url": "https://fedibird.com/@alex/107673569214329435", + "replies_count": 0, + "reblogs_count": 0, + "favourites_count": 0, + "emoji_reactions_count": 0, + "emoji_reactions": [], + "content": "

test post

", + "quote": null, + "reblog": null, + "application": { + "name": "Web", + "website": null + }, + "account": { + "id": "66768", + "username": "alex", + "acct": "alex", + "display_name": "", + "locked": false, + "bot": false, + "discoverable": null, + "group": false, + "created_at": "2020-01-27T00:00:00.000Z", + "note": "

", + "url": "https://fedibird.com/@alex", + "avatar": "https://fedibird.com/avatars/original/missing.png", + "avatar_static": "https://fedibird.com/avatars/original/missing.png", + "header": "https://fedibird.com/headers/original/missing.png", + "header_static": "https://fedibird.com/headers/original/missing.png", + "followers_count": 0, + "following_count": 1, + "subscribing_count": 0, + "statuses_count": 3, + "last_status_at": "2022-01-23", + "emojis": [], + "fields": [] + }, + "media_attachments": [], + "mentions": [], + "tags": [], + "emojis": [], + "card": null, + "poll": null + } +} diff --git a/app/soapbox/__fixtures__/intlMessages.json b/app/soapbox/__fixtures__/intlMessages.json index 2423f657c..093f4fc4f 100644 --- a/app/soapbox/__fixtures__/intlMessages.json +++ b/app/soapbox/__fixtures__/intlMessages.json @@ -106,7 +106,7 @@ "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -584,7 +584,7 @@ "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", diff --git a/app/soapbox/__fixtures__/mastodon-3.0.0-instance.json b/app/soapbox/__fixtures__/mastodon-3.0.0-instance.json new file mode 100644 index 000000000..f1d0a5e6d --- /dev/null +++ b/app/soapbox/__fixtures__/mastodon-3.0.0-instance.json @@ -0,0 +1,43 @@ +{ + "uri": "animalliberation.social", + "title": "Animal Liberation Network", + "short_description": "", + "description": "Animal Liberation Network is a community for animal activists on the Fediverse. You can connect with other activists through the local timeline, as well as spread your activism to the outside world with the federated timeline.", + "email": "alex@alexgleason.me", + "version": "3.0.0", + "urls": { + "streaming_api": "wss://animalliberation.social" + }, + "stats": { + "user_count": 662, + "status_count": 2904, + "domain_count": 4003 + }, + "thumbnail": "https://animalliberation.social/packs/media/images/preview-9a17d32fc48369e8ccd910a75260e67d.jpg", + "languages": [ + "en" + ], + "registrations": true, + "approval_required": false, + "contact_account": { + "id": "1", + "username": "alex", + "acct": "alex", + "display_name": "Alex Gleason", + "locked": false, + "bot": false, + "created_at": "2016-11-30T22:19:42.956Z", + "note": "

Animal liberation free software Communist

", + "url": "https://animalliberation.social/@alex", + "avatar": "https://media.animalliberation.social/accounts/avatars/000/000/001/original/media.jpg", + "avatar_static": "https://media.animalliberation.social/accounts/avatars/000/000/001/original/media.jpg", + "header": "https://media.animalliberation.social/accounts/headers/000/000/001/original/09887023017e02c9.jpg", + "header_static": "https://media.animalliberation.social/accounts/headers/000/000/001/original/09887023017e02c9.jpg", + "followers_count": 236, + "following_count": 83, + "statuses_count": 357, + "last_status_at": "2021-02-20T19:28:24.353Z", + "emojis": [], + "fields": [] + } +} diff --git a/app/soapbox/__fixtures__/mastodon-instance.json b/app/soapbox/__fixtures__/mastodon-instance.json new file mode 100644 index 000000000..3c8a2f9d3 --- /dev/null +++ b/app/soapbox/__fixtures__/mastodon-instance.json @@ -0,0 +1,128 @@ +{ + "uri": "mastodon.social", + "title": "Mastodon", + "short_description": "Server run by the main developers of the project \"🐘\" It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!", + "description": "Server run by the main developers of the project \"🐘\" It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!", + "email": "staff@mastodon.social", + "version": "3.4.3", + "urls": { + "streaming_api": "wss://mastodon.social" + }, + "stats": { + "user_count": 619022, + "status_count": 33914684, + "domain_count": 21524 + }, + "thumbnail": "https://files.mastodon.social/site_uploads/files/000/000/001/original/vlcsnap-2018-08-27-16h43m11s127.png", + "languages": [ + "en" + ], + "registrations": true, + "approval_required": false, + "invites_enabled": true, + "configuration": { + "statuses": { + "max_characters": 500, + "max_media_attachments": 4, + "characters_reserved_per_url": 23 + }, + "media_attachments": { + "supported_mime_types": [ + "image/jpeg", + "image/png", + "image/gif", + "video/webm", + "video/mp4", + "video/quicktime", + "video/ogg", + "audio/wave", + "audio/wav", + "audio/x-wav", + "audio/x-pn-wave", + "audio/ogg", + "audio/vorbis", + "audio/mpeg", + "audio/mp3", + "audio/webm", + "audio/flac", + "audio/aac", + "audio/m4a", + "audio/x-m4a", + "audio/mp4", + "audio/3gpp", + "video/x-ms-asf" + ], + "image_size_limit": 10485760, + "image_matrix_limit": 16777216, + "video_size_limit": 41943040, + "video_frame_rate_limit": 60, + "video_matrix_limit": 2304000 + }, + "polls": { + "max_options": 4, + "max_characters_per_option": 50, + "min_expiration": 300, + "max_expiration": 2629746 + } + }, + "contact_account": { + "id": "1", + "username": "Gargron", + "acct": "Gargron", + "display_name": "Eugen 🎄", + "locked": false, + "bot": false, + "discoverable": true, + "group": false, + "created_at": "2016-03-16T00:00:00.000Z", + "note": "

Founder, CEO and lead developer @Mastodon, Germany.

", + "url": "https://mastodon.social/@Gargron", + "avatar": "https://files.mastodon.social/accounts/avatars/000/000/001/original/ccb05a778962e171.png", + "avatar_static": "https://files.mastodon.social/accounts/avatars/000/000/001/original/ccb05a778962e171.png", + "header": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg", + "header_static": "https://files.mastodon.social/accounts/headers/000/000/001/original/3b91c9965d00888b.jpeg", + "followers_count": 98343, + "following_count": 271, + "statuses_count": 71288, + "last_status_at": "2022-01-31", + "emojis": [], + "fields": [ + { + "name": "Patreon", + "value": "https://www.patreon.com/mastodon", + "verified_at": null + }, + { + "name": "Homepage", + "value": "https://zeonfederated.com", + "verified_at": "2019-07-15T18:29:57.191+00:00" + } + ] + }, + "rules": [ + { + "id": "1", + "text": "Sexually explicit or violent media must be marked as sensitive when posting" + }, + { + "id": "2", + "text": "No racism, sexism, homophobia, transphobia, xenophobia, or casteism" + }, + { + "id": "3", + "text": "No incitement of violence or promotion of violent ideologies" + }, + { + "id": "4", + "text": "No harassment, dogpiling or doxxing of other users" + }, + { + "id": "5", + "text": "No content illegal in Germany" + }, + { + "id": "6", + "text": "No spam, advertising or bot accounts" + } + ] +} diff --git a/app/soapbox/__fixtures__/mitra-context.json b/app/soapbox/__fixtures__/mitra-context.json new file mode 100644 index 000000000..91b48420c --- /dev/null +++ b/app/soapbox/__fixtures__/mitra-context.json @@ -0,0 +1,107 @@ +[ + { + "id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "uri": "https://mitra.social/objects/017ed503-bc96-301a-e871-2c23b30ddd05", + "created_at": "2022-02-07T16:28:18.966874Z", + "account": { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex", + "display_name": null, + "created_at": "2022-02-07T16:17:24.769229Z", + "note": null, + "avatar": null, + "header": null, + "fields": [], + "followers_count": 1, + "following_count": 1, + "statuses_count": 3, + "source": null, + "wallet_address": null + }, + "content": "@silverpill sup!", + "in_reply_to_id": null, + "reblog": null, + "visibility": "public", + "replies_count": 1, + "favourites_count": 0, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill" + } + ], + "tags": [], + "favourited": false, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + }, + { + "id": "017ed505-5926-392f-256a-f86d5075df70", + "uri": "https://mitra.social/objects/017ed505-5926-392f-256a-f86d5075df70", + "created_at": "2022-02-07T16:30:04.582771Z", + "account": { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill", + "display_name": "silverpill", + "created_at": "2021-11-06T21:08:57.441927Z", + "note": "Admin of mitra.social instance. It is running experimental ActivityPub server Mitra.", + "avatar": "https://mitra.social/media/6a785bf7dd05f61c3590e8935aa49156a499ac30fd1e402f79e7e164adb36e2c.png", + "header": null, + "fields": [ + { + "name": "Matrix", + "value": "@silverpill:poa.st" + }, + { + "name": "Alt", + "value": "@silverpill@poa.st" + }, + { + "name": "Code", + "value": "https://codeberg.org/silverpill/" + }, + { + "name": "$XMR", + "value": "884y9LmsWY7PQNsyR7bJy1dvj91tuF5spVabyCnPk4KfQtSuzFbQobTFC7xSemJgVW1FWAwnJbjTZX5zZWbBrfkv62DB62d" + } + ], + "followers_count": 27, + "following_count": 15, + "statuses_count": 110, + "source": null, + "wallet_address": null + }, + "content": "@alex welcome", + "in_reply_to_id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "reblog": null, + "visibility": "public", + "replies_count": 0, + "favourites_count": 1, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex" + } + ], + "tags": [], + "favourited": true, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + } +] diff --git a/app/soapbox/__fixtures__/mitra-status-with-attachments.json b/app/soapbox/__fixtures__/mitra-status-with-attachments.json new file mode 100644 index 000000000..689e4d3bb --- /dev/null +++ b/app/soapbox/__fixtures__/mitra-status-with-attachments.json @@ -0,0 +1,95 @@ +{ + "id": "017eeb0e-e5e7-98fe-6b2b-ad02349251fb", + "uri": "https://gleasonator.com/objects/aa5e66c9-0a10-4167-9c80-f40d9574aaec", + "created_at": "2022-02-11T23:11:59.891770Z", + "account": { + "id": "8fe4d6ed-3a99-43e1-a7d4-66b4e635f756", + "username": "alex", + "acct": "alex@gleasonator.com", + "url": "https://gleasonator.com/users/alex", + "display_name": "Alex Gleason", + "created_at": "2021-11-14T17:01:17.446307Z", + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "avatar": "https://mitra.social/media/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "header": "https://mitra.social/media/bdfb009adac0e31257e9fe527d3844a7234cc71f6e06dff2bec94354639555dd.png", + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2, + "following_count": 2, + "statuses_count": 970, + "source": null, + "wallet_address": null + }, + "content": "

Test

", + "in_reply_to_id": null, + "reblog": null, + "visibility": "public", + "replies_count": 0, + "favourites_count": 0, + "reblogs_count": 0, + "media_attachments": [ + { + "id": "017eeb0e-e5df-30a4-77a7-a929145cb836", + "type": "image", + "url": "https://mitra.social/media/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png" + }, + { + "id": "017eeb0e-e5e4-2a48-2889-afdebf368a54", + "type": "unknown", + "url": "https://mitra.social/media/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac" + }, + { + "id": "017eeb0e-e5e5-79fd-6054-8b6869b1db49", + "type": "unknown", + "url": "https://mitra.social/media/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.oga" + }, + { + "id": "017eeb0e-e5e6-c416-a444-21e560c47839", + "type": "unknown", + "url": "https://mitra.social/media/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0" + } + ], + "mentions": [], + "tags": [], + "favourited": false, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null +} diff --git a/app/soapbox/__fixtures__/pleroma-instance.json b/app/soapbox/__fixtures__/pleroma-instance.json new file mode 100644 index 000000000..b91376302 --- /dev/null +++ b/app/soapbox/__fixtures__/pleroma-instance.json @@ -0,0 +1,131 @@ +{ + "approval_required": true, + "avatar_upload_limit": 2000000, + "background_image": "https://gleasonator.com/images/city.jpg", + "background_upload_limit": 4000000, + "banner_upload_limit": 4000000, + "description": "Building the next generation of the Fediverse. Speak freely.", + "description_limit": 5000, + "email": "alex@alexgleason.me", + "languages": [ + "en" + ], + "max_toot_chars": 5000, + "pleroma": { + "metadata": { + "account_activation_required": false, + "birthday_min_age": 0, + "birthday_required": false, + "features": [ + "pleroma_api", + "mastodon_api", + "mastodon_api_streaming", + "polls", + "v2_suggestions", + "pleroma_explicit_addressing", + "shareable_emoji_packs", + "multifetch", + "pleroma:api/v1/notifications:include_types_filter", + "quote_posting", + "media_proxy", + "relay", + "pleroma_emoji_reactions", + "pleroma_chat_messages", + "email_list", + "profile_directory" + ], + "federation": { + "enabled": true, + "exclusions": false, + "mrf_hashtag": { + "federated_timeline_removal": [], + "reject": [], + "sensitive": [ + "nsfw" + ] + }, + "mrf_policies": [ + "TagPolicy", + "SimplePolicy", + "InlineQuotePolicy", + "HashtagPolicy" + ], + "mrf_simple": { + "accept": [], + "avatar_removal": [ + "pawoo.net", + "sinblr.com", + "dajiaweibo.com", + "baraag.net" + ], + "banner_removal": [ + "pawoo.net", + "sinblr.com", + "dajiaweibo.com", + "baraag.net" + ], + "federated_timeline_removal": [], + "followers_only": [], + "media_nsfw": [], + "media_removal": [ + "pawoo.net", + "sinblr.com", + "dajiaweibo.com", + "baraag.net" + ], + "reject": [ + "solagg.com" + ], + "reject_deletes": [], + "report_removal": [] + }, + "mrf_simple_info": {}, + "quarantined_instances": [], + "quarantined_instances_info": { + "quarantined_instances": {} + } + }, + "fields_limits": { + "max_fields": 15, + "max_remote_fields": 20, + "name_length": 512, + "value_length": 2048 + }, + "post_formats": [ + "text/plain", + "text/html", + "text/markdown", + "text/bbcode" + ], + "privileged_staff": true + }, + "stats": { + "mau": 71 + }, + "vapid_public_key": "BLElLQVJVmY_e4F5JoYxI5jXiVOYNsJ9p-amkykc9NcI-jwa9T1Y2GIbDqbY-HqC6ayPkfW4K4o9vgBFKYmkuS4" + }, + "poll_limits": { + "max_expiration": 31536000, + "max_option_chars": 200, + "max_options": 20, + "min_expiration": 0 + }, + "registrations": true, + "shout_limit": 5000, + "soapbox": { + "version": "1.1.1" + }, + "stats": { + "domain_count": 8140, + "status_count": 101956, + "user_count": 421 + }, + "thumbnail": "https://media.gleasonator.com/c0d38bde6ef0b3baa483f574797662ebd83ef9e1a1162e8e4fcd930bb4b3c068.png", + "title": "Gleasonator", + "upload_limit": 100000000, + "uri": "https://gleasonator.com", + "urls": { + "streaming_api": "wss://gleasonator.com" + }, + "version": "2.7.2 (compatible; Pleroma 2.4.51-1129-gf2cfef09-gleasonator)" +} diff --git a/app/soapbox/__fixtures__/pleroma-quote-of-quote-post.json b/app/soapbox/__fixtures__/pleroma-quote-of-quote-post.json new file mode 100644 index 000000000..1156cdb3a --- /dev/null +++ b/app/soapbox/__fixtures__/pleroma-quote-of-quote-post.json @@ -0,0 +1,371 @@ +{ + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2220, + "following_count": 1544, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-01-24T21:02:44", + "locked": false, + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23004, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": { + "name": "Soapbox FE", + "website": "https://soapbox.pub/" + }, + "bookmarked": false, + "card": null, + "content": "

Quote of quote post

", + "created_at": "2022-01-24T21:02:43.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 0, + "id": "AFmFNKmfrR9CxtV01g", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [ + { + "acct": "alex", + "id": "9v5bmRalQvjOy0ECcC", + "url": "https://gleasonator.com/users/alex", + "username": "alex" + } + ], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "Quote of quote post" + }, + "conversation_id": "AFmFNKkXzLRirIVIi8", + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": null, + "quote": { + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2220, + "following_count": 1544, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-01-24T21:02:44", + "locked": false, + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23004, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": { + "name": "Soapbox FE", + "website": "https://soapbox.pub/" + }, + "bookmarked": false, + "card": null, + "content": "

Quote post

", + "created_at": "2022-01-24T21:02:34.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 0, + "id": "AFmFMSpITT9xcOJKcK", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [ + { + "acct": "alex", + "id": "9v5bmRalQvjOy0ECcC", + "url": "https://gleasonator.com/users/alex", + "username": "alex" + } + ], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "Quote post" + }, + "conversation_id": "AFmFMSnWa3k3WtTur2", + "direct_conversation_id": null, + "emoji_reactions": [ + { + "count": 1, + "me": false, + "name": "👍" + } + ], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": null, + "quote": null, + "quote_url": "https://gleasonator.com/objects/4f35159c-3794-4037-9269-a7c84f7137c7", + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/54d93075-7d04-4016-a128-81f3843bca79", + "url": "https://gleasonator.com/notice/AFmFMSpITT9xcOJKcK", + "visibility": "public" + }, + "quote_url": "https://gleasonator.com/objects/54d93075-7d04-4016-a128-81f3843bca79", + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 1, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/1e2cfb5a-ece5-42df-9ec1-13e5de6d9f5b", + "url": "https://gleasonator.com/notice/AFmFNKmfrR9CxtV01g", + "visibility": "public" +} diff --git a/app/soapbox/__fixtures__/pleroma-quote-post.json b/app/soapbox/__fixtures__/pleroma-quote-post.json new file mode 100644 index 000000000..994671ce4 --- /dev/null +++ b/app/soapbox/__fixtures__/pleroma-quote-post.json @@ -0,0 +1,364 @@ +{ + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2220, + "following_count": 1544, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-01-24T21:02:44", + "locked": false, + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23004, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": { + "name": "Soapbox FE", + "website": "https://soapbox.pub/" + }, + "bookmarked": false, + "card": null, + "content": "

Quote post

", + "created_at": "2022-01-24T21:02:34.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 0, + "id": "AFmFMSpITT9xcOJKcK", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [ + { + "acct": "alex", + "id": "9v5bmRalQvjOy0ECcC", + "url": "https://gleasonator.com/users/alex", + "username": "alex" + } + ], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "Quote post" + }, + "conversation_id": "AFmFMSnWa3k3WtTur2", + "direct_conversation_id": null, + "emoji_reactions": [ + { + "count": 1, + "me": false, + "name": "👍" + } + ], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": null, + "quote": { + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2220, + "following_count": 1544, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-01-24T21:02:44", + "locked": false, + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23004, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": { + "name": "Soapbox FE", + "website": "https://soapbox.pub/" + }, + "bookmarked": false, + "card": null, + "content": "

Test post

", + "created_at": "2022-01-24T21:02:25.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 0, + "id": "AFmFLcd6XYVdjWCrOS", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "Test post" + }, + "conversation_id": "AFmFLcaGi6EzaisayO", + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": null, + "quote": null, + "quote_url": null, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/4f35159c-3794-4037-9269-a7c84f7137c7", + "url": "https://gleasonator.com/notice/AFmFLcd6XYVdjWCrOS", + "visibility": "public" + }, + "quote_url": "https://gleasonator.com/objects/4f35159c-3794-4037-9269-a7c84f7137c7", + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/54d93075-7d04-4016-a128-81f3843bca79", + "url": "https://gleasonator.com/notice/AFmFMSpITT9xcOJKcK", + "visibility": "public" +} diff --git a/app/soapbox/__fixtures__/pleroma-status-with-attachments.json b/app/soapbox/__fixtures__/pleroma-status-with-attachments.json new file mode 100644 index 000000000..75db8292f --- /dev/null +++ b/app/soapbox/__fixtures__/pleroma-status-with-attachments.json @@ -0,0 +1,238 @@ +{ + "account": { + "acct": "alex", + "avatar": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "avatar_static": "https://media.gleasonator.com/6d64aecb17348b23aaff78db4687b9476cb0da1c07cc6a819c2e6ec7144c18b1.png", + "bot": false, + "created_at": "2020-01-08T01:25:43.000Z", + "display_name": "Alex Gleason", + "emojis": [], + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "followers_count": 2344, + "following_count": 1564, + "fqn": "alex@gleasonator.com", + "header": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "header_static": "https://media.gleasonator.com/accounts/headers/000/000/001/original/9d0e4dbf1c9dbc8f.png", + "id": "9v5bmRalQvjOy0ECcC", + "last_status_at": "2022-02-11T23:12:00", + "locked": false, + "note": "I create Fediverse software that empowers people online.

I'm vegan btw

Note: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://gleasonator.com/users/alex", + "background_image": null, + "birthday": "1993-07-03", + "favicon": "https://gleasonator.com/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": true, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": true, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [ + { + "name": "Website", + "value": "https://alexgleason.me" + }, + { + "name": "Pleroma+Soapbox", + "value": "https://soapbox.pub" + }, + { + "name": "Email", + "value": "alex@alexgleason.me" + }, + { + "name": "Gender identity", + "value": "Soyboy" + }, + { + "name": "Donate (PayPal)", + "value": "https://paypal.me/gleasonator" + }, + { + "name": "$BTC", + "value": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n" + }, + { + "name": "$ETH", + "value": "0xAc9aB5Fc04Dc1cB1789Af75b523Bd23C70B2D717" + }, + { + "name": "$DOGE", + "value": "D5zVZs6jrRakaPVGiErkQiHt9sayzm6V5D" + }, + { + "name": "$XMR", + "value": "45JDCLrjJ4bgVUSbbs2yjy9m5Mf4VLPW8fG7jw9sq5u69rXZZopQogZNeyYkMBnXpkaip4p4QwaaJNhdTotPa9g44DBCzdK" + } + ], + "note": "I create Fediverse software that empowers people online.\r\n\r\nI'm vegan btw\r\n\r\nNote: If you have a question for me, please tag me publicly. This gives the opportunity for others to chime in, and bystanders to learn.", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 23357, + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + "application": { + "name": "Soapbox FE", + "website": "https://soapbox.pub/" + }, + "bookmarked": false, + "card": null, + "content": "

Test

", + "created_at": "2022-02-11T23:11:59.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 1, + "id": "AGNkA21auFR5lnEAHw", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [ + { + "blurhash": "emLqe9t7~q%M%M-;WBt7ofRj%Moft7ofoft7ayWBj[of-;j[ayofM{", + "description": "", + "id": "974611173", + "meta": { + "original": { + "aspect": 0.9944598337950139, + "height": 1444, + "width": 1436 + } + }, + "pleroma": { + "mime_type": "image/png" + }, + "preview_url": "https://media.gleasonator.com/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png", + "remote_url": "https://media.gleasonator.com/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png", + "text_url": "https://media.gleasonator.com/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png", + "type": "image", + "url": "https://media.gleasonator.com/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png" + }, + { + "blurhash": null, + "description": "", + "id": "-1764036199", + "pleroma": { + "mime_type": "application/x-nes-rom" + }, + "preview_url": "https://media.gleasonator.com/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac.nes", + "remote_url": "https://media.gleasonator.com/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac.nes", + "text_url": "https://media.gleasonator.com/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac.nes", + "type": "unknown", + "url": "https://media.gleasonator.com/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac.nes" + }, + { + "blurhash": null, + "description": "", + "id": "-636167741", + "pleroma": { + "mime_type": "audio/ogg" + }, + "preview_url": "https://media.gleasonator.com/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.ogg", + "remote_url": "https://media.gleasonator.com/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.ogg", + "text_url": "https://media.gleasonator.com/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.ogg", + "type": "audio", + "url": "https://media.gleasonator.com/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.ogg" + }, + { + "blurhash": null, + "description": "", + "id": "517941208", + "pleroma": { + "mime_type": "text/plain" + }, + "preview_url": "https://media.gleasonator.com/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0.LICENSE", + "remote_url": "https://media.gleasonator.com/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0.LICENSE", + "text_url": "https://media.gleasonator.com/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0.LICENSE", + "type": "unknown", + "url": "https://media.gleasonator.com/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0.LICENSE" + } + ], + "mentions": [], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "Test" + }, + "conversation_id": "AGNkA1yP66srbtjcJc", + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "pinned_at": null, + "quote": null, + "quote_url": null, + "quote_visible": false, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://gleasonator.com/objects/aa5e66c9-0a10-4167-9c80-f40d9574aaec", + "url": "https://gleasonator.com/notice/AGNkA21auFR5lnEAHw", + "visibility": "public" +} diff --git a/app/soapbox/__fixtures__/status-unordered-mentions.json b/app/soapbox/__fixtures__/status-unordered-mentions.json new file mode 100644 index 000000000..40bdbe8b6 --- /dev/null +++ b/app/soapbox/__fixtures__/status-unordered-mentions.json @@ -0,0 +1,122 @@ +{ + "account": { + "acct": "apropos@freespeechextremist.com", + "avatar": "https://gleasonator.com/proxy/WVdkCbG7AOZ_eqMzskzXQoyjq8o/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8zN2I4MDMzZC03OGQ1LTQ0YmMtYmY5NC0xYTI2NzY5NTQwM2YvYmxvYi5wbmc_bmFtZT1ibG9iLnBuZw/blob.png", + "avatar_static": "https://gleasonator.com/proxy/WVdkCbG7AOZ_eqMzskzXQoyjq8o/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8zN2I4MDMzZC03OGQ1LTQ0YmMtYmY5NC0xYTI2NzY5NTQwM2YvYmxvYi5wbmc_bmFtZT1ibG9iLnBuZw/blob.png", + "bot": false, + "created_at": "2020-05-21T07:20:46.000Z", + "display_name": "of nothing", + "emojis": [], + "fields": [], + "followers_count": 87, + "following_count": 85, + "fqn": "apropos@freespeechextremist.com", + "header": "https://gleasonator.com/proxy/pIracLGWm_skCfOOgdwcCNqES5s/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8yZDEwYmRjZC01NDUwLTRjZjYtYWFhZS1hNTJjMzYwYjk2YjYvdHJhY2tzb25tYXJzLmpwZz9uYW1lPXRyYWNrc29ubWFycy5qcGc/tracksonmars.jpg", + "header_static": "https://gleasonator.com/proxy/pIracLGWm_skCfOOgdwcCNqES5s/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8yZDEwYmRjZC01NDUwLTRjZjYtYWFhZS1hNTJjMzYwYjk2YjYvdHJhY2tzb25tYXJzLmpwZz9uYW1lPXRyYWNrc29ubWFycy5qcGc/tracksonmars.jpg", + "id": "9vGR3IWmWVYRkKUZ4i", + "last_status_at": "2022-01-07T21:47:39", + "locked": false, + "note": "If you wait by the river long enough, the bodies of your enemies will float by.

Deo Vindice", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://freespeechextremist.com/users/apropos", + "background_image": null, + "favicon": "https://gleasonator.com/proxy/EN7BSaEEYTRpmRj4lITIjgWp2sg/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9mYXZpY29uLnBuZw/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 7087, + "url": "https://freespeechextremist.com/users/apropos", + "username": "apropos" + }, + "application": null, + "bookmarked": false, + "card": null, + "content": "@NEETzsche @alex @Lumeinshin @sneeden
>seething
'posting', just like you.", + "created_at": "2022-01-07T17:29:58.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 1, + "id": "AFChectaqZjmOVkXZ2", + "in_reply_to_account_id": "9v5bw7hEGBPc9nrpzc", + "in_reply_to_id": "AFChbnWqrAZ2VIlPJw", + "language": null, + "media_attachments": [], + "mentions": [ + { + "acct": "alex", + "id": "9v5bmRalQvjOy0ECcC", + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + { + "acct": "NEETzsche@iddqd.social", + "id": "9v5bw7hEGBPc9nrpzc", + "url": "https://iddqd.social/users/NEETzsche", + "username": "NEETzsche" + }, + { + "acct": "Lumeinshin@pleroma.skyshanty.xyz", + "id": "A3dFSwTkwgRfd998iG", + "url": "https://pleroma.skyshanty.xyz/users/Lumeinshin", + "username": "Lumeinshin" + }, + { + "acct": "sneeden@social.silkky.cloud", + "id": "ACrsPAbAOPh3GbKZhQ", + "url": "https://social.silkky.cloud/users/sneeden", + "username": "sneeden" + } + ], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "@NEETzsche @alex @Lumeinshin @sneeden >seething'posting', just like you." + }, + "conversation_id": "AFCYCBFN9SgOwoIWTg", + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": "NEETzsche@iddqd.social", + "local": false, + "parent_visible": true, + "pinned_at": null, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://freespeechextremist.com/objects/714b0e04-bec4-4a2a-9514-312814380064", + "url": "https://freespeechextremist.com/objects/714b0e04-bec4-4a2a-9514-312814380064", + "visibility": "public" +} diff --git a/app/soapbox/actions/__tests__/about-test.js b/app/soapbox/actions/__tests__/about-test.js index f6ce02099..49840e357 100644 --- a/app/soapbox/actions/__tests__/about-test.js +++ b/app/soapbox/actions/__tests__/about-test.js @@ -1,13 +1,15 @@ +import MockAdapter from 'axios-mock-adapter'; +import { Map as ImmutableMap } from 'immutable'; + +import { staticClient } from 'soapbox/api'; +import { mockStore } from 'soapbox/test_helpers'; + import { FETCH_ABOUT_PAGE_REQUEST, FETCH_ABOUT_PAGE_SUCCESS, FETCH_ABOUT_PAGE_FAIL, fetchAboutPage, } from '../about'; -import { Map as ImmutableMap } from 'immutable'; -import MockAdapter from 'axios-mock-adapter'; -import { staticClient } from 'soapbox/api'; -import { mockStore } from 'soapbox/test_helpers'; describe('fetchAboutPage()', () => { it('creates the expected actions on success', () => { diff --git a/app/soapbox/actions/__tests__/preload-test.js b/app/soapbox/actions/__tests__/preload-test.js index bf0dc83a5..5290802d2 100644 --- a/app/soapbox/actions/__tests__/preload-test.js +++ b/app/soapbox/actions/__tests__/preload-test.js @@ -1,12 +1,14 @@ +import { Map as ImmutableMap } from 'immutable'; + +import { __stub } from 'soapbox/api'; +import { mockStore } from 'soapbox/test_helpers'; + +import { VERIFY_CREDENTIALS_REQUEST } from '../auth'; +import { ACCOUNTS_IMPORT } from '../importer'; import { MASTODON_PRELOAD_IMPORT, preloadMastodon, } from '../preload'; -import { VERIFY_CREDENTIALS_REQUEST } from '../auth'; -import { ACCOUNTS_IMPORT } from '../importer'; -import { Map as ImmutableMap } from 'immutable'; -import { __stub } from 'soapbox/api'; -import { mockStore } from 'soapbox/test_helpers'; describe('preloadMastodon()', () => { it('creates the expected actions', () => { diff --git a/app/soapbox/actions/__tests__/statuses-test.js b/app/soapbox/actions/__tests__/statuses-test.js new file mode 100644 index 000000000..71a0596a4 --- /dev/null +++ b/app/soapbox/actions/__tests__/statuses-test.js @@ -0,0 +1,29 @@ +import { Map as ImmutableMap } from 'immutable'; + +import { STATUSES_IMPORT } from 'soapbox/actions/importer'; +import { __stub } from 'soapbox/api'; +import { mockStore } from 'soapbox/test_helpers'; + +import { fetchContext } from '../statuses'; + +describe('fetchContext()', () => { + it('handles Mitra context', done => { + const statuses = require('soapbox/__fixtures__/mitra-context.json'); + + __stub(mock => { + mock.onGet('/api/v1/statuses/017ed505-5926-392f-256a-f86d5075df70/context') + .reply(200, statuses); + }); + + const store = mockStore(ImmutableMap()); + + store.dispatch(fetchContext('017ed505-5926-392f-256a-f86d5075df70')).then(context => { + const actions = store.getActions(); + + expect(actions[3].type).toEqual(STATUSES_IMPORT); + expect(actions[3].statuses[0].id).toEqual('017ed503-bc96-301a-e871-2c23b30ddd05'); + + done(); + }).catch(console.error); + }); +}); diff --git a/app/soapbox/actions/accounts.js b/app/soapbox/actions/accounts.js index 4530ec705..23aad5601 100644 --- a/app/soapbox/actions/accounts.js +++ b/app/soapbox/actions/accounts.js @@ -1,11 +1,13 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; + import api, { getLinks } from '../api'; + import { importFetchedAccount, importFetchedAccounts, importErrorWhileFetchingAccountByUsername, } from './importer'; -import { isLoggedIn } from 'soapbox/utils/auth'; -import { getFeatures } from 'soapbox/utils/features'; export const ACCOUNT_CREATE_REQUEST = 'ACCOUNT_CREATE_REQUEST'; export const ACCOUNT_CREATE_SUCCESS = 'ACCOUNT_CREATE_SUCCESS'; @@ -55,10 +57,18 @@ export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST'; export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS'; export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL'; +export const PINNED_ACCOUNTS_FETCH_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST'; +export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS'; +export const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL'; + export const ACCOUNT_SEARCH_REQUEST = 'ACCOUNT_SEARCH_REQUEST'; export const ACCOUNT_SEARCH_SUCCESS = 'ACCOUNT_SEARCH_SUCCESS'; export const ACCOUNT_SEARCH_FAIL = 'ACCOUNT_SEARCH_FAIL'; +export const ACCOUNT_LOOKUP_REQUEST = 'ACCOUNT_LOOKUP_REQUEST'; +export const ACCOUNT_LOOKUP_SUCCESS = 'ACCOUNT_LOOKUP_SUCCESS'; +export const ACCOUNT_LOOKUP_FAIL = 'ACCOUNT_LOOKUP_FAIL'; + export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST'; export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS'; export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL'; @@ -99,6 +109,10 @@ export const NOTIFICATION_SETTINGS_REQUEST = 'NOTIFICATION_SETTINGS_REQUEST'; export const NOTIFICATION_SETTINGS_SUCCESS = 'NOTIFICATION_SETTINGS_SUCCESS'; export const NOTIFICATION_SETTINGS_FAIL = 'NOTIFICATION_SETTINGS_FAIL'; +export const BIRTHDAY_REMINDERS_FETCH_REQUEST = 'BIRTHDAY_REMINDERS_FETCH_REQUEST'; +export const BIRTHDAY_REMINDERS_FETCH_SUCCESS = 'BIRTHDAY_REMINDERS_FETCH_SUCCESS'; +export const BIRTHDAY_REMINDERS_FETCH_FAIL = 'BIRTHDAY_REMINDERS_FETCH_FAIL'; + export function createAccount(params) { return (dispatch, getState) => { dispatch({ type: ACCOUNT_CREATE_REQUEST, params }); @@ -144,8 +158,9 @@ export function fetchAccountByUsername(username) { const instance = state.get('instance'); const features = getFeatures(instance); + const me = state.get('me'); - if (features.accountByUsername) { + if (features.accountByUsername && (me || !features.accountLookup)) { api(getState).get(`/api/v1/accounts/${username}`).then(response => { dispatch(fetchRelationships([response.data.id])); dispatch(importFetchedAccount(response.data)); @@ -154,6 +169,13 @@ export function fetchAccountByUsername(username) { dispatch(fetchAccountFail(null, error)); dispatch(importErrorWhileFetchingAccountByUsername(username)); }); + } else if (features.accountLookup) { + dispatch(accountLookup(username)).then(account => { + dispatch(fetchAccountSuccess(account)); + }).catch(error => { + dispatch(fetchAccountFail(null, error)); + dispatch(importErrorWhileFetchingAccountByUsername(username)); + }); } else { dispatch(accountSearch({ q: username, @@ -199,7 +221,7 @@ export function fetchAccountFail(id, error) { }; } -export function followAccount(id, reblogs = true) { +export function followAccount(id, options = { reblogs: true }) { return (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -208,7 +230,7 @@ export function followAccount(id, reblogs = true) { dispatch(followAccountRequest(id, locked)); - api(getState).post(`/api/v1/accounts/${id}/follow`, { reblogs }).then(response => { + api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => { dispatch(followAccountSuccess(response.data, alreadyFollowing)); }).catch(error => { dispatch(followAccountFail(error, locked)); @@ -948,6 +970,43 @@ export function unpinAccountFail(error) { }; } +export function fetchPinnedAccounts(id) { + return (dispatch, getState) => { + dispatch(fetchPinnedAccountsRequest(id)); + + api(getState).get(`/api/v1/pleroma/accounts/${id}/endorsements`).then(response => { + dispatch(importFetchedAccounts(response.data)); + dispatch(fetchPinnedAccountsSuccess(id, response.data, null)); + }).catch(error => { + dispatch(fetchPinnedAccountsFail(id, error)); + }); + }; +} + +export function fetchPinnedAccountsRequest(id) { + return { + type: PINNED_ACCOUNTS_FETCH_REQUEST, + id, + }; +} + +export function fetchPinnedAccountsSuccess(id, accounts, next) { + return { + type: PINNED_ACCOUNTS_FETCH_SUCCESS, + id, + accounts, + next, + }; +} + +export function fetchPinnedAccountsFail(id, error) { + return { + type: PINNED_ACCOUNTS_FETCH_FAIL, + id, + error, + }; +} + export function accountSearch(params, cancelToken) { return (dispatch, getState) => { dispatch({ type: ACCOUNT_SEARCH_REQUEST, params }); @@ -961,3 +1020,40 @@ export function accountSearch(params, cancelToken) { }); }; } + +export function accountLookup(acct, cancelToken) { + return (dispatch, getState) => { + dispatch({ type: ACCOUNT_LOOKUP_REQUEST, acct }); + return api(getState).get('/api/v1/accounts/lookup', { params: { acct }, cancelToken }).then(({ data: account }) => { + if (account && account.id) dispatch(importFetchedAccount(account)); + dispatch({ type: ACCOUNT_LOOKUP_SUCCESS, account }); + return account; + }).catch(error => { + dispatch({ type: ACCOUNT_LOOKUP_FAIL }); + throw error; + }); + }; +} + +export function fetchBirthdayReminders(day, month) { + return (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + + const me = getState().get('me'); + + dispatch({ type: BIRTHDAY_REMINDERS_FETCH_REQUEST, day, month, id: me }); + + api(getState).get('/api/v1/pleroma/birthdays', { params: { day, month } }).then(response => { + dispatch(importFetchedAccounts(response.data)); + dispatch({ + type: BIRTHDAY_REMINDERS_FETCH_SUCCESS, + accounts: response.data, + day, + month, + id: me, + }); + }).catch(error => { + dispatch({ type: BIRTHDAY_REMINDERS_FETCH_FAIL, day, month, id: me }); + }); + }; +} diff --git a/app/soapbox/actions/admin.js b/app/soapbox/actions/admin.js index a48636d0e..414cb07d6 100644 --- a/app/soapbox/actions/admin.js +++ b/app/soapbox/actions/admin.js @@ -1,6 +1,7 @@ -import api from '../api'; -import { importFetchedAccount, importFetchedStatuses } from 'soapbox/actions/importer'; import { fetchRelationships } from 'soapbox/actions/accounts'; +import { importFetchedAccount, importFetchedStatuses } from 'soapbox/actions/importer'; + +import api from '../api'; export const ADMIN_CONFIG_FETCH_REQUEST = 'ADMIN_CONFIG_FETCH_REQUEST'; export const ADMIN_CONFIG_FETCH_SUCCESS = 'ADMIN_CONFIG_FETCH_SUCCESS'; @@ -62,6 +63,14 @@ export const ADMIN_REMOVE_PERMISSION_GROUP_REQUEST = 'ADMIN_REMOVE_PERMISSION_GR export const ADMIN_REMOVE_PERMISSION_GROUP_SUCCESS = 'ADMIN_REMOVE_PERMISSION_GROUP_SUCCESS'; export const ADMIN_REMOVE_PERMISSION_GROUP_FAIL = 'ADMIN_REMOVE_PERMISSION_GROUP_FAIL'; +export const ADMIN_USERS_SUGGEST_REQUEST = 'ADMIN_USERS_SUGGEST_REQUEST'; +export const ADMIN_USERS_SUGGEST_SUCCESS = 'ADMIN_USERS_SUGGEST_SUCCESS'; +export const ADMIN_USERS_SUGGEST_FAIL = 'ADMIN_USERS_SUGGEST_FAIL'; + +export const ADMIN_USERS_UNSUGGEST_REQUEST = 'ADMIN_USERS_UNSUGGEST_REQUEST'; +export const ADMIN_USERS_UNSUGGEST_SUCCESS = 'ADMIN_USERS_UNSUGGEST_SUCCESS'; +export const ADMIN_USERS_UNSUGGEST_FAIL = 'ADMIN_USERS_UNSUGGEST_FAIL'; + const nicknamesFromIds = (getState, ids) => ids.map(id => getState().getIn(['accounts', id, 'acct'])); export function fetchConfig() { @@ -319,3 +328,31 @@ export function demoteToUser(accountId) { ]); }; } + +export function suggestUsers(accountIds) { + return (dispatch, getState) => { + const nicknames = nicknamesFromIds(getState, accountIds); + dispatch({ type: ADMIN_USERS_SUGGEST_REQUEST, accountIds }); + return api(getState) + .patch('/api/pleroma/admin/users/suggest', { nicknames }) + .then(({ data: { users } }) => { + dispatch({ type: ADMIN_USERS_SUGGEST_SUCCESS, users, accountIds }); + }).catch(error => { + dispatch({ type: ADMIN_USERS_SUGGEST_FAIL, error, accountIds }); + }); + }; +} + +export function unsuggestUsers(accountIds) { + return (dispatch, getState) => { + const nicknames = nicknamesFromIds(getState, accountIds); + dispatch({ type: ADMIN_USERS_UNSUGGEST_REQUEST, accountIds }); + return api(getState) + .patch('/api/pleroma/admin/users/unsuggest', { nicknames }) + .then(({ data: { users } }) => { + dispatch({ type: ADMIN_USERS_UNSUGGEST_SUCCESS, users, accountIds }); + }).catch(error => { + dispatch({ type: ADMIN_USERS_UNSUGGEST_FAIL, error, accountIds }); + }); + }; +} diff --git a/app/soapbox/actions/aliases.js b/app/soapbox/actions/aliases.js index 7f2dc6b00..e28817681 100644 --- a/app/soapbox/actions/aliases.js +++ b/app/soapbox/actions/aliases.js @@ -1,10 +1,18 @@ import { defineMessages } from 'react-intl'; -import api from '../api'; -import { importFetchedAccount, importFetchedAccounts } from './importer'; -import { showAlertForError } from './alerts'; -import snackbar from './snackbar'; + import { isLoggedIn } from 'soapbox/utils/auth'; -import { ME_PATCH_SUCCESS } from './me'; +import { getFeatures } from 'soapbox/utils/features'; + +import api from '../api'; + +import { showAlertForError } from './alerts'; +import { importFetchedAccounts } from './importer'; +import { patchMeSuccess } from './me'; +import snackbar from './snackbar'; + +export const ALIASES_FETCH_REQUEST = 'ALIASES_FETCH_REQUEST'; +export const ALIASES_FETCH_SUCCESS = 'ALIASES_FETCH_SUCCESS'; +export const ALIASES_FETCH_FAIL = 'ALIASES_FETCH_FAIL'; export const ALIASES_SUGGESTIONS_CHANGE = 'ALIASES_SUGGESTIONS_CHANGE'; export const ALIASES_SUGGESTIONS_READY = 'ALIASES_SUGGESTIONS_READY'; @@ -23,6 +31,38 @@ const messages = defineMessages({ removeSuccess: { id: 'aliases.success.remove', defaultMessage: 'Account alias removed successfully' }, }); +export const fetchAliases = (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + const state = getState(); + + const instance = state.get('instance'); + const features = getFeatures(instance); + + if (!features.accountMoving) return; + + dispatch(fetchAliasesRequest()); + + api(getState).get('/api/pleroma/aliases') + .then(response => { + dispatch(fetchAliasesSuccess(response.data.aliases)); + }) + .catch(err => dispatch(fetchAliasesFail(err))); +}; + +export const fetchAliasesRequest = () => ({ + type: ALIASES_FETCH_REQUEST, +}); + +export const fetchAliasesSuccess = aliases => ({ + type: ALIASES_FETCH_SUCCESS, + value: aliases, +}); + +export const fetchAliasesFail = error => ({ + type: ALIASES_FETCH_FAIL, + error, +}); + export const fetchAliasesSuggestions = q => (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -53,80 +93,104 @@ export const changeAliasesSuggestions = value => ({ value, }); -export const addToAliases = (intl, apId) => (dispatch, getState) => { +export const addToAliases = (intl, account) => (dispatch, getState) => { if (!isLoggedIn(getState)) return; const state = getState(); - const me = state.get('me'); - const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); + const instance = state.get('instance'); + const features = getFeatures(instance); - dispatch(addToAliasesRequest(apId)); + if (!features.accountMoving) { + const me = state.get('me'); + const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); - api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, apId] }) - .then((response => { + dispatch(addToAliasesRequest()); + + api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, account.getIn(['pleroma', 'ap_id'])] }) + .then((response => { + dispatch(snackbar.success(intl.formatMessage(messages.createSuccess))); + dispatch(addToAliasesSuccess); + dispatch(patchMeSuccess(response.data)); + })) + .catch(err => dispatch(addToAliasesFail(err))); + + return; + } + + dispatch(addToAliasesRequest()); + + api(getState).put('/api/pleroma/aliases', { + alias: account.get('acct'), + }) + .then(response => { dispatch(snackbar.success(intl.formatMessage(messages.createSuccess))); - dispatch(addToAliasesSuccess(response.data)); - })) - .catch(err => dispatch(addToAliasesFail(err))); + dispatch(addToAliasesSuccess); + dispatch(fetchAliases); + }) + .catch(err => dispatch(fetchAliasesFail(err))); }; -export const addToAliasesRequest = (apId) => ({ +export const addToAliasesRequest = () => ({ type: ALIASES_ADD_REQUEST, - apId, }); -export const addToAliasesSuccess = me => dispatch => { - dispatch(importFetchedAccount(me)); - dispatch({ - type: ME_PATCH_SUCCESS, - me, - }); - dispatch({ - type: ALIASES_ADD_SUCCESS, - }); -}; +export const addToAliasesSuccess = () => ({ + type: ALIASES_ADD_SUCCESS, +}); -export const addToAliasesFail = (apId, error) => ({ +export const addToAliasesFail = error => ({ type: ALIASES_ADD_FAIL, - apId, error, }); -export const removeFromAliases = (intl, apId) => (dispatch, getState) => { +export const removeFromAliases = (intl, account) => (dispatch, getState) => { if (!isLoggedIn(getState)) return; const state = getState(); - const me = state.get('me'); - const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); + const instance = state.get('instance'); + const features = getFeatures(instance); - dispatch(removeFromAliasesRequest(apId)); + if (!features.accountMoving) { + const me = state.get('me'); + const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); - api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== apId) }) + dispatch(removeFromAliasesRequest()); + + api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== account) }) + .then(response => { + dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess))); + dispatch(removeFromAliasesSuccess); + dispatch(patchMeSuccess(response.data)); + }) + .catch(err => dispatch(removeFromAliasesFail(err))); + + return; + } + + dispatch(addToAliasesRequest()); + + api(getState).delete('/api/pleroma/aliases', { + data: { + alias: account, + }, + }) .then(response => { dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess))); - dispatch(removeFromAliasesSuccess(response.data)); + dispatch(removeFromAliasesSuccess); + dispatch(fetchAliases); }) - .catch(err => dispatch(removeFromAliasesFail(apId, err))); + .catch(err => dispatch(fetchAliasesFail(err))); }; -export const removeFromAliasesRequest = (apId) => ({ +export const removeFromAliasesRequest = () => ({ type: ALIASES_REMOVE_REQUEST, - apId, }); -export const removeFromAliasesSuccess = me => dispatch => { - dispatch(importFetchedAccount(me)); - dispatch({ - type: ME_PATCH_SUCCESS, - me, - }); - dispatch({ - type: ALIASES_REMOVE_SUCCESS, - }); -}; +export const removeFromAliasesSuccess = () => ({ + type: ALIASES_REMOVE_SUCCESS, +}); -export const removeFromAliasesFail = (apId, error) => ({ +export const removeFromAliasesFail = error => ({ type: ALIASES_REMOVE_FAIL, - apId, error, }); diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 128df1027..5274a98cf 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -8,18 +8,21 @@ */ import { defineMessages } from 'react-intl'; -import api, { baseClient } from '../api'; -import { importFetchedAccount } from './importer'; -import snackbar from 'soapbox/actions/snackbar'; + import { createAccount } from 'soapbox/actions/accounts'; -import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me'; -import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import { createApp } from 'soapbox/actions/apps'; +import { fetchMeSuccess, fetchMeFail } from 'soapbox/actions/me'; import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth'; +import snackbar from 'soapbox/actions/snackbar'; +import KVStore from 'soapbox/storage/kv_store'; +import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; import { isStandalone } from 'soapbox/utils/state'; -import KVStore from 'soapbox/storage/kv_store'; + +import api, { baseClient } from '../api'; + +import { importFetchedAccount } from './importer'; export const SWITCH_ACCOUNT = 'SWITCH_ACCOUNT'; @@ -140,6 +143,7 @@ export function otpVerify(code, mfa_token) { code: code, challenge_type: 'totp', redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', + scope: getScopes(getState()), }).then(({ data: token }) => dispatch(authLoggedIn(token))); }; } @@ -186,7 +190,7 @@ export function loadCredentials(token, accountUrl) { export function logIn(intl, username, password) { return (dispatch, getState) => { - return dispatch(createAppAndToken()).then(() => { + return dispatch(createAuthApp()).then(() => { return dispatch(createUserToken(username, password)); }).catch(error => { if (error.response.data.error === 'mfa_required') { diff --git a/app/soapbox/actions/blocks.js b/app/soapbox/actions/blocks.js index 63d01de3a..554446f2f 100644 --- a/app/soapbox/actions/blocks.js +++ b/app/soapbox/actions/blocks.js @@ -1,9 +1,11 @@ -import api, { getLinks } from '../api'; -import { fetchRelationships } from './accounts'; -import { importFetchedAccounts } from './importer'; import { isLoggedIn } from 'soapbox/utils/auth'; import { getNextLinkName } from 'soapbox/utils/quirks'; +import api, { getLinks } from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; + export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST'; export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS'; export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL'; diff --git a/app/soapbox/actions/bookmarks.js b/app/soapbox/actions/bookmarks.js index cf1ca8113..a0400ff38 100644 --- a/app/soapbox/actions/bookmarks.js +++ b/app/soapbox/actions/bookmarks.js @@ -1,4 +1,5 @@ import api, { getLinks } from '../api'; + import { importFetchedStatuses } from './importer'; export const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST'; diff --git a/app/soapbox/actions/chats.js b/app/soapbox/actions/chats.js index 5fa6811ee..8003bb8cb 100644 --- a/app/soapbox/actions/chats.js +++ b/app/soapbox/actions/chats.js @@ -1,12 +1,19 @@ -import api from '../api'; -import { getSettings, changeSetting } from 'soapbox/actions/settings'; -import { v4 as uuidv4 } from 'uuid'; import { Map as ImmutableMap } from 'immutable'; +import { v4 as uuidv4 } from 'uuid'; + +import { getSettings, changeSetting } from 'soapbox/actions/settings'; +import { getFeatures } from 'soapbox/utils/features'; + +import api, { getLinks } from '../api'; export const CHATS_FETCH_REQUEST = 'CHATS_FETCH_REQUEST'; export const CHATS_FETCH_SUCCESS = 'CHATS_FETCH_SUCCESS'; export const CHATS_FETCH_FAIL = 'CHATS_FETCH_FAIL'; +export const CHATS_EXPAND_REQUEST = 'CHATS_EXPAND_REQUEST'; +export const CHATS_EXPAND_SUCCESS = 'CHATS_EXPAND_SUCCESS'; +export const CHATS_EXPAND_FAIL = 'CHATS_EXPAND_FAIL'; + export const CHAT_MESSAGES_FETCH_REQUEST = 'CHAT_MESSAGES_FETCH_REQUEST'; export const CHAT_MESSAGES_FETCH_SUCCESS = 'CHAT_MESSAGES_FETCH_SUCCESS'; export const CHAT_MESSAGES_FETCH_FAIL = 'CHAT_MESSAGES_FETCH_FAIL'; @@ -27,14 +34,61 @@ export const CHAT_MESSAGE_DELETE_REQUEST = 'CHAT_MESSAGE_DELETE_REQUEST'; export const CHAT_MESSAGE_DELETE_SUCCESS = 'CHAT_MESSAGE_DELETE_SUCCESS'; export const CHAT_MESSAGE_DELETE_FAIL = 'CHAT_MESSAGE_DELETE_FAIL'; -export function fetchChats() { - return (dispatch, getState) => { - dispatch({ type: CHATS_FETCH_REQUEST }); - return api(getState).get('/api/v1/pleroma/chats').then(({ data }) => { - dispatch({ type: CHATS_FETCH_SUCCESS, chats: data }); +export function fetchChatsV1() { + return (dispatch, getState) => + api(getState).get('/api/v1/pleroma/chats').then((response) => { + dispatch({ type: CHATS_FETCH_SUCCESS, chats: response.data }); }).catch(error => { dispatch({ type: CHATS_FETCH_FAIL, error }); }); +} + +export function fetchChatsV2() { + return (dispatch, getState) => + api(getState).get('/api/v2/pleroma/chats').then((response) => { + let next = getLinks(response).refs.find(link => link.rel === 'next'); + + if (!next && response.data.length) { + next = { uri: `/api/v2/pleroma/chats?max_id=${response.data[response.data.length - 1].id}&offset=0` }; + } + + dispatch({ type: CHATS_FETCH_SUCCESS, chats: response.data, next: next ? next.uri : null }); + }).catch(error => { + dispatch({ type: CHATS_FETCH_FAIL, error }); + }); +} + +export function fetchChats() { + return (dispatch, getState) => { + const state = getState(); + const instance = state.get('instance'); + const features = getFeatures(instance); + + dispatch({ type: CHATS_FETCH_REQUEST }); + if (features.chatsV2) { + dispatch(fetchChatsV2()); + } else { + dispatch(fetchChatsV1()); + } + }; +} + +export function expandChats() { + return (dispatch, getState) => { + const url = getState().getIn(['chats', 'next']); + + if (url === null) { + return; + } + + dispatch({ type: CHATS_EXPAND_REQUEST }); + api(getState).get(url).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + + dispatch({ type: CHATS_EXPAND_SUCCESS, chats: response.data, next: next ? next.uri : null }); + }).catch(error => { + dispatch({ type: CHATS_EXPAND_FAIL, error }); + }); }; } @@ -140,7 +194,7 @@ export function startChat(accountId) { export function markChatRead(chatId, lastReadId) { return (dispatch, getState) => { - const chat = getState().getIn(['chats', chatId]); + const chat = getState().getIn(['chats', 'items', chatId]); if (!lastReadId) lastReadId = chat.get('last_message'); if (chat.get('unread') < 1) return; diff --git a/app/soapbox/actions/compose.js b/app/soapbox/actions/compose.js index 421df5883..04b1c3cd7 100644 --- a/app/soapbox/actions/compose.js +++ b/app/soapbox/actions/compose.js @@ -1,20 +1,23 @@ -import api from '../api'; import { CancelToken, isCancel } from 'axios'; import { throttle } from 'lodash'; +import { defineMessages } from 'react-intl'; + +import snackbar from 'soapbox/actions/snackbar'; +import { isLoggedIn } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; + +import api from '../api'; import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light'; import { tagHistory } from '../settings'; -import { useEmoji } from './emojis'; import resizeImage from '../utils/resize_image'; -import { importFetchedAccounts } from './importer'; + import { showAlert, showAlertForError } from './alerts'; -import { defineMessages } from 'react-intl'; -import { openModal, closeModal } from './modal'; -import { getSettings } from './settings'; -import { getFeatures } from 'soapbox/utils/features'; +import { useEmoji } from './emojis'; +import { importFetchedAccounts } from './importer'; import { uploadMedia, fetchMedia, updateMedia } from './media'; -import { isLoggedIn } from 'soapbox/utils/auth'; +import { openModal, closeModal } from './modals'; +import { getSettings } from './settings'; import { createStatus } from './statuses'; -import snackbar from 'soapbox/actions/snackbar'; let cancelFetchComposeSuggestionsAccounts; @@ -24,6 +27,8 @@ export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS'; export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL'; export const COMPOSE_REPLY = 'COMPOSE_REPLY'; export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL'; +export const COMPOSE_QUOTE = 'COMPOSE_QUOTE'; +export const COMPOSE_QUOTE_CANCEL = 'COMPOSE_QUOTE_CANCEL'; export const COMPOSE_DIRECT = 'COMPOSE_DIRECT'; export const COMPOSE_MENTION = 'COMPOSE_MENTION'; export const COMPOSE_RESET = 'COMPOSE_RESET'; @@ -68,11 +73,15 @@ export const COMPOSE_SCHEDULE_ADD = 'COMPOSE_SCHEDULE_ADD'; export const COMPOSE_SCHEDULE_SET = 'COMPOSE_SCHEDULE_SET'; export const COMPOSE_SCHEDULE_REMOVE = 'COMPOSE_SCHEDULE_REMOVE'; +export const COMPOSE_ADD_TO_MENTIONS = 'COMPOSE_ADD_TO_MENTIONS'; +export const COMPOSE_REMOVE_FROM_MENTIONS = 'COMPOSE_REMOVE_FROM_MENTIONS'; + const messages = defineMessages({ uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' }, uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' }, scheduleError: { id: 'compose.invalid_schedule', defaultMessage: 'You must schedule a post at least 5 minutes out.' }, success: { id: 'compose.submit_success', defaultMessage: 'Your post was sent' }, + view: { id: 'snackbar.view', defaultMessage: 'View' }, }); const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1); @@ -93,10 +102,14 @@ export function changeCompose(text) { export function replyCompose(status, routerHistory) { return (dispatch, getState) => { const state = getState(); + const instance = state.get('instance'); + const { explicitAddressing } = getFeatures(instance); + dispatch({ type: COMPOSE_REPLY, status: status, account: state.getIn(['accounts', state.get('me')]), + explicitAddressing, }); dispatch(openModal('COMPOSE')); @@ -109,6 +122,29 @@ export function cancelReplyCompose() { }; } +export function quoteCompose(status, routerHistory) { + return (dispatch, getState) => { + const state = getState(); + const instance = state.get('instance'); + const { explicitAddressing } = getFeatures(instance); + + dispatch({ + type: COMPOSE_QUOTE, + status: status, + account: state.getIn(['accounts', state.get('me')]), + explicitAddressing, + }); + + dispatch(openModal('COMPOSE')); + }; +} + +export function cancelQuoteCompose() { + return { + type: COMPOSE_QUOTE_CANCEL, + }; +} + export function resetCompose() { return { type: COMPOSE_RESET, @@ -155,7 +191,7 @@ export function handleComposeSubmit(dispatch, getState, data, status) { dispatch(insertIntoTagHistory(data.tags || [], status)); dispatch(submitComposeSuccess({ ...data })); - dispatch(snackbar.success(messages.success)); + dispatch(snackbar.success(messages.success, messages.view, `/@${data.account.acct}/posts/${data.id}`)); } const needsDescriptions = state => { @@ -183,6 +219,7 @@ export function submitCompose(routerHistory, force = false) { const status = state.getIn(['compose', 'text'], ''); const media = state.getIn(['compose', 'media_attachments']); + let to = state.getIn(['compose', 'to'], null); if (!validateSchedule(state)) { dispatch(snackbar.error(messages.scheduleError)); @@ -200,6 +237,13 @@ export function submitCompose(routerHistory, force = false) { return; } + if (to && status) { + const mentions = status.match(/(?:^|\s|\.)@([a-z0-9_]+(?:@[a-z0-9\.\-]+)?)/gi); // not a perfect regex + + if (mentions) + to = to.union(mentions.map(mention => mention.trim().slice(1))); + } + dispatch(submitComposeRequest()); dispatch(closeModal()); @@ -208,6 +252,7 @@ export function submitCompose(routerHistory, force = false) { const params = { status, in_reply_to_id: state.getIn(['compose', 'in_reply_to'], null), + quote_id: state.getIn(['compose', 'quote'], null), media_ids: media.map(item => item.get('id')), sensitive: state.getIn(['compose', 'sensitive']), spoiler_text: state.getIn(['compose', 'spoiler_text'], ''), @@ -215,6 +260,7 @@ export function submitCompose(routerHistory, force = false) { content_type: state.getIn(['compose', 'content_type']), poll: state.getIn(['compose', 'poll'], null), scheduled_at: state.getIn(['compose', 'schedule'], null), + to, }; dispatch(createStatus(params, idempotencyKey)).then(function(data) { @@ -251,8 +297,7 @@ export function submitComposeFail(error) { export function uploadCompose(files) { return function(dispatch, getState) { if (!isLoggedIn(getState)) return; - const instance = getState().get('instance'); - const { attachmentLimit } = getFeatures(instance); + const attachmentLimit = getState().getIn(['instance', 'configuration', 'statuses', 'max_media_attachments']); const media = getState().getIn(['compose', 'media_attachments']); const progress = new Array(files.length).fill(0); @@ -643,3 +688,27 @@ export function openComposeWithText(text = '') { dispatch(changeCompose(text)); }; } + +export function addToMentions(accountId) { + return (dispatch, getState) => { + const state = getState(); + const acct = state.getIn(['accounts', accountId, 'acct']); + + return dispatch({ + type: COMPOSE_ADD_TO_MENTIONS, + account: acct, + }); + }; +} + +export function removeFromMentions(accountId) { + return (dispatch, getState) => { + const state = getState(); + const acct = state.getIn(['accounts', accountId, 'acct']); + + return dispatch({ + type: COMPOSE_REMOVE_FROM_MENTIONS, + account: acct, + }); + }; +} diff --git a/app/soapbox/actions/conversations.js b/app/soapbox/actions/conversations.js index e019441f9..4e7eb214f 100644 --- a/app/soapbox/actions/conversations.js +++ b/app/soapbox/actions/conversations.js @@ -1,10 +1,12 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; + import api, { getLinks } from '../api'; + import { importFetchedAccounts, importFetchedStatuses, importFetchedStatus, } from './importer'; -import { isLoggedIn } from 'soapbox/utils/auth'; export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT'; export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT'; diff --git a/app/soapbox/actions/directory.js b/app/soapbox/actions/directory.js new file mode 100644 index 000000000..0ee15386b --- /dev/null +++ b/app/soapbox/actions/directory.js @@ -0,0 +1,62 @@ +import api from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; + +export const DIRECTORY_FETCH_REQUEST = 'DIRECTORY_FETCH_REQUEST'; +export const DIRECTORY_FETCH_SUCCESS = 'DIRECTORY_FETCH_SUCCESS'; +export const DIRECTORY_FETCH_FAIL = 'DIRECTORY_FETCH_FAIL'; + +export const DIRECTORY_EXPAND_REQUEST = 'DIRECTORY_EXPAND_REQUEST'; +export const DIRECTORY_EXPAND_SUCCESS = 'DIRECTORY_EXPAND_SUCCESS'; +export const DIRECTORY_EXPAND_FAIL = 'DIRECTORY_EXPAND_FAIL'; + +export const fetchDirectory = params => (dispatch, getState) => { + dispatch(fetchDirectoryRequest()); + + api(getState).get('/api/v1/directory', { params: { ...params, limit: 20 } }).then(({ data }) => { + dispatch(importFetchedAccounts(data)); + dispatch(fetchDirectorySuccess(data)); + dispatch(fetchRelationships(data.map(x => x.id))); + }).catch(error => dispatch(fetchDirectoryFail(error))); +}; + +export const fetchDirectoryRequest = () => ({ + type: DIRECTORY_FETCH_REQUEST, +}); + +export const fetchDirectorySuccess = accounts => ({ + type: DIRECTORY_FETCH_SUCCESS, + accounts, +}); + +export const fetchDirectoryFail = error => ({ + type: DIRECTORY_FETCH_FAIL, + error, +}); + +export const expandDirectory = params => (dispatch, getState) => { + dispatch(expandDirectoryRequest()); + + const loadedItems = getState().getIn(['user_lists', 'directory', 'items']).size; + + api(getState).get('/api/v1/directory', { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => { + dispatch(importFetchedAccounts(data)); + dispatch(expandDirectorySuccess(data)); + dispatch(fetchRelationships(data.map(x => x.id))); + }).catch(error => dispatch(expandDirectoryFail(error))); +}; + +export const expandDirectoryRequest = () => ({ + type: DIRECTORY_EXPAND_REQUEST, +}); + +export const expandDirectorySuccess = accounts => ({ + type: DIRECTORY_EXPAND_SUCCESS, + accounts, +}); + +export const expandDirectoryFail = error => ({ + type: DIRECTORY_EXPAND_FAIL, + error, +}); \ No newline at end of file diff --git a/app/soapbox/actions/domain_blocks.js b/app/soapbox/actions/domain_blocks.js index 8872590a3..92824a55c 100644 --- a/app/soapbox/actions/domain_blocks.js +++ b/app/soapbox/actions/domain_blocks.js @@ -1,6 +1,7 @@ -import api, { getLinks } from '../api'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api, { getLinks } from '../api'; + export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST'; export const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS'; export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL'; diff --git a/app/soapbox/actions/emoji_reacts.js b/app/soapbox/actions/emoji_reacts.js index 8ed43b8ed..a057dd35e 100644 --- a/app/soapbox/actions/emoji_reacts.js +++ b/app/soapbox/actions/emoji_reacts.js @@ -1,8 +1,11 @@ +import { List as ImmutableList } from 'immutable'; + +import { isLoggedIn } from 'soapbox/utils/auth'; + import api from '../api'; + import { importFetchedAccounts, importFetchedStatus } from './importer'; import { favourite, unfavourite } from './interactions'; -import { isLoggedIn } from 'soapbox/utils/auth'; -import { List as ImmutableList } from 'immutable'; export const EMOJI_REACT_REQUEST = 'EMOJI_REACT_REQUEST'; export const EMOJI_REACT_SUCCESS = 'EMOJI_REACT_SUCCESS'; diff --git a/app/soapbox/actions/export_data.js b/app/soapbox/actions/export_data.js index 479b44b0a..12e0bd58b 100644 --- a/app/soapbox/actions/export_data.js +++ b/app/soapbox/actions/export_data.js @@ -1,5 +1,7 @@ import { defineMessages } from 'react-intl'; + import snackbar from 'soapbox/actions/snackbar'; + import api, { getLinks } from '../api'; export const EXPORT_FOLLOWS_REQUEST = 'EXPORT_FOLLOWS_REQUEST'; diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js index d486b4026..f4058cba2 100644 --- a/app/soapbox/actions/external_auth.js +++ b/app/soapbox/actions/external_auth.js @@ -6,21 +6,25 @@ * @see module:soapbox/actions/oauth */ -import { baseClient } from '../api'; -import { createApp } from 'soapbox/actions/apps'; -import { obtainOAuthToken } from 'soapbox/actions/oauth'; -import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; -import { parseBaseURL } from 'soapbox/utils/auth'; -import { getFeatures } from 'soapbox/utils/features'; -import sourceCode from 'soapbox/utils/code'; import { Map as ImmutableMap, fromJS } from 'immutable'; +import { createApp } from 'soapbox/actions/apps'; +import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; +import { obtainOAuthToken } from 'soapbox/actions/oauth'; +import { parseBaseURL } from 'soapbox/utils/auth'; +import sourceCode from 'soapbox/utils/code'; +import { getWalletAndSign } from 'soapbox/utils/ethereum'; +import { getFeatures } from 'soapbox/utils/features'; +import { getQuirks } from 'soapbox/utils/quirks'; + +import { baseClient } from '../api'; + const fetchExternalInstance = baseURL => { return baseClient(null, baseURL) .get('/api/v1/instance') .then(({ data: instance }) => fromJS(instance)) .catch(error => { - if (error.response && error.response.status === 401) { + if (error.response?.status === 401) { // Authenticated fetch is enabled. // Continue with a limited featureset. return ImmutableMap({ version: '0.0.0' }); @@ -30,36 +34,86 @@ const fetchExternalInstance = baseURL => { }); }; -export function createAppAndRedirect(host) { +function createExternalApp(instance, baseURL) { + return (dispatch, getState) => { + // Mitra: skip creating the auth app + if (getQuirks(instance).noApps) return new Promise(f => f({})); + + const { scopes } = getFeatures(instance); + + const params = { + client_name: sourceCode.displayName, + redirect_uris: `${window.location.origin}/auth/external`, + website: sourceCode.homepage, + scopes, + }; + + return dispatch(createApp(params, baseURL)); + }; +} + +function externalAuthorize(instance, baseURL) { + return (dispatch, getState) => { + const { scopes } = getFeatures(instance); + + return dispatch(createExternalApp(instance, baseURL)).then(app => { + const { client_id, redirect_uri } = app; + + const query = new URLSearchParams({ + client_id, + redirect_uri, + response_type: 'code', + scope: scopes, + }); + + localStorage.setItem('soapbox:external:app', JSON.stringify(app)); + localStorage.setItem('soapbox:external:baseurl', baseURL); + localStorage.setItem('soapbox:external:scopes', scopes); + + window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; + }); + }; +} + +export function externalEthereumLogin(instance, baseURL) { + return (dispatch, getState) => { + const loginMessage = instance.get('login_message'); + + return getWalletAndSign(loginMessage).then(({ wallet, signature }) => { + return dispatch(createExternalApp(instance, baseURL)).then(app => { + const params = { + grant_type: 'ethereum', + wallet_address: wallet.toLowerCase(), + client_id: app.client_id, + client_secret: app.client_secret, + password: signature, + redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', + scope: getFeatures(instance).scopes, + }; + + return dispatch(obtainOAuthToken(params, baseURL)) + .then(token => dispatch(authLoggedIn(token))) + .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL))) + .then(account => dispatch(switchAccount(account.id))) + .then(() => window.location.href = '/'); + }); + }); + }; +} + +export function externalLogin(host) { return (dispatch, getState) => { const baseURL = parseBaseURL(host) || parseBaseURL(`https://${host}`); return fetchExternalInstance(baseURL).then(instance => { - const { scopes } = getFeatures(instance); + const features = getFeatures(instance); + const quirks = getQuirks(instance); - const params = { - client_name: sourceCode.displayName, - redirect_uris: `${window.location.origin}/auth/external`, - website: sourceCode.homepage, - scopes, - }; - - return dispatch(createApp(params, baseURL)).then(app => { - const { client_id, redirect_uri } = app; - - const query = new URLSearchParams({ - client_id, - redirect_uri, - response_type: 'code', - scope: scopes, - }); - - localStorage.setItem('soapbox:external:app', JSON.stringify(app)); - localStorage.setItem('soapbox:external:baseurl', baseURL); - localStorage.setItem('soapbox:external:scopes', scopes); - - window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; - }); + if (features.ethereumLogin && quirks.noOAuthForm) { + return dispatch(externalEthereumLogin(instance, baseURL)); + } else { + return dispatch(externalAuthorize(instance, baseURL)); + } }); }; } diff --git a/app/soapbox/actions/favourites.js b/app/soapbox/actions/favourites.js index dfc1ee9ba..c4bce15e9 100644 --- a/app/soapbox/actions/favourites.js +++ b/app/soapbox/actions/favourites.js @@ -1,7 +1,9 @@ -import api, { getLinks } from '../api'; -import { importFetchedStatuses } from './importer'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api, { getLinks } from '../api'; + +import { importFetchedStatuses } from './importer'; + export const FAVOURITED_STATUSES_FETCH_REQUEST = 'FAVOURITED_STATUSES_FETCH_REQUEST'; export const FAVOURITED_STATUSES_FETCH_SUCCESS = 'FAVOURITED_STATUSES_FETCH_SUCCESS'; export const FAVOURITED_STATUSES_FETCH_FAIL = 'FAVOURITED_STATUSES_FETCH_FAIL'; diff --git a/app/soapbox/actions/filters.js b/app/soapbox/actions/filters.js index b5964cd38..e6af25f9c 100644 --- a/app/soapbox/actions/filters.js +++ b/app/soapbox/actions/filters.js @@ -1,8 +1,10 @@ import { defineMessages } from 'react-intl'; -import api from '../api'; + import snackbar from 'soapbox/actions/snackbar'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api from '../api'; + export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST'; export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS'; export const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL'; diff --git a/app/soapbox/actions/group_editor.js b/app/soapbox/actions/group_editor.js index b74533a14..f504a743a 100644 --- a/app/soapbox/actions/group_editor.js +++ b/app/soapbox/actions/group_editor.js @@ -1,6 +1,7 @@ -import api from '../api'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api from '../api'; + export const GROUP_CREATE_REQUEST = 'GROUP_CREATE_REQUEST'; export const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS'; export const GROUP_CREATE_FAIL = 'GROUP_CREATE_FAIL'; diff --git a/app/soapbox/actions/groups.js b/app/soapbox/actions/groups.js index 94b3675ad..3c6255216 100644 --- a/app/soapbox/actions/groups.js +++ b/app/soapbox/actions/groups.js @@ -1,8 +1,10 @@ -import api, { getLinks } from '../api'; -import { importFetchedAccounts } from './importer'; -import { fetchRelationships } from './accounts'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api, { getLinks } from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; + export const GROUP_FETCH_REQUEST = 'GROUP_FETCH_REQUEST'; export const GROUP_FETCH_SUCCESS = 'GROUP_FETCH_SUCCESS'; export const GROUP_FETCH_FAIL = 'GROUP_FETCH_FAIL'; diff --git a/app/soapbox/actions/import_data.js b/app/soapbox/actions/import_data.js index acf205f94..7bde21a4a 100644 --- a/app/soapbox/actions/import_data.js +++ b/app/soapbox/actions/import_data.js @@ -1,7 +1,9 @@ import { defineMessages } from 'react-intl'; -import api from '../api'; + import snackbar from 'soapbox/actions/snackbar'; +import api from '../api'; + export const IMPORT_FOLLOWS_REQUEST = 'IMPORT_FOLLOWS_REQUEST'; export const IMPORT_FOLLOWS_SUCCESS = 'IMPORT_FOLLOWS_SUCCESS'; export const IMPORT_FOLLOWS_FAIL = 'IMPORT_FOLLOWS_FAIL'; diff --git a/app/soapbox/actions/importer/index.js b/app/soapbox/actions/importer/index.js index ee4f1cfa7..3a019e636 100644 --- a/app/soapbox/actions/importer/index.js +++ b/app/soapbox/actions/importer/index.js @@ -1,4 +1,5 @@ import { getSettings } from '../settings'; + import { normalizeAccount, normalizeStatus, @@ -12,12 +13,6 @@ export const STATUSES_IMPORT = 'STATUSES_IMPORT'; export const POLLS_IMPORT = 'POLLS_IMPORT'; export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'; -function pushUnique(array, object) { - if (array.every(element => element.id !== object.id)) { - array.push(object); - } -} - export function importAccount(account) { return { type: ACCOUNT_IMPORT, account }; } @@ -48,7 +43,7 @@ export function importFetchedAccounts(accounts) { function processAccount(account) { if (!account.id) return; - pushUnique(normalAccounts, normalizeAccount(account)); + normalAccounts.push(normalizeAccount(account)); if (account.moved) { processAccount(account.moved); @@ -70,11 +65,20 @@ export function importFetchedStatus(status, idempotencyKey) { const normalizedStatus = normalizeStatus(status, normalOldStatus, expandSpoilers); - if (status.reblog && status.reblog.id) { + if (status.reblog?.id) { dispatch(importFetchedStatus(status.reblog)); } - if (status.poll && status.poll.id) { + // Fedibird quotes + if (status.quote?.id) { + dispatch(importFetchedStatus(status.quote)); + } + + if (status.pleroma?.quote?.id) { + dispatch(importFetchedStatus(status.pleroma.quote)); + } + + if (status.poll?.id) { dispatch(importFetchedPoll(status.poll)); } @@ -112,15 +116,24 @@ export function importFetchedStatuses(statuses) { const normalOldStatus = getState().getIn(['statuses', status.id]); const expandSpoilers = getSettings(getState()).get('expandSpoilers'); - pushUnique(normalStatuses, normalizeStatus(status, normalOldStatus, expandSpoilers)); - pushUnique(accounts, status.account); + normalStatuses.push(normalizeStatus(status, normalOldStatus, expandSpoilers)); + accounts.push(status.account); - if (status.reblog && status.reblog.id) { + if (status.reblog?.id) { processStatus(status.reblog); } - if (status.poll && status.poll.id) { - pushUnique(polls, normalizePoll(status.poll)); + // Fedibird quotes + if (status.quote?.id) { + processStatus(status.quote); + } + + if (status.pleroma?.quote?.id) { + processStatus(status.pleroma.quote); + } + + if (status.poll?.id) { + polls.push(normalizePoll(status.poll)); } } diff --git a/app/soapbox/actions/importer/normalizer.js b/app/soapbox/actions/importer/normalizer.js index 922e57986..7d40357f0 100644 --- a/app/soapbox/actions/importer/normalizer.js +++ b/app/soapbox/actions/importer/normalizer.js @@ -1,4 +1,7 @@ import escapeTextContentForBrowser from 'escape-html'; + +import { stripCompatibilityFeatures } from 'soapbox/utils/html'; + import emojify from '../../features/emoji/emoji'; import { unescapeHTML } from '../../utils/html'; @@ -12,6 +15,13 @@ const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => { export function normalizeAccount(account) { account = { ...account }; + // Some backends can return null, or omit these required fields + if (!account.emojis) account.emojis = []; + if (!account.display_name) account.display_name = ''; + if (!account.note) account.note = ''; + if (!account.avatar) account.avatar = account.avatar_static || require('images/avatar-missing.png'); + if (!account.avatar_static) account.avatar_static = account.avatar; + const emojiMap = makeEmojiMap(account); const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name; @@ -36,18 +46,39 @@ export function normalizeAccount(account) { } export function normalizeStatus(status, normalOldStatus, expandSpoilers) { - const normalStatus = { ...status }; + const normalStatus = { ...status }; + + // Some backends can return null, or omit these required fields + if (!normalStatus.emojis) normalStatus.emojis = []; + if (!normalStatus.spoiler_text) normalStatus.spoiler_text = ''; + + // Copy the pleroma object too, so we can modify our copy + if (status.pleroma) { + normalStatus.pleroma = { ...status.pleroma }; + } normalStatus.account = status.account.id; - if (status.reblog && status.reblog.id) { + if (status.reblog?.id) { normalStatus.reblog = status.reblog.id; } - if (status.poll && status.poll.id) { + if (status.poll?.id) { normalStatus.poll = status.poll.id; } + if (status.pleroma?.quote?.id) { + // Normalize quote to the top-level, so delete the original for performance + normalStatus.quote = status.pleroma.quote.id; + delete normalStatus.pleroma.quote; + } else if (status.quote?.id) { + // Fedibird compatibility, because why not + normalStatus.quote = status.quote.id; + } else if (status.quote_id) { + // Fedibird: fall back to quote_id + normalStatus.quote = status.quote_id; + } + // Only calculate these values when status first encountered // Otherwise keep the ones already in the reducer if (normalOldStatus) { @@ -57,11 +88,11 @@ export function normalizeStatus(status, normalOldStatus, expandSpoilers) { normalStatus.hidden = normalOldStatus.get('hidden'); } else { const spoilerText = normalStatus.spoiler_text || ''; - const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).join('\n\n').replace(//g, '\n').replace(/<\/p>

/g, '\n\n'); + const searchContent = ([spoilerText, status.content].concat((status.poll?.options) ? status.poll.options.map(option => option.title) : [])).join('\n\n').replace(//g, '\n').replace(/<\/p>

/g, '\n\n'); const emojiMap = makeEmojiMap(normalStatus); normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; - normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); + normalStatus.contentHtml = stripCompatibilityFeatures(emojify(normalStatus.content, emojiMap)); normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap); normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive; } @@ -76,7 +107,7 @@ export function normalizePoll(poll) { normalPoll.options = poll.options.map((option, index) => ({ ...option, - voted: poll.own_votes && poll.own_votes.includes(index), + voted: Boolean(poll.own_votes?.includes(index)), title_emojified: emojify(escapeTextContentForBrowser(option.title), emojiMap), })); diff --git a/app/soapbox/actions/instance.js b/app/soapbox/actions/instance.js index ec77742b2..b1df09d64 100644 --- a/app/soapbox/actions/instance.js +++ b/app/soapbox/actions/instance.js @@ -1,8 +1,10 @@ -import api from '../api'; import { get } from 'lodash'; -import { parseVersion } from 'soapbox/utils/features'; -import { getAuthUserUrl } from 'soapbox/utils/auth'; + import KVStore from 'soapbox/storage/kv_store'; +import { getAuthUserUrl } from 'soapbox/utils/auth'; +import { parseVersion } from 'soapbox/utils/features'; + +import api from '../api'; export const INSTANCE_FETCH_REQUEST = 'INSTANCE_FETCH_REQUEST'; export const INSTANCE_FETCH_SUCCESS = 'INSTANCE_FETCH_SUCCESS'; @@ -22,7 +24,7 @@ const getMeUrl = state => { }; // Figure out the appropriate instance to fetch depending on the state -const getHost = state => { +export const getHost = state => { const accountUrl = getMeUrl(state) || getAuthUserUrl(state); try { @@ -59,6 +61,7 @@ export function fetchInstance() { dispatch(fetchNodeinfo()); // Pleroma < 2.1 backwards compatibility } }).catch(error => { + console.error(error); dispatch({ type: INSTANCE_FETCH_FAIL, error, skipAlert: true }); }); }; diff --git a/app/soapbox/actions/interactions.js b/app/soapbox/actions/interactions.js index 1e2d729f1..bb0461411 100644 --- a/app/soapbox/actions/interactions.js +++ b/app/soapbox/actions/interactions.js @@ -1,9 +1,12 @@ import { defineMessages } from 'react-intl'; -import api from '../api'; -import { importFetchedAccounts, importFetchedStatus } from './importer'; + import snackbar from 'soapbox/actions/snackbar'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api from '../api'; + +import { importFetchedAccounts, importFetchedStatus } from './importer'; + export const REBLOG_REQUEST = 'REBLOG_REQUEST'; export const REBLOG_SUCCESS = 'REBLOG_SUCCESS'; export const REBLOG_FAIL = 'REBLOG_FAIL'; @@ -48,9 +51,14 @@ export const UNBOOKMARK_REQUEST = 'UNBOOKMARKED_REQUEST'; export const UNBOOKMARK_SUCCESS = 'UNBOOKMARKED_SUCCESS'; export const UNBOOKMARK_FAIL = 'UNBOOKMARKED_FAIL'; +export const REMOTE_INTERACTION_REQUEST = 'REMOTE_INTERACTION_REQUEST'; +export const REMOTE_INTERACTION_SUCCESS = 'REMOTE_INTERACTION_SUCCESS'; +export const REMOTE_INTERACTION_FAIL = 'REMOTE_INTERACTION_FAIL'; + const messages = defineMessages({ bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' }, bookmarkRemoved: { id: 'status.unbookmarked', defaultMessage: 'Bookmark removed.' }, + view: { id: 'snackbar.view', defaultMessage: 'View' }, }); export function reblog(status) { @@ -77,7 +85,6 @@ export function unreblog(status) { dispatch(unreblogRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => { - dispatch(importFetchedStatus(response.data)); dispatch(unreblogSuccess(status)); }).catch(error => { dispatch(unreblogFail(status, error)); @@ -157,7 +164,6 @@ export function unfavourite(status) { dispatch(unfavouriteRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => { - dispatch(importFetchedStatus(response.data)); dispatch(unfavouriteSuccess(status)); }).catch(error => { dispatch(unfavouriteFail(status, error)); @@ -215,28 +221,28 @@ export function unfavouriteFail(status, error) { }; } -export function bookmark(intl, status) { +export function bookmark(status) { return function(dispatch, getState) { dispatch(bookmarkRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function(response) { dispatch(importFetchedStatus(response.data)); dispatch(bookmarkSuccess(status, response.data)); - dispatch(snackbar.success(intl.formatMessage(messages.bookmarkAdded))); + dispatch(snackbar.success(messages.bookmarkAdded, messages.view, '/bookmarks')); }).catch(function(error) { dispatch(bookmarkFail(status, error)); }); }; } -export function unbookmark(intl, status) { +export function unbookmark(status) { return (dispatch, getState) => { dispatch(unbookmarkRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => { dispatch(importFetchedStatus(response.data)); dispatch(unbookmarkSuccess(status, response.data)); - dispatch(snackbar.success(intl.formatMessage(messages.bookmarkRemoved))); + dispatch(snackbar.success(messages.bookmarkRemoved)); }).catch(error => { dispatch(unbookmarkFail(status, error)); }); @@ -477,3 +483,46 @@ export function unpinFail(status, error) { skipLoading: true, }; } + +export function remoteInteraction(ap_id, profile) { + return (dispatch, getState) => { + dispatch(remoteInteractionRequest(ap_id, profile)); + + return api(getState).post('/api/v1/pleroma/remote_interaction', { ap_id, profile }).then(({ data }) => { + if (data.error) throw new Error(data.error); + + dispatch(remoteInteractionSuccess(ap_id, profile, data.url)); + + return data.url; + }).catch(error => { + dispatch(remoteInteractionFail(ap_id, profile, error)); + throw error; + }); + }; +} + +export function remoteInteractionRequest(ap_id, profile) { + return { + type: REMOTE_INTERACTION_REQUEST, + ap_id, + profile, + }; +} + +export function remoteInteractionSuccess(ap_id, profile, url) { + return { + type: REMOTE_INTERACTION_SUCCESS, + ap_id, + profile, + url, + }; +} + +export function remoteInteractionFail(ap_id, profile, error) { + return { + type: REMOTE_INTERACTION_FAIL, + ap_id, + profile, + error, + }; +} diff --git a/app/soapbox/actions/lists.js b/app/soapbox/actions/lists.js index 68171cbe3..6b39978d2 100644 --- a/app/soapbox/actions/lists.js +++ b/app/soapbox/actions/lists.js @@ -1,8 +1,10 @@ -import api from '../api'; -import { importFetchedAccounts } from './importer'; -import { showAlertForError } from './alerts'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api from '../api'; + +import { showAlertForError } from './alerts'; +import { importFetchedAccounts } from './importer'; + export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST'; export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS'; export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL'; @@ -367,7 +369,7 @@ export const fetchAccountLists = accountId => (dispatch, getState) => { }; export const fetchAccountListsRequest = id => ({ - type:LIST_ADDER_LISTS_FETCH_REQUEST, + type: LIST_ADDER_LISTS_FETCH_REQUEST, id, }); diff --git a/app/soapbox/actions/me.js b/app/soapbox/actions/me.js index 2dcf36ab9..e04001e4c 100644 --- a/app/soapbox/actions/me.js +++ b/app/soapbox/actions/me.js @@ -1,8 +1,10 @@ -import api from '../api'; -import { importFetchedAccount } from './importer'; -import { loadCredentials } from './auth'; import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth'; +import api from '../api'; + +import { loadCredentials } from './auth'; +import { importFetchedAccount } from './importer'; + export const ME_FETCH_REQUEST = 'ME_FETCH_REQUEST'; export const ME_FETCH_SUCCESS = 'ME_FETCH_SUCCESS'; export const ME_FETCH_FAIL = 'ME_FETCH_FAIL'; diff --git a/app/soapbox/actions/media.js b/app/soapbox/actions/media.js index 3c71c91a4..460c2f079 100644 --- a/app/soapbox/actions/media.js +++ b/app/soapbox/actions/media.js @@ -1,6 +1,7 @@ -import api from '../api'; import { getFeatures } from 'soapbox/utils/features'; +import api from '../api'; + const noOp = () => {}; export function fetchMedia(mediaId) { diff --git a/app/soapbox/actions/mfa.js b/app/soapbox/actions/mfa.js index 7cde55b84..d41c60f52 100644 --- a/app/soapbox/actions/mfa.js +++ b/app/soapbox/actions/mfa.js @@ -1,180 +1,84 @@ import api from '../api'; -export const TOTP_SETTINGS_FETCH_REQUEST = 'TOTP_SETTINGS_FETCH_REQUEST'; -export const TOTP_SETTINGS_FETCH_SUCCESS = 'TOTP_SETTINGS_FETCH_SUCCESS'; -export const TOTP_SETTINGS_FETCH_FAIL = 'TOTP_SETTINGS_FETCH_FAIL'; +export const MFA_FETCH_REQUEST = 'MFA_FETCH_REQUEST'; +export const MFA_FETCH_SUCCESS = 'MFA_FETCH_SUCCESS'; +export const MFA_FETCH_FAIL = 'MFA_FETCH_FAIL'; -export const BACKUP_CODES_FETCH_REQUEST = 'BACKUP_CODES_FETCH_REQUEST'; -export const BACKUP_CODES_FETCH_SUCCESS = 'BACKUP_CODES_FETCH_SUCCESS'; -export const BACKUP_CODES_FETCH_FAIL = 'BACKUP_CODES_FETCH_FAIL'; +export const MFA_BACKUP_CODES_FETCH_REQUEST = 'MFA_BACKUP_CODES_FETCH_REQUEST'; +export const MFA_BACKUP_CODES_FETCH_SUCCESS = 'MFA_BACKUP_CODES_FETCH_SUCCESS'; +export const MFA_BACKUP_CODES_FETCH_FAIL = 'MFA_BACKUP_CODES_FETCH_FAIL'; -export const TOTP_SETUP_FETCH_REQUEST = 'TOTP_SETUP_FETCH_REQUEST'; -export const TOTP_SETUP_FETCH_SUCCESS = 'TOTP_SETUP_FETCH_SUCCESS'; -export const TOTP_SETUP_FETCH_FAIL = 'TOTP_SETUP_FETCH_FAIL'; +export const MFA_SETUP_REQUEST = 'MFA_SETUP_REQUEST'; +export const MFA_SETUP_SUCCESS = 'MFA_SETUP_SUCCESS'; +export const MFA_SETUP_FAIL = 'MFA_SETUP_FAIL'; -export const CONFIRM_TOTP_REQUEST = 'CONFIRM_TOTP_REQUEST'; -export const CONFIRM_TOTP_SUCCESS = 'CONFIRM_TOTP_SUCCESS'; -export const CONFIRM_TOTP_FAIL = 'CONFIRM_TOTP_FAIL'; +export const MFA_CONFIRM_REQUEST = 'MFA_CONFIRM_REQUEST'; +export const MFA_CONFIRM_SUCCESS = 'MFA_CONFIRM_SUCCESS'; +export const MFA_CONFIRM_FAIL = 'MFA_CONFIRM_FAIL'; -export const DISABLE_TOTP_REQUEST = 'DISABLE_TOTP_REQUEST'; -export const DISABLE_TOTP_SUCCESS = 'DISABLE_TOTP_SUCCESS'; -export const DISABLE_TOTP_FAIL = 'DISABLE_TOTP_FAIL'; +export const MFA_DISABLE_REQUEST = 'MFA_DISABLE_REQUEST'; +export const MFA_DISABLE_SUCCESS = 'MFA_DISABLE_SUCCESS'; +export const MFA_DISABLE_FAIL = 'MFA_DISABLE_FAIL'; -export function fetchUserMfaSettings() { +export function fetchMfa() { return (dispatch, getState) => { - dispatch({ type: TOTP_SETTINGS_FETCH_REQUEST }); - return api(getState).get('/api/pleroma/accounts/mfa').then(response => { - dispatch({ type: TOTP_SETTINGS_FETCH_SUCCESS, totpEnabled: response.data.totp }); - return response; + dispatch({ type: MFA_FETCH_REQUEST }); + return api(getState).get('/api/pleroma/accounts/mfa').then(({ data }) => { + dispatch({ type: MFA_FETCH_SUCCESS, data }); }).catch(error => { - dispatch({ type: TOTP_SETTINGS_FETCH_FAIL }); + dispatch({ type: MFA_FETCH_FAIL }); }); }; } -export function fetchUserMfaSettingsRequest() { - return { - type: TOTP_SETTINGS_FETCH_REQUEST, - }; -} - -export function fetchUserMfaSettingsSuccess() { - return { - type: TOTP_SETTINGS_FETCH_SUCCESS, - }; -} - -export function fetchUserMfaSettingsFail() { - return { - type: TOTP_SETTINGS_FETCH_FAIL, - }; -} - export function fetchBackupCodes() { return (dispatch, getState) => { - dispatch({ type: BACKUP_CODES_FETCH_REQUEST }); - return api(getState).get('/api/pleroma/accounts/mfa/backup_codes').then(response => { - dispatch({ type: BACKUP_CODES_FETCH_SUCCESS, backup_codes: response.data }); - return response; + dispatch({ type: MFA_BACKUP_CODES_FETCH_REQUEST }); + return api(getState).get('/api/pleroma/accounts/mfa/backup_codes').then(({ data }) => { + dispatch({ type: MFA_BACKUP_CODES_FETCH_SUCCESS, data }); + return data; }).catch(error => { - dispatch({ type: BACKUP_CODES_FETCH_FAIL }); + dispatch({ type: MFA_BACKUP_CODES_FETCH_FAIL }); }); }; } -export function fetchBackupCodesRequest() { - return { - type: BACKUP_CODES_FETCH_REQUEST, - }; -} - -export function fetchBackupCodesSuccess(backup_codes, response) { - return { - type: BACKUP_CODES_FETCH_SUCCESS, - backup_codes: response.data, - }; -} - -export function fetchBackupCodesFail(error) { - return { - type: BACKUP_CODES_FETCH_FAIL, - error, - }; -} - -export function fetchToptSetup() { +export function setupMfa(method) { return (dispatch, getState) => { - dispatch({ type: TOTP_SETUP_FETCH_REQUEST }); - return api(getState).get('/api/pleroma/accounts/mfa/setup/totp').then(response => { - dispatch({ type: TOTP_SETUP_FETCH_SUCCESS, totp_setup: response.data }); - return response; + dispatch({ type: MFA_SETUP_REQUEST, method }); + return api(getState).get(`/api/pleroma/accounts/mfa/setup/${method}`).then(({ data }) => { + dispatch({ type: MFA_SETUP_SUCCESS, data }); + return data; }).catch(error => { - dispatch({ type: TOTP_SETUP_FETCH_FAIL }); + dispatch({ type: MFA_SETUP_FAIL }); + throw error; }); }; } -export function fetchToptSetupRequest() { - return { - type: TOTP_SETUP_FETCH_REQUEST, - }; -} - -export function fetchToptSetupSuccess(totp_setup, response) { - return { - type: TOTP_SETUP_FETCH_SUCCESS, - totp_setup: response.data, - }; -} - -export function fetchToptSetupFail(error) { - return { - type: TOTP_SETUP_FETCH_FAIL, - error, - }; -} - -export function confirmToptSetup(code, password) { +export function confirmMfa(method, code, password) { return (dispatch, getState) => { - dispatch({ type: CONFIRM_TOTP_REQUEST, code }); - return api(getState).post('/api/pleroma/accounts/mfa/confirm/totp', { - code, - password, - }).then(response => { - dispatch({ type: CONFIRM_TOTP_SUCCESS }); - return response; + const params = { code, password }; + dispatch({ type: MFA_CONFIRM_REQUEST, method, code }); + return api(getState).post(`/api/pleroma/accounts/mfa/confirm/${method}`, params).then(({ data }) => { + dispatch({ type: MFA_CONFIRM_SUCCESS, method, code }); + return data; }).catch(error => { - dispatch({ type: CONFIRM_TOTP_FAIL }); + dispatch({ type: MFA_CONFIRM_FAIL, method, code, error, skipAlert: true }); + throw error; }); }; } -export function confirmToptRequest() { - return { - type: CONFIRM_TOTP_REQUEST, - }; -} - -export function confirmToptSuccess(backup_codes, response) { - return { - type: CONFIRM_TOTP_SUCCESS, - }; -} - -export function confirmToptFail(error) { - return { - type: CONFIRM_TOTP_FAIL, - error, - }; -} - -export function disableToptSetup(password) { +export function disableMfa(method, password) { return (dispatch, getState) => { - dispatch({ type: DISABLE_TOTP_REQUEST }); - return api(getState).delete('/api/pleroma/accounts/mfa/totp', { data: { password } }).then(response => { - dispatch({ type: DISABLE_TOTP_SUCCESS }); - return response; + dispatch({ type: MFA_DISABLE_REQUEST, method }); + return api(getState).delete(`/api/pleroma/accounts/mfa/${method}`, { data: { password } }).then(({ data }) => { + dispatch({ type: MFA_DISABLE_SUCCESS, method }); + return data; }).catch(error => { - dispatch({ type: DISABLE_TOTP_FAIL }); + dispatch({ type: MFA_DISABLE_FAIL, method, skipAlert: true }); + throw error; }); }; } - -export function disableToptRequest() { - return { - type: DISABLE_TOTP_REQUEST, - }; -} - -export function disableToptSuccess(backup_codes, response) { - return { - type: DISABLE_TOTP_SUCCESS, - }; -} - -export function disableToptFail(error) { - return { - type: DISABLE_TOTP_FAIL, - error, - }; -} diff --git a/app/soapbox/actions/modal.js b/app/soapbox/actions/modals.js similarity index 100% rename from app/soapbox/actions/modal.js rename to app/soapbox/actions/modals.js diff --git a/app/soapbox/actions/moderation.js b/app/soapbox/actions/moderation.js index cb84803bd..d84242d66 100644 --- a/app/soapbox/actions/moderation.js +++ b/app/soapbox/actions/moderation.js @@ -1,23 +1,32 @@ import React from 'react'; import { defineMessages } from 'react-intl'; -import { openModal } from 'soapbox/actions/modal'; -import { deactivateUsers, deleteUsers, deleteStatus, toggleStatusSensitivity } from 'soapbox/actions/admin'; + import { fetchAccountByUsername } from 'soapbox/actions/accounts'; +import { deactivateUsers, deleteUsers, deleteStatus, toggleStatusSensitivity } from 'soapbox/actions/admin'; +import { openModal } from 'soapbox/actions/modals'; import snackbar from 'soapbox/actions/snackbar'; import AccountContainer from 'soapbox/containers/account_container'; import { isLocal } from 'soapbox/utils/accounts'; const messages = defineMessages({ + deactivateUserHeading: { id: 'confirmations.admin.deactivate_user.heading', defaultMessage: 'Deactivate @{acct}' }, deactivateUserPrompt: { id: 'confirmations.admin.deactivate_user.message', defaultMessage: 'You are about to deactivate @{acct}. Deactivating a user is a reversible action.' }, deactivateUserConfirm: { id: 'confirmations.admin.deactivate_user.confirm', defaultMessage: 'Deactivate @{name}' }, userDeactivated: { id: 'admin.users.user_deactivated_message', defaultMessage: '@{acct} was deactivated' }, + deleteUserHeading: { id: 'confirmations.admin.delete_user.heading', defaultMessage: 'Delete @{acct}' }, deleteUserPrompt: { id: 'confirmations.admin.delete_user.message', defaultMessage: 'You are about to delete @{acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.' }, deleteUserConfirm: { id: 'confirmations.admin.delete_user.confirm', defaultMessage: 'Delete @{name}' }, deleteLocalUserCheckbox: { id: 'confirmations.admin.delete_local_user.checkbox', defaultMessage: 'I understand that I am about to delete a local user.' }, userDeleted: { id: 'admin.users.user_deleted_message', defaultMessage: '@{acct} was deleted' }, + deleteStatusHeading: { id: 'confirmations.admin.delete_status.heading', defaultMessage: 'Delete post' }, deleteStatusPrompt: { id: 'confirmations.admin.delete_status.message', defaultMessage: 'You are about to delete a post by @{acct}. This action cannot be undone.' }, deleteStatusConfirm: { id: 'confirmations.admin.delete_status.confirm', defaultMessage: 'Delete post' }, + rejectUserHeading: { id: 'confirmations.admin.reject_user.heading', defaultMessage: 'Reject @{acct}' }, + rejectUserPrompt: { id: 'confirmations.admin.reject_user.message', defaultMessage: 'You are about to reject @{acct} registration request. This action cannot be undone.' }, + rejectUserConfirm: { id: 'confirmations.admin.reject_user.confirm', defaultMessage: 'Reject @{name}' }, statusDeleted: { id: 'admin.statuses.status_deleted_message', defaultMessage: 'Post by @{acct} was deleted' }, + markStatusSensitiveHeading: { id: 'confirmations.admin.mark_status_sensitive.heading', defaultMessage: 'Mark post sensitive' }, + markStatusNotSensitiveHeading: { id: 'confirmations.admin.mark_status_not_sensitive.heading', defaultMessage: 'Mark post not sensitive.' }, markStatusSensitivePrompt: { id: 'confirmations.admin.mark_status_sensitive.message', defaultMessage: 'You are about to mark a post by @{acct} sensitive.' }, markStatusNotSensitivePrompt: { id: 'confirmations.admin.mark_status_not_sensitive.message', defaultMessage: 'You are about to mark a post by @{acct} not sensitive.' }, markStatusSensitiveConfirm: { id: 'confirmations.admin.mark_status_sensitive.confirm', defaultMessage: 'Mark post sensitive' }, @@ -33,6 +42,8 @@ export function deactivateUserModal(intl, accountId, afterConfirm = () => {}) { const name = state.getIn(['accounts', accountId, 'username']); dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/user-off.svg'), + heading: intl.formatMessage(messages.deactivateUserHeading, { acct }), message: intl.formatMessage(messages.deactivateUserPrompt, { acct }), confirm: intl.formatMessage(messages.deactivateUserConfirm, { name }), onConfirm: () => { @@ -70,6 +81,8 @@ export function deleteUserModal(intl, accountId, afterConfirm = () => {}) { const checkbox = local ? intl.formatMessage(messages.deleteLocalUserCheckbox) : false; dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/user-minus.svg'), + heading: intl.formatMessage(messages.deleteUserHeading, { acct }), message, confirm, checkbox, @@ -85,6 +98,28 @@ export function deleteUserModal(intl, accountId, afterConfirm = () => {}) { }; } +export function rejectUserModal(intl, accountId, afterConfirm = () => {}) { + return function(dispatch, getState) { + const state = getState(); + const acct = state.getIn(['accounts', accountId, 'acct']); + const name = state.getIn(['accounts', accountId, 'username']); + + dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/user-off.svg'), + heading: intl.formatMessage(messages.rejectUserHeading, { acct }), + message: intl.formatMessage(messages.rejectUserPrompt, { acct }), + confirm: intl.formatMessage(messages.rejectUserConfirm, { name }), + onConfirm: () => { + dispatch(deleteUsers([accountId])) + .then(() => { + afterConfirm(); + }) + .catch(() => {}); + }, + })); + }; +} + export function toggleStatusSensitivityModal(intl, statusId, sensitive, afterConfirm = () => {}) { return function(dispatch, getState) { const state = getState(); @@ -92,6 +127,8 @@ export function toggleStatusSensitivityModal(intl, statusId, sensitive, afterCon const acct = state.getIn(['accounts', accountId, 'acct']); dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/alert-triangle.svg'), + heading: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveHeading : messages.markStatusNotSensitiveHeading), message: intl.formatMessage(sensitive === false ? messages.markStatusSensitivePrompt : messages.markStatusNotSensitivePrompt, { acct }), confirm: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveConfirm : messages.markStatusNotSensitiveConfirm), onConfirm: () => { @@ -112,6 +149,8 @@ export function deleteStatusModal(intl, statusId, afterConfirm = () => {}) { const acct = state.getIn(['accounts', accountId, 'acct']); dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/trash.svg'), + heading: intl.formatMessage(messages.deleteStatusHeading), message: intl.formatMessage(messages.deleteStatusPrompt, { acct }), confirm: intl.formatMessage(messages.deleteStatusConfirm), onConfirm: () => { diff --git a/app/soapbox/actions/mrf.js b/app/soapbox/actions/mrf.js index e4f07a9fd..39359e965 100644 --- a/app/soapbox/actions/mrf.js +++ b/app/soapbox/actions/mrf.js @@ -1,7 +1,9 @@ -import { fetchConfig, updateConfig } from './admin'; import { Set as ImmutableSet } from 'immutable'; + import ConfigDB from 'soapbox/utils/config_db'; +import { fetchConfig, updateConfig } from './admin'; + const simplePolicyMerge = (simplePolicy, host, restrictions) => { return simplePolicy.map((hosts, key) => { const isRestricted = restrictions.get(key); diff --git a/app/soapbox/actions/mutes.js b/app/soapbox/actions/mutes.js index 3cdc3b5fb..f204ea9b8 100644 --- a/app/soapbox/actions/mutes.js +++ b/app/soapbox/actions/mutes.js @@ -1,10 +1,12 @@ -import api, { getLinks } from '../api'; -import { fetchRelationships } from './accounts'; -import { importFetchedAccounts } from './importer'; -import { openModal } from './modal'; import { isLoggedIn } from 'soapbox/utils/auth'; import { getNextLinkName } from 'soapbox/utils/quirks'; +import api, { getLinks } from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; +import { openModal } from './modals'; + export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST'; export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS'; export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL'; diff --git a/app/soapbox/actions/notifications.js b/app/soapbox/actions/notifications.js index ca37cf525..a4331bf8c 100644 --- a/app/soapbox/actions/notifications.js +++ b/app/soapbox/actions/notifications.js @@ -1,6 +1,20 @@ -import api, { getLinks } from '../api'; +import { + List as ImmutableList, + Map as ImmutableMap, + OrderedMap as ImmutableOrderedMap, +} from 'immutable'; import IntlMessageFormat from 'intl-messageformat'; import 'intl-pluralrules'; +import { defineMessages } from 'react-intl'; + +import { isLoggedIn } from 'soapbox/utils/auth'; +import { parseVersion, PLEROMA } from 'soapbox/utils/features'; +import { joinPublicPath } from 'soapbox/utils/static'; + +import api, { getLinks } from '../api'; +import { getFilters, regexFromFilters } from '../selectors'; +import { unescapeHTML } from '../utils/html'; + import { fetchRelationships } from './accounts'; import { importFetchedAccount, @@ -10,17 +24,6 @@ import { } from './importer'; import { saveMarker } from './markers'; import { getSettings, saveSettings } from './settings'; -import { defineMessages } from 'react-intl'; -import { - List as ImmutableList, - Map as ImmutableMap, - OrderedMap as ImmutableOrderedMap, -} from 'immutable'; -import { unescapeHTML } from '../utils/html'; -import { getFilters, regexFromFilters } from '../selectors'; -import { isLoggedIn } from 'soapbox/utils/auth'; -import { parseVersion, PLEROMA } from 'soapbox/utils/features'; -import { joinPublicPath } from 'soapbox/utils/static'; export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP'; @@ -115,7 +118,7 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale, data: { url: joinPublicPath('/notifications'), }, - }); + }).catch(console.error); }).catch(console.error); } } catch(e) { @@ -203,16 +206,16 @@ export function expandNotifications({ maxId } = {}, done = noOp) { const next = getLinks(response).refs.find(link => link.rel === 'next'); const entries = response.data.reduce((acc, item) => { - if (item.account && item.account.id) { + if (item.account?.id) { acc.accounts[item.account.id] = item.account; } // Used by Move notification - if (item.target && item.target.id) { + if (item.target?.id) { acc.accounts[item.target.id] = item.target; } - if (item.status && item.status.id) { + if (item.status?.id) { acc.statuses[item.status.id] = item.status; } diff --git a/app/soapbox/actions/pin_statuses.js b/app/soapbox/actions/pin_statuses.js index ecab511d0..26194f553 100644 --- a/app/soapbox/actions/pin_statuses.js +++ b/app/soapbox/actions/pin_statuses.js @@ -1,7 +1,9 @@ -import api from '../api'; -import { importFetchedStatuses } from './importer'; import { isLoggedIn } from 'soapbox/utils/auth'; +import api from '../api'; + +import { importFetchedStatuses } from './importer'; + export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST'; export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS'; export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL'; diff --git a/app/soapbox/actions/polls.js b/app/soapbox/actions/polls.js index 8e8b82df5..a37410dc9 100644 --- a/app/soapbox/actions/polls.js +++ b/app/soapbox/actions/polls.js @@ -1,4 +1,5 @@ import api from '../api'; + import { importFetchedPoll } from './importer'; export const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST'; diff --git a/app/soapbox/actions/preload.js b/app/soapbox/actions/preload.js index c8f2fe7d1..d14c6f9fe 100644 --- a/app/soapbox/actions/preload.js +++ b/app/soapbox/actions/preload.js @@ -1,6 +1,7 @@ import { mapValues } from 'lodash'; -import { importFetchedAccounts } from './importer'; + import { verifyCredentials } from './auth'; +import { importFetchedAccounts } from './importer'; export const PLEROMA_PRELOAD_IMPORT = 'PLEROMA_PRELOAD_IMPORT'; export const MASTODON_PRELOAD_IMPORT = 'MASTODON_PRELOAD_IMPORT'; diff --git a/app/soapbox/actions/push_notifications/index.js b/app/soapbox/actions/push_notifications/index.js index 2ffec500a..32b0ffcaf 100644 --- a/app/soapbox/actions/push_notifications/index.js +++ b/app/soapbox/actions/push_notifications/index.js @@ -1,3 +1,4 @@ +import { register, saveSettings } from './registerer'; import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, @@ -5,7 +6,6 @@ import { SET_ALERTS, setAlerts, } from './setter'; -import { register, saveSettings } from './registerer'; export { SET_BROWSER_SUPPORT, diff --git a/app/soapbox/actions/push_notifications/registerer.js b/app/soapbox/actions/push_notifications/registerer.js index 156641c2b..b4d86631e 100644 --- a/app/soapbox/actions/push_notifications/registerer.js +++ b/app/soapbox/actions/push_notifications/registerer.js @@ -1,7 +1,10 @@ -import { decode as decodeBase64 } from '../../utils/base64'; -import { pushNotificationsSetting } from '../../settings'; -import { setBrowserSupport, setSubscription, clearSubscription } from './setter'; import { createPushSubsription, updatePushSubscription } from 'soapbox/actions/push_subscriptions'; +import { getVapidKey } from 'soapbox/utils/auth'; + +import { pushNotificationsSetting } from '../../settings'; +import { decode as decodeBase64 } from '../../utils/base64'; + +import { setBrowserSupport, setSubscription, clearSubscription } from './setter'; // Taken from https://www.npmjs.com/package/web-push const urlBase64ToUint8Array = (base64String) => { @@ -13,11 +16,6 @@ const urlBase64ToUint8Array = (base64String) => { return decodeBase64(base64); }; -const getVapidKey = getState => { - const state = getState(); - return state.getIn(['auth', 'app', 'vapid_key']) || state.getIn(['instance', 'pleroma', 'vapid_public_key']); -}; - const getRegistration = () => navigator.serviceWorker.ready; const getPushSubscription = (registration) => @@ -27,7 +25,7 @@ const getPushSubscription = (registration) => const subscribe = (registration, getState) => registration.pushManager.subscribe({ userVisibleOnly: true, - applicationServerKey: urlBase64ToUint8Array(getVapidKey(getState)), + applicationServerKey: urlBase64ToUint8Array(getVapidKey(getState())), }); const unsubscribe = ({ registration, subscription }) => @@ -35,7 +33,8 @@ const unsubscribe = ({ registration, subscription }) => const sendSubscriptionToBackend = (subscription, me) => { return (dispatch, getState) => { - const params = { subscription }; + const alerts = getState().getIn(['push_notifications', 'alerts']).toJS(); + const params = { subscription, data: { alerts } }; if (me) { const data = pushNotificationsSetting.get(me); @@ -54,7 +53,7 @@ const supportsPushNotifications = ('serviceWorker' in navigator && 'PushManager' export function register() { return (dispatch, getState) => { const me = getState().get('me'); - const vapidKey = getVapidKey(getState); + const vapidKey = getVapidKey(getState()); dispatch(setBrowserSupport(supportsPushNotifications)); @@ -105,6 +104,7 @@ export function register() { } }) .catch(error => { + console.error(error); if (error.code === 20 && error.name === 'AbortError') { console.warn('Your browser supports Web Push Notifications, but does not seem to implement the VAPID protocol.'); } else if (error.code === 5 && error.name === 'InvalidCharacterError') { diff --git a/app/soapbox/actions/reports.js b/app/soapbox/actions/reports.js index 9d0d4e581..8b7c55644 100644 --- a/app/soapbox/actions/reports.js +++ b/app/soapbox/actions/reports.js @@ -1,5 +1,6 @@ import api from '../api'; -import { openModal, closeModal } from './modal'; + +import { openModal, closeModal } from './modals'; export const REPORT_INIT = 'REPORT_INIT'; export const REPORT_CANCEL = 'REPORT_CANCEL'; diff --git a/app/soapbox/actions/search.js b/app/soapbox/actions/search.js index 6f1621ad4..27cb4bdbd 100644 --- a/app/soapbox/actions/search.js +++ b/app/soapbox/actions/search.js @@ -1,4 +1,5 @@ import api from '../api'; + import { fetchRelationships } from './accounts'; import { importFetchedAccounts, importFetchedStatuses } from './importer'; @@ -17,9 +18,16 @@ export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS'; export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL'; export function changeSearch(value) { - return { - type: SEARCH_CHANGE, - value, + return (dispatch, getState) => { + // If backspaced all the way, clear the search + if (value.length === 0) { + return dispatch(clearSearch()); + } else { + return dispatch({ + type: SEARCH_CHANGE, + value, + }); + } }; } @@ -29,10 +37,12 @@ export function clearSearch() { }; } -export function submitSearch() { +export function submitSearch(filter) { return (dispatch, getState) => { const value = getState().getIn(['search', 'value']); + const type = filter || getState().getIn(['search', 'filter'], 'accounts'); + // An empty search doesn't return any results if (value.length === 0) { return; } @@ -44,6 +54,7 @@ export function submitSearch() { q: value, resolve: true, limit: 20, + type, }, }).then(response => { if (response.data.accounts) { @@ -54,7 +65,7 @@ export function submitSearch() { dispatch(importFetchedStatuses(response.data.statuses)); } - dispatch(fetchSearchSuccess(response.data)); + dispatch(fetchSearchSuccess(response.data, value, type)); dispatch(fetchRelationships(response.data.accounts.map(item => item.id))); }).catch(error => { dispatch(fetchSearchFail(error)); @@ -69,10 +80,12 @@ export function fetchSearchRequest(value) { }; } -export function fetchSearchSuccess(results) { +export function fetchSearchSuccess(results, searchTerm, searchType) { return { type: SEARCH_FETCH_SUCCESS, results, + searchTerm, + searchType, }; } @@ -83,13 +96,17 @@ export function fetchSearchFail(error) { }; } -export const setFilter = filterType => dispatch => { - dispatch({ - type: SEARCH_FILTER_SET, - path: ['search', 'filter'], - value: filterType, - }); -}; +export function setFilter(filterType) { + return (dispatch) => { + dispatch(submitSearch(filterType)); + + dispatch({ + type: SEARCH_FILTER_SET, + path: ['search', 'filter'], + value: filterType, + }); + }; +} export const expandSearch = type => (dispatch, getState) => { const value = getState().getIn(['search', 'value']); diff --git a/app/soapbox/actions/security.js b/app/soapbox/actions/security.js index e5e15b6f5..254acbdfb 100644 --- a/app/soapbox/actions/security.js +++ b/app/soapbox/actions/security.js @@ -4,9 +4,11 @@ * @see module:soapbox/actions/auth */ -import api from '../api'; -import { getLoggedInAccount } from 'soapbox/utils/auth'; import snackbar from 'soapbox/actions/snackbar'; +import { getLoggedInAccount } from 'soapbox/utils/auth'; + +import api from '../api'; + import { AUTH_LOGGED_OUT, messages } from './auth'; export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST'; @@ -33,6 +35,10 @@ export const DELETE_ACCOUNT_REQUEST = 'DELETE_ACCOUNT_REQUEST'; export const DELETE_ACCOUNT_SUCCESS = 'DELETE_ACCOUNT_SUCCESS'; export const DELETE_ACCOUNT_FAIL = 'DELETE_ACCOUNT_FAIL'; +export const MOVE_ACCOUNT_REQUEST = 'MOVE_ACCOUNT_REQUEST'; +export const MOVE_ACCOUNT_SUCCESS = 'MOVE_ACCOUNT_SUCCESS'; +export const MOVE_ACCOUNT_FAIL = 'MOVE_ACCOUNT_FAIL'; + export function fetchOAuthTokens() { return (dispatch, getState) => { dispatch({ type: FETCH_TOKENS_REQUEST }); @@ -122,3 +128,19 @@ export function deleteAccount(intl, password) { }); }; } + +export function moveAccount(targetAccount, password) { + return (dispatch, getState) => { + dispatch({ type: MOVE_ACCOUNT_REQUEST }); + return api(getState).post('/api/pleroma/move_account', { + password, + target_account: targetAccount, + }).then(response => { + if (response.data.error) throw response.data.error; // This endpoint returns HTTP 200 even on failure + dispatch({ type: MOVE_ACCOUNT_SUCCESS, response }); + }).catch(error => { + dispatch({ type: MOVE_ACCOUNT_FAIL, error, skipAlert: true }); + throw error; + }); + }; +} diff --git a/app/soapbox/actions/settings.js b/app/soapbox/actions/settings.js index 55ca6b0b5..418c41292 100644 --- a/app/soapbox/actions/settings.js +++ b/app/soapbox/actions/settings.js @@ -1,13 +1,17 @@ -import { debounce } from 'lodash'; -import { showAlertForError } from './alerts'; -import { patchMe } from 'soapbox/actions/me'; import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable'; -import { isLoggedIn } from 'soapbox/utils/auth'; -import uuid from '../uuid'; +import { debounce } from 'lodash'; import { createSelector } from 'reselect'; +import { patchMe } from 'soapbox/actions/me'; +import { isLoggedIn } from 'soapbox/utils/auth'; + +import uuid from '../uuid'; + +import { showAlertForError } from './alerts'; + export const SETTING_CHANGE = 'SETTING_CHANGE'; export const SETTING_SAVE = 'SETTING_SAVE'; +export const SETTINGS_UPDATE = 'SETTINGS_UPDATE'; export const FE_NAME = 'soapbox_fe'; @@ -30,7 +34,6 @@ export const defaultSettings = ImmutableMap({ locale: navigator.language.split(/[-_]/)[0] || 'en', showExplanationBox: true, explanationBox: true, - otpEnabled: false, autoloadTimelines: true, autoloadMore: true, @@ -97,12 +100,17 @@ export const defaultSettings = ImmutableMap({ move: false, 'pleroma:emoji_reaction': false, }), + + birthdays: ImmutableMap({ + show: true, + }), }), community: ImmutableMap({ shows: ImmutableMap({ reblog: false, reply: true, + direct: false, }), other: ImmutableMap({ onlyMedia: false, @@ -116,6 +124,7 @@ export const defaultSettings = ImmutableMap({ shows: ImmutableMap({ reblog: true, reply: true, + direct: false, }), other: ImmutableMap({ onlyMedia: false, @@ -135,6 +144,7 @@ export const defaultSettings = ImmutableMap({ shows: ImmutableMap({ reblog: true, pinned: true, + direct: false, }), }), @@ -162,6 +172,18 @@ export const getSettings = createSelector([ .mergeDeep(settings); }); +export function changeSettingImmediate(path, value) { + return dispatch => { + dispatch({ + type: SETTING_CHANGE, + path, + value, + }); + + dispatch(saveSettingsImmediate()); + }; +} + export function changeSetting(path, value) { return dispatch => { dispatch({ @@ -174,23 +196,29 @@ export function changeSetting(path, value) { }; } +export function saveSettingsImmediate() { + return (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + + const state = getState(); + if (getSettings(state).getIn(['saved'])) return; + + const data = state.get('settings').delete('saved').toJS(); + + dispatch(patchMe({ + pleroma_settings_store: { + [FE_NAME]: data, + }, + })).then(response => { + dispatch({ type: SETTING_SAVE }); + }).catch(error => { + dispatch(showAlertForError(error)); + }); + }; +} + const debouncedSave = debounce((dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - const state = getState(); - if (getSettings(state).getIn(['saved'])) return; - - const data = state.get('settings').delete('saved').toJS(); - - dispatch(patchMe({ - pleroma_settings_store: { - [FE_NAME]: data, - }, - })).then(response => { - dispatch({ type: SETTING_SAVE }); - }).catch(error => { - dispatch(showAlertForError(error)); - }); + dispatch(saveSettingsImmediate()); }, 5000, { trailing: true }); export function saveSettings() { diff --git a/app/soapbox/actions/snackbar.js b/app/soapbox/actions/snackbar.js index c1be02757..47fd11137 100644 --- a/app/soapbox/actions/snackbar.js +++ b/app/soapbox/actions/snackbar.js @@ -1,21 +1,23 @@ import { ALERT_SHOW } from './alerts'; -export const show = (severity, message) => ({ +export const show = (severity, message, actionLabel, actionLink) => ({ type: ALERT_SHOW, message, + actionLabel, + actionLink, severity, }); -export function info(message) { - return show('info', message); +export function info(message, actionLabel, actionLink) { + return show('info', message, actionLabel, actionLink); } -export function success(message) { - return show('success', message); +export function success(message, actionLabel, actionLink) { + return show('success', message, actionLabel, actionLink); } -export function error(message) { - return show('error', message); +export function error(message, actionLabel, actionLink) { + return show('error', message, actionLabel, actionLink); } export default { diff --git a/app/soapbox/actions/soapbox.js b/app/soapbox/actions/soapbox.js index 64fbe1891..d85bd0f0f 100644 --- a/app/soapbox/actions/soapbox.js +++ b/app/soapbox/actions/soapbox.js @@ -1,11 +1,19 @@ -import api, { staticClient } from '../api'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; -import { getFeatures } from 'soapbox/utils/features'; import { createSelector } from 'reselect'; +import { getHost } from 'soapbox/actions/instance'; +import KVStore from 'soapbox/storage/kv_store'; +import { getFeatures } from 'soapbox/utils/features'; + +import api, { staticClient } from '../api'; + export const SOAPBOX_CONFIG_REQUEST_SUCCESS = 'SOAPBOX_CONFIG_REQUEST_SUCCESS'; export const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL'; +export const SOAPBOX_CONFIG_REMEMBER_REQUEST = 'SOAPBOX_CONFIG_REMEMBER_REQUEST'; +export const SOAPBOX_CONFIG_REMEMBER_SUCCESS = 'SOAPBOX_CONFIG_REMEMBER_SUCCESS'; +export const SOAPBOX_CONFIG_REMEMBER_FAIL = 'SOAPBOX_CONFIG_REMEMBER_FAIL'; + const allowedEmoji = ImmutableList([ '👍', '❤', @@ -61,46 +69,71 @@ export const getSoapboxConfig = createSelector([ return makeDefaultConfig(features).merge(soapbox); }); -export function fetchSoapboxConfig() { +export function rememberSoapboxConfig(host) { + return (dispatch, getState) => { + dispatch({ type: SOAPBOX_CONFIG_REMEMBER_REQUEST, host }); + return KVStore.getItemOrError(`soapbox_config:${host}`).then(soapboxConfig => { + dispatch({ type: SOAPBOX_CONFIG_REMEMBER_SUCCESS, host, soapboxConfig }); + return soapboxConfig; + }).catch(error => { + dispatch({ type: SOAPBOX_CONFIG_REMEMBER_FAIL, host, error, skipAlert: true }); + }); + }; +} + +export function fetchSoapboxConfig(host) { return (dispatch, getState) => { api(getState).get('/api/pleroma/frontend_configurations').then(response => { if (response.data.soapbox_fe) { - dispatch(importSoapboxConfig(response.data.soapbox_fe)); + dispatch(importSoapboxConfig(response.data.soapbox_fe, host)); } else { - dispatch(fetchSoapboxJson()); + dispatch(fetchSoapboxJson(host)); } }).catch(error => { - dispatch(fetchSoapboxJson()); + dispatch(fetchSoapboxJson(host)); }); }; } -export function fetchSoapboxJson() { +// Tries to remember the config from browser storage before fetching it +export function loadSoapboxConfig() { + return (dispatch, getState) => { + const host = getHost(getState()); + + return dispatch(rememberSoapboxConfig(host)).finally(() => { + return dispatch(fetchSoapboxConfig(host)); + }); + }; +} + +export function fetchSoapboxJson(host) { return (dispatch, getState) => { staticClient.get('/instance/soapbox.json').then(({ data }) => { if (!isObject(data)) throw 'soapbox.json failed'; - dispatch(importSoapboxConfig(data)); + dispatch(importSoapboxConfig(data, host)); }).catch(error => { - dispatch(soapboxConfigFail(error)); + dispatch(soapboxConfigFail(error, host)); }); }; } -export function importSoapboxConfig(soapboxConfig) { +export function importSoapboxConfig(soapboxConfig, host) { if (!soapboxConfig.brandColor) { soapboxConfig.brandColor = '#0482d8'; } return { type: SOAPBOX_CONFIG_REQUEST_SUCCESS, soapboxConfig, + host, }; } -export function soapboxConfigFail(error) { +export function soapboxConfigFail(error, host) { return { type: SOAPBOX_CONFIG_REQUEST_FAIL, error, skipAlert: true, + host, }; } diff --git a/app/soapbox/actions/statuses.js b/app/soapbox/actions/statuses.js index 5b65349b7..b529e9b23 100644 --- a/app/soapbox/actions/statuses.js +++ b/app/soapbox/actions/statuses.js @@ -1,8 +1,12 @@ -import api from '../api'; -import { deleteFromTimelines } from './timelines'; -import { importFetchedStatus, importFetchedStatuses } from './importer'; -import { openModal } from './modal'; import { isLoggedIn } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; +import { shouldHaveCard } from 'soapbox/utils/status'; + +import api from '../api'; + +import { importFetchedStatus, importFetchedStatuses } from './importer'; +import { openModal } from './modals'; +import { deleteFromTimelines } from './timelines'; export const STATUS_CREATE_REQUEST = 'STATUS_CREATE_REQUEST'; export const STATUS_CREATE_SUCCESS = 'STATUS_CREATE_SUCCESS'; @@ -44,8 +48,31 @@ export function createStatus(params, idempotencyKey) { return api(getState).post('/api/v1/statuses', params, { headers: { 'Idempotency-Key': idempotencyKey }, }).then(({ data: status }) => { + // The backend might still be processing the rich media attachment + if (!status.card && shouldHaveCard(status)) { + status.expectsCard = true; + } + dispatch(importFetchedStatus(status, idempotencyKey)); dispatch({ type: STATUS_CREATE_SUCCESS, status, params, idempotencyKey }); + + // Poll the backend for the updated card + if (status.expectsCard) { + const delay = 1000; + + const poll = (retries = 5) => { + api(getState).get(`/api/v1/statuses/${status.id}`).then(response => { + if (response.data?.card) { + dispatch(importFetchedStatus(response.data)); + } else if (retries > 0 && response.status === 200) { + setTimeout(() => poll(retries - 1), delay); + } + }).catch(console.error); + }; + + setTimeout(() => poll(), delay); + } + return status; }).catch(error => { dispatch({ type: STATUS_CREATE_FAIL, error, params, idempotencyKey }); @@ -71,10 +98,17 @@ export function fetchStatus(id) { } export function redraft(status, raw_text) { - return { - type: REDRAFT, - status, - raw_text, + return (dispatch, getState) => { + const state = getState(); + const instance = state.get('instance'); + const { explicitAddressing } = getFeatures(instance); + + dispatch({ + type: REDRAFT, + status, + raw_text, + explicitAddressing, + }); }; } @@ -109,13 +143,21 @@ export function fetchContext(id) { dispatch({ type: CONTEXT_FETCH_REQUEST, id }); return api(getState).get(`/api/v1/statuses/${id}/context`).then(({ data: context }) => { - const { ancestors, descendants } = context; - const statuses = ancestors.concat(descendants); - dispatch(importFetchedStatuses(statuses)); - dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + if (Array.isArray(context)) { + // Mitra: returns a list of statuses + dispatch(importFetchedStatuses(context)); + } else if (typeof context === 'object') { + // Standard Mastodon API returns a map with `ancestors` and `descendants` + const { ancestors, descendants } = context; + const statuses = ancestors.concat(descendants); + dispatch(importFetchedStatuses(statuses)); + dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + } else { + throw context; + } return context; }).catch(error => { - if (error.response && error.response.status === 404) { + if (error.response?.status === 404) { dispatch(deleteFromTimelines(id)); } diff --git a/app/soapbox/actions/streaming.js b/app/soapbox/actions/streaming.js index 1b8de7b97..bd1ed00da 100644 --- a/app/soapbox/actions/streaming.js +++ b/app/soapbox/actions/streaming.js @@ -1,4 +1,11 @@ +import { getSettings } from 'soapbox/actions/settings'; +import messages from 'soapbox/locales/messages'; + import { connectStream } from '../stream'; + +import { updateConversations } from './conversations'; +import { fetchFilters } from './filters'; +import { updateNotificationsQueue, expandNotifications } from './notifications'; import { deleteFromTimelines, expandHomeTimeline, @@ -6,11 +13,6 @@ import { disconnectTimeline, processTimelineUpdate, } from './timelines'; -import { updateNotificationsQueue, expandNotifications } from './notifications'; -import { updateConversations } from './conversations'; -import { fetchFilters } from './filters'; -import { getSettings } from 'soapbox/actions/settings'; -import messages from 'soapbox/locales/messages'; export const STREAMING_CHAT_UPDATE = 'STREAMING_CHAT_UPDATE'; export const STREAMING_FOLLOW_RELATIONSHIPS_UPDATE = 'STREAMING_FOLLOW_RELATIONSHIPS_UPDATE'; diff --git a/app/soapbox/actions/suggestions.js b/app/soapbox/actions/suggestions.js index d36c2c21d..d896e6e07 100644 --- a/app/soapbox/actions/suggestions.js +++ b/app/soapbox/actions/suggestions.js @@ -1,8 +1,10 @@ -import api from '../api'; -import { importFetchedAccounts } from './importer'; import { isLoggedIn } from 'soapbox/utils/auth'; import { getFeatures } from 'soapbox/utils/features'; + +import api from '../api'; + import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST'; export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS'; diff --git a/app/soapbox/actions/timelines.js b/app/soapbox/actions/timelines.js index 934c52b00..12223c0ba 100644 --- a/app/soapbox/actions/timelines.js +++ b/app/soapbox/actions/timelines.js @@ -1,9 +1,12 @@ -import { importFetchedStatus, importFetchedStatuses } from './importer'; -import api, { getLinks } from '../api'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; + import { getSettings } from 'soapbox/actions/settings'; import { shouldFilter } from 'soapbox/utils/timelines'; +import api, { getLinks } from '../api'; + +import { importFetchedStatus, importFetchedStatuses } from './importer'; + export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; export const TIMELINE_DELETE = 'TIMELINE_DELETE'; export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'; @@ -23,7 +26,7 @@ export const MAX_QUEUED_ITEMS = 40; export function processTimelineUpdate(timeline, status, accept) { return (dispatch, getState) => { const me = getState().get('me'); - const ownStatus = status.account && status.account.id === me; + const ownStatus = status.account?.id === me; const hasPendingStatuses = !getState().get('pending_statuses').isEmpty(); const columnSettings = getSettings(getState()).get(timeline, ImmutableMap()); diff --git a/app/soapbox/api.js b/app/soapbox/api.js index 2a6b5092a..13ee07186 100644 --- a/app/soapbox/api.js +++ b/app/soapbox/api.js @@ -7,9 +7,10 @@ import axios from 'axios'; import LinkHeader from 'http-link-header'; -import { getAccessToken, getAppToken, parseBaseURL } from 'soapbox/utils/auth'; import { createSelector } from 'reselect'; + import { BACKEND_URL, FE_SUBDIRECTORY } from 'soapbox/build_config'; +import { getAccessToken, getAppToken, parseBaseURL } from 'soapbox/utils/auth'; import { isURL } from 'soapbox/utils/auth'; /** diff --git a/app/soapbox/base_polyfills.js b/app/soapbox/base_polyfills.js index d54ed977c..e4744fee3 100644 --- a/app/soapbox/base_polyfills.js +++ b/app/soapbox/base_polyfills.js @@ -4,9 +4,10 @@ import 'intl'; import 'intl/locale-data/jsonp/en'; import 'es6-symbol/implement'; import includes from 'array-includes'; +import isNaN from 'is-nan'; import assign from 'object-assign'; import values from 'object.values'; -import isNaN from 'is-nan'; + import { decode as decodeBase64 } from './utils/base64'; if (!Array.prototype.includes) { diff --git a/app/soapbox/components/__mocks__/react-inlinesvg.js b/app/soapbox/components/__mocks__/react-inlinesvg.js index 33da43fde..41000c5cc 100644 --- a/app/soapbox/components/__mocks__/react-inlinesvg.js +++ b/app/soapbox/components/__mocks__/react-inlinesvg.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; export default function InlineSVG({ src }) { return ; diff --git a/app/soapbox/components/__tests__/autosuggest_emoji-test.js b/app/soapbox/components/__tests__/autosuggest_emoji-test.js index 05616e444..9a2fb58e8 100644 --- a/app/soapbox/components/__tests__/autosuggest_emoji-test.js +++ b/app/soapbox/components/__tests__/autosuggest_emoji-test.js @@ -1,5 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; + import AutosuggestEmoji from '../autosuggest_emoji'; describe('', () => { diff --git a/app/soapbox/components/__tests__/avatar-test.js b/app/soapbox/components/__tests__/avatar-test.js index 297b0b413..3834dfbb5 100644 --- a/app/soapbox/components/__tests__/avatar-test.js +++ b/app/soapbox/components/__tests__/avatar-test.js @@ -1,6 +1,8 @@ -import React from 'react'; import { fromJS } from 'immutable'; +import React from 'react'; + import { createComponent } from 'soapbox/test_helpers'; + import Avatar from '../avatar'; describe('', () => { diff --git a/app/soapbox/components/__tests__/avatar_overlay-test.js b/app/soapbox/components/__tests__/avatar_overlay-test.js index c469dcc75..db4250c59 100644 --- a/app/soapbox/components/__tests__/avatar_overlay-test.js +++ b/app/soapbox/components/__tests__/avatar_overlay-test.js @@ -1,6 +1,8 @@ -import React from 'react'; import { fromJS } from 'immutable'; +import React from 'react'; + import { createComponent } from 'soapbox/test_helpers'; + import AvatarOverlay from '../avatar_overlay'; describe(' { diff --git a/app/soapbox/components/__tests__/badge-test.js b/app/soapbox/components/__tests__/badge-test.js index 5a42f0531..0b577dc18 100644 --- a/app/soapbox/components/__tests__/badge-test.js +++ b/app/soapbox/components/__tests__/badge-test.js @@ -1,5 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; + import Badge from '../badge'; describe('', () => { diff --git a/app/soapbox/components/__tests__/button-test.js b/app/soapbox/components/__tests__/button-test.js index 160cd3cbc..e1480fe6f 100644 --- a/app/soapbox/components/__tests__/button-test.js +++ b/app/soapbox/components/__tests__/button-test.js @@ -1,6 +1,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import renderer from 'react-test-renderer'; + import Button from '../button'; describe(' - )} + {quote} { - const { me } = this.props; + const { me, onReply, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.onReply(this.props.status, this.context.router.history); + onReply(status, this.context.router.history); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('REPLY'); } } @@ -167,22 +173,22 @@ class StatusActionBar extends ImmutablePureComponent { handleReactClick = emoji => { return e => { - const { me, status } = this.props; + const { me, dispatch, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.dispatch(simpleEmojiReact(status, emoji)); + dispatch(simpleEmojiReact(status, emoji)); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('FAVOURITE'); } this.setState({ emojiSelectorVisible: false }); }; } handleFavouriteClick = () => { - const { me } = this.props; + const { me, onFavourite, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.onFavourite(this.props.status); + onFavourite(status); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('FAVOURITE'); } } @@ -191,11 +197,20 @@ class StatusActionBar extends ImmutablePureComponent { } handleReblogClick = e => { - const { me } = this.props; + const { me, onReblog, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.onReblog(this.props.status, e); + onReblog(status, e); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('REBLOG'); + } + } + + handleQuoteClick = () => { + const { me, onQuote, onOpenUnauthorizedModal, status } = this.props; + if (me) { + onQuote(status, this.context.router.history); + } else { + onOpenUnauthorizedModal('REBLOG'); } } @@ -294,6 +309,13 @@ class StatusActionBar extends ImmutablePureComponent { this.props.onToggleStatusSensitivity(this.props.status); } + handleOpenReblogsModal = () => { + const { me, status, onOpenUnauthorizedModal, onOpenReblogsModal } = this.props; + + if (!me) onOpenUnauthorizedModal(); + else onOpenReblogsModal(status.getIn(['account', 'acct']), status.get('id')); + } + _makeMenu = (publicStatus) => { const { status, intl, withDismiss, withGroupAdmin, me, features, isStaff, isAdmin } = this.props; const mutingConversation = status.get('muted'); @@ -320,6 +342,10 @@ class StatusActionBar extends ImmutablePureComponent { // }); } + if (!me) { + return menu; + } + if (features.bookmarks) { menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), @@ -328,10 +354,6 @@ class StatusActionBar extends ImmutablePureComponent { }); } - if (!me) { - return menu; - } - menu.push(null); if (ownAccount || withDismiss) { @@ -364,11 +386,13 @@ class StatusActionBar extends ImmutablePureComponent { text: intl.formatMessage(messages.delete), action: this.handleDeleteClick, icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }); menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick, icon: require('@tabler/icons/icons/edit.svg'), + destructive: true, }); } else { menu.push({ @@ -441,11 +465,13 @@ class StatusActionBar extends ImmutablePureComponent { text: intl.formatMessage(messages.deleteUser, { name: status.getIn(['account', 'username']) }), action: this.handleDeleteUser, icon: require('@tabler/icons/icons/user-minus.svg'), + destructive: true, }); menu.push({ text: intl.formatMessage(messages.deleteStatus), action: this.handleDeleteStatus, icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }); } } @@ -456,11 +482,13 @@ class StatusActionBar extends ImmutablePureComponent { text: intl.formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount, icon: require('@tabler/icons/icons/user-x.svg'), + destructive: true, }); menu.push({ text: intl.formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost, icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }); } @@ -479,7 +507,7 @@ class StatusActionBar extends ImmutablePureComponent { } render() { - const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features } = this.props; + const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features, me } = this.props; const { emojiSelectorVisible } = this.state; const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); @@ -513,6 +541,48 @@ class StatusActionBar extends ImmutablePureComponent { reblogIcon = require('@tabler/icons/icons/lock.svg'); } + let reblogButton; + + if (me && features.quotePosts) { + const reblogMenu = [ + { + text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog), + action: this.handleReblogClick, + icon: require('@tabler/icons/icons/repeat.svg'), + }, + { + text: intl.formatMessage(messages.quotePost), + action: this.handleQuoteClick, + icon: require('@tabler/icons/icons/quote.svg'), + }, + ]; + + reblogButton = ( + + ); + } else { + reblogButton = ( + + ); + } + if (status.get('in_reply_to_id', null) === null) { replyTitle = intl.formatMessage(messages.reply); } else { @@ -536,9 +606,9 @@ class StatusActionBar extends ImmutablePureComponent { {replyCount !== 0 && {replyCount}} -

- - {reblogCount !== 0 && {reblogCount}} +
+ {reblogButton} + {reblogCount !== 0 && {reblogCount}}
{ }; }; -const mapDispatchToProps = (dispatch) => ({ +const mapDispatchToProps = (dispatch, { status }) => ({ dispatch, - onOpenUnauthorizedModal() { - dispatch(openModal('UNAUTHORIZED')); + onOpenUnauthorizedModal(action) { + dispatch(openModal('UNAUTHORIZED', { + action, + ap_id: status.get('url'), + })); + }, + onOpenReblogsModal(username, statusId) { + dispatch(openModal('REBLOGS', { + username, + statusId, + })); }, }); diff --git a/app/soapbox/components/status_content.js b/app/soapbox/components/status_content.js index 508e2de1f..717071a5c 100644 --- a/app/soapbox/components/status_content.js +++ b/app/soapbox/components/status_content.js @@ -1,17 +1,20 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { isRtl } from '../rtl'; -import { FormattedMessage } from 'react-intl'; -import Permalink from './permalink'; import classnames from 'classnames'; -import PollContainer from 'soapbox/containers/poll_container'; -import Icon from 'soapbox/components/icon'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import Icon from 'soapbox/components/icon'; +import PollContainer from 'soapbox/containers/poll_container'; import { addGreentext } from 'soapbox/utils/greentext'; import { onlyEmoji } from 'soapbox/utils/rich_content'; +import { isRtl } from '../rtl'; + +import Permalink from './permalink'; + const MAX_HEIGHT = 642; // 20px * 32 (+ 2px padding at the top) const BIG_EMOJI_LIMIT = 10; @@ -242,7 +245,7 @@ class StatusContent extends React.PureComponent {
- {!hidden && !!status.get('poll') && } + {!hidden && !!status.get('poll') && }
); } else if (this.props.onClick) { @@ -265,7 +268,7 @@ class StatusContent extends React.PureComponent { } if (status.get('poll')) { - output.push(); + output.push(); } return output; @@ -285,7 +288,7 @@ class StatusContent extends React.PureComponent { ]; if (status.get('poll')) { - output.push(); + output.push(); } return output; diff --git a/app/soapbox/components/status_list.js b/app/soapbox/components/status_list.js index a186a8073..9fc51242b 100644 --- a/app/soapbox/components/status_list.js +++ b/app/soapbox/components/status_list.js @@ -1,15 +1,17 @@ import { debounce } from 'lodash'; -import React from 'react'; -import { FormattedMessage, defineMessages } from 'react-intl'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import MaterialStatus from 'soapbox/components/material_status'; -import PendingStatus from 'soapbox/features/ui/components/pending_status'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage, defineMessages } from 'react-intl'; + +import MaterialStatus from 'soapbox/components/material_status'; +import PlaceholderMaterialStatus from 'soapbox/features/placeholder/components/placeholder_material_status'; +import PendingStatus from 'soapbox/features/ui/components/pending_status'; + import LoadGap from './load_gap'; import ScrollableList from './scrollable_list'; import TimelineQueueButtonHeader from './timeline_queue_button_header'; -import PlaceholderMaterialStatus from 'soapbox/features/placeholder/components/placeholder_material_status'; const messages = defineMessages({ queue: { id: 'status_list.queue_label', defaultMessage: 'Click to see {count} new {count, plural, one {post} other {posts}}' }, @@ -118,7 +120,6 @@ export default class StatusList extends ImmutablePureComponent { contextType={timelineId} group={group} withGroupAdmin={withGroupAdmin} - showThread /> ); } @@ -138,7 +139,6 @@ export default class StatusList extends ImmutablePureComponent { contextType={timelineId} group={group} withGroupAdmin={withGroupAdmin} - showThread />
@@ -157,7 +157,6 @@ export default class StatusList extends ImmutablePureComponent { onMoveUp={this.handleMoveUp} onMoveDown={this.handleMoveDown} contextType={timelineId} - showThread /> )); } diff --git a/app/soapbox/components/status_reply_mentions.js b/app/soapbox/components/status_reply_mentions.js new file mode 100644 index 000000000..11664bb31 --- /dev/null +++ b/app/soapbox/components/status_reply_mentions.js @@ -0,0 +1,103 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { openModal } from 'soapbox/actions/modals'; +import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; + +const mapDispatchToProps = (dispatch) => ({ + onOpenMentionsModal(username, statusId) { + dispatch(openModal('MENTIONS', { + username, + statusId, + })); + }, +}); + +export default @connect(null, mapDispatchToProps) +@injectIntl +class StatusReplyMentions extends ImmutablePureComponent { + + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + onOpenMentionsModal: PropTypes.func, + } + + handleOpenMentionsModal = () => { + const { status, onOpenMentionsModal } = this.props; + + onOpenMentionsModal(status.getIn(['account', 'acct']), status.get('id')); + } + + render() { + const { status } = this.props; + + if (!status.get('in_reply_to_id')) { + return null; + } + + const to = status.get('mentions', []); + + // The post is a reply, but it has no mentions. + if (to.size === 0) { + // The author is replying to themself. + if (status.get('in_reply_to_account_id') === status.getIn(['account', 'id'])) { + return ( +
+ + + @{status.getIn(['account', 'username'])} + + ), + more: false, + }} + /> +
+ ); + } else { + // The reply-to is unknown. Rare, but it can happen. + return ( +
+ +
+ ); + } + } + + + // The typical case with a reply-to and a list of mentions. + return ( +
+ (<> + + @{account.get('username')} + + {' '} + )), + more: to.size > 2 && ( + + + + ), + }} + /> +
+ ); + } + +} diff --git a/app/soapbox/components/still_image.js b/app/soapbox/components/still_image.js index 18b3d9fb0..1773fc0c3 100644 --- a/app/soapbox/components/still_image.js +++ b/app/soapbox/components/still_image.js @@ -1,8 +1,9 @@ +import classNames from 'classnames'; +import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; + import { getSettings } from 'soapbox/actions/settings'; -import classNames from 'classnames'; const mapStateToProps = state => ({ autoPlayGif: getSettings(state).get('autoPlayGif'), diff --git a/app/soapbox/components/sub_navigation.js b/app/soapbox/components/sub_navigation.js index 063448b5c..0f9092760 100644 --- a/app/soapbox/components/sub_navigation.js +++ b/app/soapbox/components/sub_navigation.js @@ -1,13 +1,14 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { injectIntl, defineMessages } from 'react-intl'; +import classNames from 'classnames'; import { throttle } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { openModal } from 'soapbox/actions/modals'; +import Helmet from 'soapbox/components/helmet'; import Icon from 'soapbox/components/icon'; import IconButton from 'soapbox/components/icon_button'; -import classNames from 'classnames'; -import Helmet from 'soapbox/components/helmet'; -import { openModal } from 'soapbox/actions/modal'; const messages = defineMessages({ back: { id: 'column_back_button.label', defaultMessage: 'Back' }, diff --git a/app/soapbox/components/svg_icon.js b/app/soapbox/components/svg_icon.js index c0baca595..ded55c50d 100644 --- a/app/soapbox/components/svg_icon.js +++ b/app/soapbox/components/svg_icon.js @@ -4,9 +4,9 @@ * @see soapbox/components/icon */ -import React from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; import InlineSVG from 'react-inlinesvg'; export default class SvgIcon extends React.PureComponent { @@ -17,10 +17,13 @@ export default class SvgIcon extends React.PureComponent { }; render() { - const { src, className } = this.props; + const { src, className, ...other } = this.props; return ( -
+
); diff --git a/app/soapbox/components/thumb_navigation.js b/app/soapbox/components/thumb_navigation.js index 06b27161d..7234a39b0 100644 --- a/app/soapbox/components/thumb_navigation.js +++ b/app/soapbox/components/thumb_navigation.js @@ -1,15 +1,16 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { NavLink, withRouter } from 'react-router-dom'; import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { NavLink, withRouter } from 'react-router-dom'; + +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import Icon from 'soapbox/components/icon'; import IconWithCounter from 'soapbox/components/icon_with_counter'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { isStaff } from 'soapbox/utils/accounts'; import { getFeatures } from 'soapbox/utils/features'; -import classNames from 'classnames'; const mapStateToProps = state => { const me = state.get('me'); @@ -21,7 +22,7 @@ const mapStateToProps = state => { account: state.getIn(['accounts', me]), logo: getSoapboxConfig(state).get('logo'), notificationCount: state.getIn(['notifications', 'unread']), - chatsCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0), + chatsCount: state.getIn(['chats', 'items']).reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0), dashboardCount: reportsCount + approvalCount, features: getFeatures(instance), }; diff --git a/app/soapbox/components/timeline_queue_button_header.js b/app/soapbox/components/timeline_queue_button_header.js index 8328d3292..1fa9cbadf 100644 --- a/app/soapbox/components/timeline_queue_button_header.js +++ b/app/soapbox/components/timeline_queue_button_header.js @@ -1,11 +1,12 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { injectIntl } from 'react-intl'; -import { throttle } from 'lodash'; import classNames from 'classnames'; -import Icon from 'soapbox/components/icon'; +import { throttle } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; +import Icon from 'soapbox/components/icon'; const mapStateToProps = state => { const settings = getSettings(state); diff --git a/app/soapbox/containers/account_container.js b/app/soapbox/containers/account_container.js index 1e890a7e2..78abcdea8 100644 --- a/app/soapbox/containers/account_container.js +++ b/app/soapbox/containers/account_container.js @@ -1,8 +1,7 @@ import React from 'react'; -import { connect } from 'react-redux'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { makeGetAccount } from '../selectors'; -import Account from '../components/account'; +import { connect } from 'react-redux'; + import { followAccount, unfollowAccount, @@ -11,9 +10,11 @@ import { muteAccount, unmuteAccount, } from '../actions/accounts'; -import { openModal } from '../actions/modal'; +import { openModal } from '../actions/modals'; import { initMuteModal } from '../actions/mutes'; import { getSettings } from '../actions/settings'; +import Account from '../components/account'; +import { makeGetAccount } from '../selectors'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, @@ -37,6 +38,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { if (unfollowModal) { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/minus.svg'), + heading: @{account.get('acct')}
}} />, message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.unfollowConfirm), onConfirm: () => dispatch(unfollowAccount(account.get('id'))), diff --git a/app/soapbox/containers/domain_container.js b/app/soapbox/containers/domain_container.js index 7a472c17c..a1d705eaf 100644 --- a/app/soapbox/containers/domain_container.js +++ b/app/soapbox/containers/domain_container.js @@ -1,9 +1,10 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { blockDomain, unblockDomain } from '../actions/domain_blocks'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { blockDomain, unblockDomain } from '../actions/domain_blocks'; +import { openModal } from '../actions/modals'; import Domain from '../components/domain'; -import { openModal } from '../actions/modal'; const messages = defineMessages({ blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, @@ -18,6 +19,8 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onBlockDomain(domain) { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , message: {domain} }} />, confirm: intl.formatMessage(messages.blockDomainConfirm), onConfirm: () => dispatch(blockDomain(domain)), diff --git a/app/soapbox/containers/dropdown_menu_container.js b/app/soapbox/containers/dropdown_menu_container.js index f79b19202..b4101c2d2 100644 --- a/app/soapbox/containers/dropdown_menu_container.js +++ b/app/soapbox/containers/dropdown_menu_container.js @@ -1,11 +1,12 @@ -import { openDropdownMenu, closeDropdownMenu } from '../actions/dropdown_menu'; -import { openModal, closeModal } from '../actions/modal'; import { connect } from 'react-redux'; + +import { openDropdownMenu, closeDropdownMenu } from '../actions/dropdown_menu'; +import { openModal, closeModal } from '../actions/modals'; import DropdownMenu from '../components/dropdown_menu'; import { isUserTouching } from '../is_mobile'; const mapStateToProps = state => ({ - isModalOpen: state.get('modal').modalType === 'ACTIONS', + isModalOpen: state.get('modals').size && state.get('modals').last().modalType === 'ACTIONS', dropdownPlacement: state.getIn(['dropdown_menu', 'placement']), openDropdownId: state.getIn(['dropdown_menu', 'openId']), openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']), diff --git a/app/soapbox/containers/intersection_observer_article_container.js b/app/soapbox/containers/intersection_observer_article_container.js index 6ff5d5817..a112069c6 100644 --- a/app/soapbox/containers/intersection_observer_article_container.js +++ b/app/soapbox/containers/intersection_observer_article_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; -import IntersectionObserverArticle from '../components/intersection_observer_article'; + import { setHeight } from '../actions/height_cache'; +import IntersectionObserverArticle from '../components/intersection_observer_article'; const makeMapStateToProps = (state, props) => ({ cachedHeight: state.getIn(['height_cache', props.saveHeightKey, props.id]), diff --git a/app/soapbox/containers/poll_container.js b/app/soapbox/containers/poll_container.js index 55f14e1b2..50d21517a 100644 --- a/app/soapbox/containers/poll_container.js +++ b/app/soapbox/containers/poll_container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { openModal } from 'soapbox/actions/modal'; + import Poll from 'soapbox/components/poll'; const mapStateToProps = (state, { pollId }) => ({ @@ -7,10 +7,5 @@ const mapStateToProps = (state, { pollId }) => ({ me: state.get('me'), }); -const mapDispatchToProps = (dispatch) => ({ - onOpenUnauthorizedModal() { - dispatch(openModal('UNAUTHORIZED')); - }, -}); -export default connect(mapStateToProps, mapDispatchToProps)(Poll); +export default connect(mapStateToProps)(Poll); diff --git a/app/soapbox/containers/soapbox.js b/app/soapbox/containers/soapbox.js index c011d0f0d..301de4c01 100644 --- a/app/soapbox/containers/soapbox.js +++ b/app/soapbox/containers/soapbox.js @@ -1,36 +1,43 @@ 'use strict'; -import React from 'react'; -import { Provider, connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import Helmet from 'soapbox/components/helmet'; import classNames from 'classnames'; -import configureStore from '../store/configureStore'; -import { INTRODUCTION_VERSION } from '../actions/onboarding'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { IntlProvider } from 'react-intl'; +import { Provider, connect } from 'react-redux'; import { Switch, BrowserRouter, Route } from 'react-router-dom'; import { ScrollContext } from 'react-router-scroll-4'; -import UI from '../features/ui'; + // import Introduction from '../features/introduction'; -import { preload } from '../actions/preload'; -import { IntlProvider } from 'react-intl'; -import ErrorBoundary from '../components/error_boundary'; import { loadInstance } from 'soapbox/actions/instance'; -import { fetchSoapboxConfig } from 'soapbox/actions/soapbox'; import { fetchMe } from 'soapbox/actions/me'; -import PublicLayout from 'soapbox/features/public_layout'; import { getSettings } from 'soapbox/actions/settings'; +import { loadSoapboxConfig } from 'soapbox/actions/soapbox'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; -import { generateThemeCss } from 'soapbox/utils/theme'; -import messages from 'soapbox/locales/messages'; import { FE_SUBDIRECTORY } from 'soapbox/build_config'; +import Helmet from 'soapbox/components/helmet'; +import PublicLayout from 'soapbox/features/public_layout'; import { createGlobals } from 'soapbox/globals'; +import messages from 'soapbox/locales/messages'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; +import { generateThemeCss } from 'soapbox/utils/theme'; + +import { INTRODUCTION_VERSION } from '../actions/onboarding'; +import { preload } from '../actions/preload'; +import ErrorBoundary from '../components/error_boundary'; +import UI from '../features/ui'; +import configureStore from '../store/configureStore'; const validLocale = locale => Object.keys(messages).includes(locale); -const previewMediaState = 'previewMediaModal'; -const previewVideoState = 'previewVideoModal'; +// Delay rendering until instance has loaded or failed (for feature detection) +const isInstanceLoaded = state => { + const v = state.getIn(['instance', 'version'], '0.0.0'); + const fetchFailed = state.getIn(['meta', 'instance_fetch_failed'], false); + + return v !== '0.0.0' || fetchFailed; +}; export const store = configureStore(); @@ -43,7 +50,7 @@ store.dispatch(fetchMe()) .then(() => { // Postpone for authenticated fetch store.dispatch(loadInstance()); - store.dispatch(fetchSoapboxConfig()); + store.dispatch(loadSoapboxConfig()); }) .catch(() => {}); @@ -55,20 +62,24 @@ const mapStateToProps = (state) => { const soapboxConfig = getSoapboxConfig(state); const locale = settings.get('locale'); + // In demo mode, force the default brand color + const brandColor = settings.get('demo') ? '#0482d8' : soapboxConfig.get('brandColor'); + return { showIntroduction, me, + instanceLoaded: isInstanceLoaded(state), reduceMotion: settings.get('reduceMotion'), underlineLinks: settings.get('underlineLinks'), systemFont: settings.get('systemFont'), dyslexicFont: settings.get('dyslexicFont'), demetricator: settings.get('demetricator'), locale: validLocale(locale) ? locale : 'en', - themeCss: generateThemeCss(soapboxConfig.get('brandColor')), + themeCss: generateThemeCss(brandColor), brandColor: soapboxConfig.get('brandColor'), themeMode: settings.get('themeMode'), halloween: settings.get('halloween'), - customCss: soapboxConfig.get('customCss'), + customCss: settings.get('demo') ? null : soapboxConfig.get('customCss'), }; }; @@ -78,6 +89,7 @@ class SoapboxMount extends React.PureComponent { static propTypes = { showIntroduction: PropTypes.bool, me: SoapboxPropTypes.me, + instanceLoaded: PropTypes.bool, reduceMotion: PropTypes.bool, underlineLinks: PropTypes.bool, systemFont: PropTypes.bool, @@ -117,13 +129,14 @@ class SoapboxMount extends React.PureComponent { this.maybeUpdateMessages(prevProps); } - shouldUpdateScroll(_, { location }) { - return location.state !== previewMediaState && location.state !== previewVideoState; + shouldUpdateScroll(prevRouterProps, { location }) { + return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prevRouterProps?.location?.state?.soapboxModalKey); } render() { - const { me, themeCss, locale, customCss } = this.props; + const { me, instanceLoaded, themeCss, locale, customCss } = this.props; if (me === null) return null; + if (!instanceLoaded) return null; if (this.state.localeLoading) return null; // Disabling introduction for launch diff --git a/app/soapbox/containers/status_container.js b/app/soapbox/containers/status_container.js index 95c59b4b2..e671dab56 100644 --- a/app/soapbox/containers/status_container.js +++ b/app/soapbox/containers/status_container.js @@ -1,12 +1,23 @@ import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import Status from '../components/status'; -import { makeGetStatus } from '../selectors'; + +import { launchChat } from 'soapbox/actions/chats'; +import { deactivateUserModal, deleteUserModal, deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; + +import { blockAccount } from '../actions/accounts'; +import { showAlertForError } from '../actions/alerts'; import { replyCompose, mentionCompose, directCompose, + quoteCompose, } from '../actions/compose'; +import { + createRemovedAccount, + groupRemoveStatus, +} from '../actions/groups'; import { reblog, favourite, @@ -17,7 +28,10 @@ import { pin, unpin, } from '../actions/interactions'; -import { blockAccount } from '../actions/accounts'; +import { openModal } from '../actions/modals'; +import { initMuteModal } from '../actions/mutes'; +import { initReport } from '../actions/reports'; +import { getSettings } from '../actions/settings'; import { muteStatus, unmuteStatus, @@ -25,27 +39,18 @@ import { hideStatus, revealStatus, } from '../actions/statuses'; -import { initMuteModal } from '../actions/mutes'; -import { initReport } from '../actions/reports'; -import { openModal } from '../actions/modal'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { showAlertForError } from '../actions/alerts'; -import { - createRemovedAccount, - groupRemoveStatus, -} from '../actions/groups'; -import { getSettings } from '../actions/settings'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; -import { deactivateUserModal, deleteUserModal, deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; -import { launchChat } from 'soapbox/actions/chats'; +import Status from '../components/status'; +import { makeGetStatus } from '../selectors'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, + deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' }, redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, + redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' }, }); @@ -66,174 +71,195 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -const mapDispatchToProps = (dispatch, { intl }) => ({ - - onReply(status, router) { - dispatch((_, getState) => { - const state = getState(); - if (state.getIn(['compose', 'text']).trim().length !== 0) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: () => dispatch(replyCompose(status, router)), - })); - } else { - dispatch(replyCompose(status, router)); - } - }); - }, - - onModalReblog(status) { +const mapDispatchToProps = (dispatch, { intl }) => { + function onModalReblog(status) { if (status.get('reblogged')) { dispatch(unreblog(status)); } else { dispatch(reblog(status)); } - }, + } - onReblog(status, e) { - dispatch((_, getState) => { - const boostModal = getSettings(getState()).get('boostModal'); - if (e.shiftKey || !boostModal) { - this.onModalReblog(status); + return { + onReply(status, router) { + dispatch((_, getState) => { + const state = getState(); + if (state.getIn(['compose', 'text']).trim().length !== 0) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(replyCompose(status, router)), + })); + } else { + dispatch(replyCompose(status, router)); + } + }); + }, + + onModalReblog, + + onReblog(status, e) { + dispatch((_, getState) => { + const boostModal = getSettings(getState()).get('boostModal'); + if ((e && e.shiftKey) || !boostModal) { + onModalReblog(status); + } else { + dispatch(openModal('BOOST', { status, onReblog: onModalReblog })); + } + }); + }, + + onQuote(status, router) { + dispatch((_, getState) => { + const state = getState(); + if (state.getIn(['compose', 'text']).trim().length !== 0) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(quoteCompose(status, router)), + })); + } else { + dispatch(quoteCompose(status, router)); + } + }); + }, + + onFavourite(status) { + if (status.get('favourited')) { + dispatch(unfavourite(status)); } else { - dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog })); + dispatch(favourite(status)); } - }); - }, + }, - onFavourite(status) { - if (status.get('favourited')) { - dispatch(unfavourite(status)); - } else { - dispatch(favourite(status)); - } - }, - - onBookmark(status) { - if (status.get('bookmarked')) { - dispatch(unbookmark(intl, status)); - } else { - dispatch(bookmark(intl, status)); - } - }, - - onPin(status) { - if (status.get('pinned')) { - dispatch(unpin(status)); - } else { - dispatch(pin(status)); - } - }, - - onEmbed(status) { - dispatch(openModal('EMBED', { - url: status.get('url'), - onError: error => dispatch(showAlertForError(error)), - })); - }, - - onDelete(status, history, withRedraft = false) { - dispatch((_, getState) => { - const deleteModal = getSettings(getState()).get('deleteModal'); - if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), history, withRedraft)); + onBookmark(status) { + if (status.get('bookmarked')) { + dispatch(unbookmark(status)); } else { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), - confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), - })); + dispatch(bookmark(status)); } - }); - }, + }, - onDirect(account, router) { - dispatch(directCompose(account, router)); - }, + onPin(status) { + if (status.get('pinned')) { + dispatch(unpin(status)); + } else { + dispatch(pin(status)); + } + }, - onChat(account, router) { - dispatch(launchChat(account.get('id'), router)); - }, + onEmbed(status) { + dispatch(openModal('EMBED', { + url: status.get('url'), + onError: error => dispatch(showAlertForError(error)), + })); + }, - onMention(account, router) { - dispatch(mentionCompose(account, router)); - }, + onDelete(status, history, withRedraft = false) { + dispatch((_, getState) => { + const deleteModal = getSettings(getState()).get('deleteModal'); + if (!deleteModal) { + dispatch(deleteStatus(status.get('id'), history, withRedraft)); + } else { + dispatch(openModal('CONFIRM', { + icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'), + heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading), + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + })); + } + }); + }, - onOpenMedia(media, index) { - dispatch(openModal('MEDIA', { media, index })); - }, + onDirect(account, router) { + dispatch(directCompose(account, router)); + }, - onOpenVideo(media, time) { - dispatch(openModal('VIDEO', { media, time })); - }, + onChat(account, router) { + dispatch(launchChat(account.get('id'), router)); + }, - onOpenAudio(media, time) { - dispatch(openModal('AUDIO', { media, time })); - }, + onMention(account, router) { + dispatch(mentionCompose(account, router)); + }, - onBlock(status) { - const account = status.get('account'); - dispatch(openModal('CONFIRM', { - message: @{account.get('acct')} }} />, - confirm: intl.formatMessage(messages.blockConfirm), - onConfirm: () => dispatch(blockAccount(account.get('id'))), - secondary: intl.formatMessage(messages.blockAndReport), - onSecondary: () => { - dispatch(blockAccount(account.get('id'))); - dispatch(initReport(account, status)); - }, - })); - }, + onOpenMedia(media, index) { + dispatch(openModal('MEDIA', { media, index })); + }, - onReport(status) { - dispatch(initReport(status.get('account'), status)); - }, + onOpenVideo(media, time) { + dispatch(openModal('VIDEO', { media, time })); + }, - onMute(account) { - dispatch(initMuteModal(account)); - }, + onOpenAudio(media, time) { + dispatch(openModal('AUDIO', { media, time })); + }, - onMuteConversation(status) { - if (status.get('muted')) { - dispatch(unmuteStatus(status.get('id'))); - } else { - dispatch(muteStatus(status.get('id'))); - } - }, + onBlock(status) { + const account = status.get('account'); + dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , + message: @{account.get('acct')} }} />, + confirm: intl.formatMessage(messages.blockConfirm), + onConfirm: () => dispatch(blockAccount(account.get('id'))), + secondary: intl.formatMessage(messages.blockAndReport), + onSecondary: () => { + dispatch(blockAccount(account.get('id'))); + dispatch(initReport(account, status)); + }, + })); + }, - onToggleHidden(status) { - if (status.get('hidden')) { - dispatch(revealStatus(status.get('id'))); - } else { - dispatch(hideStatus(status.get('id'))); - } - }, + onReport(status) { + dispatch(initReport(status.get('account'), status)); + }, - onGroupRemoveAccount(groupId, accountId) { - dispatch(createRemovedAccount(groupId, accountId)); - }, + onMute(account) { + dispatch(initMuteModal(account)); + }, - onGroupRemoveStatus(groupId, statusId) { - dispatch(groupRemoveStatus(groupId, statusId)); - }, + onMuteConversation(status) { + if (status.get('muted')) { + dispatch(unmuteStatus(status.get('id'))); + } else { + dispatch(muteStatus(status.get('id'))); + } + }, - onDeactivateUser(status) { - dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']))); - }, + onToggleHidden(status) { + if (status.get('hidden')) { + dispatch(revealStatus(status.get('id'))); + } else { + dispatch(hideStatus(status.get('id'))); + } + }, - onDeleteUser(status) { - dispatch(deleteUserModal(intl, status.getIn(['account', 'id']))); - }, + onGroupRemoveAccount(groupId, accountId) { + dispatch(createRemovedAccount(groupId, accountId)); + }, - onDeleteStatus(status) { - dispatch(deleteStatusModal(intl, status.get('id'))); - }, + onGroupRemoveStatus(groupId, statusId) { + dispatch(groupRemoveStatus(groupId, statusId)); + }, - onToggleStatusSensitivity(status) { - dispatch(toggleStatusSensitivityModal(intl, status.get('id'), status.get('sensitive'))); - }, + onDeactivateUser(status) { + dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']))); + }, -}); + onDeleteUser(status) { + dispatch(deleteUserModal(intl, status.getIn(['account', 'id']))); + }, + + onDeleteStatus(status) { + dispatch(deleteStatusModal(intl, status.get('id'))); + }, + + onToggleStatusSensitivity(status) { + dispatch(toggleStatusSensitivityModal(intl, status.get('id'), status.get('sensitive'))); + }, + }; +}; export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status)); diff --git a/app/soapbox/features/about/index.js b/app/soapbox/features/about/index.js index 8310eb491..bb6f1222c 100644 --- a/app/soapbox/features/about/index.js +++ b/app/soapbox/features/about/index.js @@ -1,10 +1,12 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchAboutPage } from 'soapbox/actions/about'; import { getSettings } from 'soapbox/actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; + import { languages } from '../preferences'; const mapStateToProps = state => ({ diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index 949b3801f..884d57034 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -1,12 +1,28 @@ 'use strict'; -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; +import classNames from 'classnames'; +import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; +import { debounce, throttle } from 'lodash'; import PropTypes from 'prop-types'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import IconButton from 'soapbox/components/icon_button'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { NavLink } from 'react-router-dom'; + +import { openModal } from 'soapbox/actions/modals'; +import Avatar from 'soapbox/components/avatar'; +import Badge from 'soapbox/components/badge'; +import Icon from 'soapbox/components/icon'; +import IconButton from 'soapbox/components/icon_button'; +import StillImage from 'soapbox/components/still_image'; +import VerificationBadge from 'soapbox/components/verification_badge'; +import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; +import ActionButton from 'soapbox/features/ui/components/action_button'; +import SubscriptionButton from 'soapbox/features/ui/components/subscription_button'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { ProfileInfoPanel } from 'soapbox/features/ui/util/async-components'; import { isStaff, isAdmin, @@ -16,20 +32,10 @@ import { isRemote, getDomain, } from 'soapbox/utils/accounts'; -import classNames from 'classnames'; -import Avatar from 'soapbox/components/avatar'; -import { shortNumberFormat } from 'soapbox/utils/numbers'; -import { NavLink } from 'react-router-dom'; -import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { ProfileInfoPanel } from 'soapbox/features/ui/util/async-components'; -import { debounce } from 'lodash'; -import StillImage from 'soapbox/components/still_image'; -import ActionButton from 'soapbox/features/ui/components/action_button'; -import SubscriptionButton from 'soapbox/features/ui/components/subscription_button'; -import { openModal } from 'soapbox/actions/modal'; -import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; +import { getAcct } from 'soapbox/utils/accounts'; import { getFeatures } from 'soapbox/utils/features'; +import { shortNumberFormat } from 'soapbox/utils/numbers'; +import { displayFqn } from 'soapbox/utils/state'; const messages = defineMessages({ edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, @@ -68,6 +74,10 @@ const messages = defineMessages({ demoteToUser: { id: 'admin.users.actions.demote_to_user', defaultMessage: 'Demote @{name} to a regular user' }, subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' }, unsubscribe: { id: 'account.unsubscribe', defaultMessage: 'Unsubscribe to notifications from @{name}' }, + suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' }, + unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' }, + deactivated: { id: 'account.deactivated', defaultMessage: 'Deactivated' }, + bot: { id: 'account.badges.bot', defaultMessage: 'Bot' }, }); const mapStateToProps = state => { @@ -80,6 +90,8 @@ const mapStateToProps = state => { me, meAccount: account, features, + displayFqn: displayFqn(state), + }; }; @@ -94,10 +106,12 @@ class Header extends ImmutablePureComponent { intl: PropTypes.object.isRequired, username: PropTypes.string, features: PropTypes.object, + displayFqn: PropTypes.bool, }; state = { isSmallScreen: (window.innerWidth <= 895), + isLocked: false, } isStatusesPageActive = (match, location) => { @@ -109,19 +123,34 @@ class Header extends ImmutablePureComponent { } componentDidMount() { + window.addEventListener('scroll', this.handleScroll); window.addEventListener('resize', this.handleResize, { passive: true }); } componentWillUnmount() { + window.removeEventListener('scroll', this.handleScroll); window.removeEventListener('resize', this.handleResize); } + setRef = (c) => { + this.node = c; + } + handleResize = debounce(() => { this.setState({ isSmallScreen: (window.innerWidth <= 895) }); }, 5, { trailing: true, }); + handleScroll = throttle(() => { + const { top } = this.node.getBoundingClientRect(); + const isLocked = top <= 60; + + if (this.state.isLocked !== isLocked) { + this.setState({ isLocked }); + } + }, 100, { trailing: true }); + onAvatarClick = () => { const avatar_url = this.props.account.get('avatar'); const avatar = ImmutableMap({ @@ -180,7 +209,7 @@ class Header extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare, - icon: require('@tabler/icons/icons/share.svg'), + icon: require('feather-icons/dist/icons/share.svg'), }); menu.push(null); } @@ -235,7 +264,7 @@ class Header extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect, - icon:require('@tabler/icons/icons/mail.svg'), + icon: require('@tabler/icons/icons/mail.svg'), }); } @@ -254,7 +283,21 @@ class Header extends ImmutablePureComponent { }); } - if (features.accountSubscriptions) { + if (features.accountNotifies) { + if (account.getIn(['relationship', 'notifying'])) { + menu.push({ + text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }), + action: this.props.onNotifyToggle, + icon: require('@tabler/icons/icons/bell.svg'), + }); + } else { + menu.push({ + text: intl.formatMessage(messages.subscribe, { name: account.get('username') }), + action: this.props.onNotifyToggle, + icon: require('@tabler/icons/icons/bell-off.svg'), + }); + } + } else if (features.accountSubscriptions) { if (account.getIn(['relationship', 'subscribing'])) { menu.push({ text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }), @@ -278,7 +321,14 @@ class Header extends ImmutablePureComponent { }); } - // menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + if (features.accountEndorsements) { + menu.push({ + text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), + action: this.props.onEndorseToggle, + icon: require('@tabler/icons/icons/user-check.svg'), + }); + } + menu.push(null); } else if (features.lists && features.unrestrictedLists) { menu.push({ @@ -354,7 +404,7 @@ class Header extends ImmutablePureComponent { }); } - if (account.get('id') !== me && isLocal(account)) { + if (account.get('id') !== me && isLocal(account) && isAdmin(meAccount)) { if (isAdmin(account)) { menu.push({ text: intl.formatMessage(messages.demoteToModerator, { name: account.get('username') }), @@ -405,6 +455,22 @@ class Header extends ImmutablePureComponent { }); } + if (features.suggestionsV2 && isAdmin(meAccount)) { + if (account.getIn(['pleroma', 'is_suggested'])) { + menu.push({ + text: intl.formatMessage(messages.unsuggestUser, { name: account.get('username') }), + action: this.props.onUnsuggestUser, + icon: require('@tabler/icons/icons/user-x.svg'), + }); + } else { + menu.push({ + text: intl.formatMessage(messages.suggestUser, { name: account.get('username') }), + action: this.props.onSuggestUser, + icon: require('@tabler/icons/icons/user-check.svg'), + }); + } + } + if (account.get('id') !== me) { menu.push({ text: intl.formatMessage(messages.deactivateUser, { name: account.get('username') }), @@ -413,6 +479,7 @@ class Header extends ImmutablePureComponent { }); menu.push({ text: intl.formatMessage(messages.deleteUser, { name: account.get('username') }), + action: this.props.onDeleteUser, icon: require('@tabler/icons/icons/user-minus.svg'), }); } @@ -471,17 +538,36 @@ class Header extends ImmutablePureComponent { } } + renderShareButton() { + const { intl, account, me } = this.props; + const canShare = 'share' in navigator; + + if (!(account && me && account.get('id') === me && canShare)) { + return null; + } + + return ( + + ); + } + render() { - const { account, intl, username, me, features } = this.props; - const { isSmallScreen } = this.state; + const { account, displayFqn, intl, username, me, features } = this.props; + const { isSmallScreen, isLocked } = this.state; if (!account) { return (
-
+
-
+
+
+
{isSmallScreen && (
@@ -504,6 +590,9 @@ class Header extends ImmutablePureComponent { const avatarSize = isSmallScreen ? 90 : 200; const deactivated = !account.getIn(['pleroma', 'is_active'], true); + const displayNameHtml = deactivated ? { __html: intl.formatMessage(messages.deactivated) } : { __html: account.get('display_name_html') }; + const verified = account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified'); + return (
@@ -515,17 +604,33 @@ class Header extends ImmutablePureComponent { } - {features.accountSubscriptions &&
- + {(features.accountNotifies || features.accountSubscriptions) &&
+
}
-
+
- - - +
+ + + +
+ +
+ + {verified && } + {account.get('bot') && } + + @{getAcct(account, displayFqn)} + {account.get('locked') && ( + + )} + +
+
+
@@ -571,6 +676,7 @@ class Header extends ImmutablePureComponent {
{me && } + {this.renderShareButton()} {this.renderMessageButton()}
diff --git a/app/soapbox/features/account_gallery/components/media_item.js b/app/soapbox/features/account_gallery/components/media_item.js index 98b0b7059..1cccfe070 100644 --- a/app/soapbox/features/account_gallery/components/media_item.js +++ b/app/soapbox/features/account_gallery/components/media_item.js @@ -1,14 +1,15 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Icon from 'soapbox/components/icon'; -import classNames from 'classnames'; -import Blurhash from 'soapbox/components/blurhash'; -import { isIOS } from 'soapbox/is_mobile'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; +import Blurhash from 'soapbox/components/blurhash'; +import Icon from 'soapbox/components/icon'; import StillImage from 'soapbox/components/still_image'; +import { isIOS } from 'soapbox/is_mobile'; const mapStateToProps = state => ({ autoPlayGif: getSettings(state).get('autoPlayGif'), diff --git a/app/soapbox/features/account_gallery/index.js b/app/soapbox/features/account_gallery/index.js index 843f83e4d..4f0bafecb 100644 --- a/app/soapbox/features/account_gallery/index.js +++ b/app/soapbox/features/account_gallery/index.js @@ -1,27 +1,33 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { NavLink } from 'react-router-dom'; + import { fetchAccount, fetchAccountByUsername, } from 'soapbox/actions/accounts'; -import { expandAccountMediaTimeline } from '../../actions/timelines'; -import LoadingIndicator from 'soapbox/components/loading_indicator'; -import Column from '../ui/components/column'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { getAccountGallery, findAccountByUsername } from 'soapbox/selectors'; -import MediaItem from './components/media_item'; +import { openModal } from 'soapbox/actions/modals'; +import Column from 'soapbox/components/column'; import LoadMore from 'soapbox/components/load_more'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; import MissingIndicator from 'soapbox/components/missing_indicator'; -import { openModal } from 'soapbox/actions/modal'; -import { NavLink } from 'react-router-dom'; -import { FormattedMessage } from 'react-intl'; +import SubNavigation from 'soapbox/components/sub_navigation'; +import { getAccountGallery, findAccountByUsername } from 'soapbox/selectors'; +import { getFeatures } from 'soapbox/utils/features'; + +import { expandAccountMediaTimeline } from '../../actions/timelines'; + +import MediaItem from './components/media_item'; const mapStateToProps = (state, { params, withReplies = false }) => { const username = params.username || ''; const me = state.get('me'); - const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() === username.toLowerCase()); + const accountFetchError = ((state.getIn(['accounts', -1, 'username']) || '').toLowerCase() === username.toLowerCase()); + const features = getFeatures(state.get('instance')); let accountId = -1; let accountUsername = username; @@ -34,7 +40,7 @@ const mapStateToProps = (state, { params, withReplies = false }) => { } const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false); - const unavailable = (me === accountId) ? false : isBlocked; + const unavailable = (me === accountId) ? false : (isBlocked && !features.blockersVisible); return { accountId, @@ -186,6 +192,7 @@ class AccountGallery extends ImmutablePureComponent { return ( +
diff --git a/app/soapbox/features/account_timeline/components/column_settings.js b/app/soapbox/features/account_timeline/components/column_settings.js index 130cb47db..9f4ed2015 100644 --- a/app/soapbox/features/account_timeline/components/column_settings.js +++ b/app/soapbox/features/account_timeline/components/column_settings.js @@ -1,8 +1,10 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; + import IconButton from 'soapbox/components/icon_button'; + import SettingToggle from '../../notifications/components/setting_toggle'; const messages = defineMessages({ diff --git a/app/soapbox/features/account_timeline/components/header.js b/app/soapbox/features/account_timeline/components/header.js index aba9af207..51120dfcf 100644 --- a/app/soapbox/features/account_timeline/components/header.js +++ b/app/soapbox/features/account_timeline/components/header.js @@ -1,8 +1,10 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import InnerHeader from '../../account/components/header'; import ImmutablePureComponent from 'react-immutable-pure-component'; + +import InnerHeader from '../../account/components/header'; + import MovedNote from './moved_note'; export default class Header extends ImmutablePureComponent { @@ -20,7 +22,7 @@ export default class Header extends ImmutablePureComponent { onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, - // onEndorseToggle: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, onAddToList: PropTypes.func.isRequired, username: PropTypes.string, }; @@ -57,6 +59,10 @@ export default class Header extends ImmutablePureComponent { this.props.onSubscriptionToggle(this.props.account); } + handleNotifyToggle = () => { + this.props.onNotifyToggle(this.props.account); + } + handleMute = () => { this.props.onMute(this.props.account); } @@ -81,9 +87,9 @@ export default class Header extends ImmutablePureComponent { this.props.onChat(this.props.account, this.context.router.history); } - // handleEndorseToggle = () => { - // this.props.onEndorseToggle(this.props.account); - // } + handleEndorseToggle = () => { + this.props.onEndorseToggle(this.props.account); + } handleAddToList = () => { this.props.onAddToList(this.props.account); @@ -117,6 +123,14 @@ export default class Header extends ImmutablePureComponent { this.props.onDemoteToUser(this.props.account); } + handleSuggestUser = () => { + this.props.onSuggestUser(this.props.account); + } + + handleUnsuggestUser = () => { + this.props.onUnsuggestUser(this.props.account); + } + render() { const { account, identity_proofs } = this.props; const moved = (account) ? account.get('moved') : false; @@ -135,6 +149,7 @@ export default class Header extends ImmutablePureComponent { onChat={this.handleChat} onReblogToggle={this.handleReblogToggle} onSubscriptionToggle={this.handleSubscriptionToggle} + onNotifyToggle={this.handleNotifyToggle} onReport={this.handleReport} onMute={this.handleMute} onBlockDomain={this.handleBlockDomain} @@ -148,6 +163,8 @@ export default class Header extends ImmutablePureComponent { onPromoteToAdmin={this.handlePromoteToAdmin} onPromoteToModerator={this.handlePromoteToModerator} onDemoteToUser={this.handleDemoteToUser} + onSuggestUser={this.handleSuggestUser} + onUnsuggestUser={this.handleUnsuggestUser} username={this.props.username} />
diff --git a/app/soapbox/features/account_timeline/components/moved_note.js b/app/soapbox/features/account_timeline/components/moved_note.js index b3c2cae13..5963dbeea 100644 --- a/app/soapbox/features/account_timeline/components/moved_note.js +++ b/app/soapbox/features/account_timeline/components/moved_note.js @@ -1,12 +1,14 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import { NavLink } from 'react-router-dom'; + +import Icon from 'soapbox/components/icon'; + import AvatarOverlay from '../../../components/avatar_overlay'; import DisplayName from '../../../components/display_name'; -import Icon from 'soapbox/components/icon'; -import { NavLink } from 'react-router-dom'; export default class MovedNote extends ImmutablePureComponent { @@ -26,7 +28,7 @@ export default class MovedNote extends ImmutablePureComponent { return (
-
+
}} />
diff --git a/app/soapbox/features/account_timeline/containers/column_settings_container.js b/app/soapbox/features/account_timeline/containers/column_settings_container.js index e5045e54e..c0b9fdf35 100644 --- a/app/soapbox/features/account_timeline/containers/column_settings_container.js +++ b/app/soapbox/features/account_timeline/containers/column_settings_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; + import { getSettings, changeSetting } from '../../../actions/settings'; +import ColumnSettings from '../components/column_settings'; const mapStateToProps = state => ({ settings: getSettings(state).get('account_timeline'), diff --git a/app/soapbox/features/account_timeline/containers/header_container.js b/app/soapbox/features/account_timeline/containers/header_container.js index 7ce9f8e9a..cec3c29fe 100644 --- a/app/soapbox/features/account_timeline/containers/header_container.js +++ b/app/soapbox/features/account_timeline/containers/header_container.js @@ -1,15 +1,31 @@ +import { List as ImmutableList } from 'immutable'; import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import { makeGetAccount } from '../../../selectors'; -import Header from '../components/header'; + +import { + verifyUser, + unverifyUser, + promoteToAdmin, + promoteToModerator, + demoteToUser, + suggestUsers, + unsuggestUsers, +} from 'soapbox/actions/admin'; +import { launchChat } from 'soapbox/actions/chats'; +import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; +import { getSettings } from 'soapbox/actions/settings'; +import snackbar from 'soapbox/actions/snackbar'; +import { isAdmin } from 'soapbox/utils/accounts'; + import { followAccount, unfollowAccount, blockAccount, unblockAccount, unmuteAccount, - // pinAccount, - // unpinAccount, + pinAccount, + unpinAccount, subscribeAccount, unsubscribeAccount, } from '../../../actions/accounts'; @@ -17,24 +33,12 @@ import { mentionCompose, directCompose, } from '../../../actions/compose'; +import { blockDomain, unblockDomain } from '../../../actions/domain_blocks'; +import { openModal } from '../../../actions/modals'; import { initMuteModal } from '../../../actions/mutes'; import { initReport } from '../../../actions/reports'; -import { openModal } from '../../../actions/modal'; -import { blockDomain, unblockDomain } from '../../../actions/domain_blocks'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { List as ImmutableList } from 'immutable'; -import { getSettings } from 'soapbox/actions/settings'; -import { launchChat } from 'soapbox/actions/chats'; -import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; -import { - verifyUser, - unverifyUser, - promoteToAdmin, - promoteToModerator, - demoteToUser, -} from 'soapbox/actions/admin'; -import { isAdmin } from 'soapbox/utils/accounts'; -import snackbar from 'soapbox/actions/snackbar'; +import { makeGetAccount } from '../../../selectors'; +import Header from '../components/header'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, @@ -47,7 +51,8 @@ const messages = defineMessages({ promotedToModerator: { id: 'admin.users.actions.promote_to_moderator_message', defaultMessage: '@{acct} was promoted to a moderator' }, demotedToModerator: { id: 'admin.users.actions.demote_to_moderator_message', defaultMessage: '@{acct} was demoted to a moderator' }, demotedToUser: { id: 'admin.users.actions.demote_to_user_message', defaultMessage: '@{acct} was demoted to a regular user' }, - + userSuggested: { id: 'admin.users.user_suggested_message', defaultMessage: '@{acct} was suggested' }, + userUnsuggested: { id: 'admin.users.user_unsuggested_message', defaultMessage: '@{acct} was unsuggested' }, }); const makeMapStateToProps = () => { @@ -87,6 +92,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(unblockAccount(account.get('id'))); } else { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), @@ -109,9 +116,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onReblogToggle(account) { if (account.getIn(['relationship', 'showing_reblogs'])) { - dispatch(followAccount(account.get('id'), false)); + dispatch(followAccount(account.get('id'), { reblogs: false })); } else { - dispatch(followAccount(account.get('id'), true)); + dispatch(followAccount(account.get('id'), { reblogs: true })); } }, @@ -123,13 +130,21 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, - // onEndorseToggle(account) { - // if (account.getIn(['relationship', 'endorsed'])) { - // dispatch(unpinAccount(account.get('id'))); - // } else { - // dispatch(pinAccount(account.get('id'))); - // } - // }, + onNotifyToggle(account) { + if (account.getIn(['relationship', 'notifying'])) { + dispatch(followAccount(account.get('id'), { notify: false })); + } else { + dispatch(followAccount(account.get('id'), { notify: true })); + } + }, + + onEndorseToggle(account) { + if (account.getIn(['relationship', 'endorsed'])) { + dispatch(unpinAccount(account.get('id'))); + } else { + dispatch(pinAccount(account.get('id'))); + } + }, onReport(account) { dispatch(initReport(account)); @@ -145,7 +160,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onBlockDomain(domain) { dispatch(openModal('CONFIRM', { - message: {domain} }} />, + icon: require('@tabler/icons/icons/ban.svg'), + heading: , + message: {domain} }} />, confirm: intl.formatMessage(messages.blockDomainConfirm), onConfirm: () => dispatch(blockDomain(domain)), })); @@ -213,6 +230,22 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ .then(() => dispatch(snackbar.success(message))) .catch(() => {}); }, + + onSuggestUser(account) { + const message = intl.formatMessage(messages.userSuggested, { acct: account.get('acct') }); + + dispatch(suggestUsers([account.get('id')])) + .then(() => dispatch(snackbar.success(message))) + .catch(() => {}); + }, + + onUnsuggestUser(account) { + const message = intl.formatMessage(messages.userUnsuggested, { acct: account.get('acct') }); + + dispatch(unsuggestUsers([account.get('id')])) + .then(() => dispatch(snackbar.success(message))) + .catch(() => {}); + }, }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header)); diff --git a/app/soapbox/features/account_timeline/index.js b/app/soapbox/features/account_timeline/index.js index 8700710a7..ed3121a28 100644 --- a/app/soapbox/features/account_timeline/index.js +++ b/app/soapbox/features/account_timeline/index.js @@ -1,25 +1,28 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { fetchAccount, fetchAccountByUsername } from '../../actions/accounts'; -import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines'; -import Icon from 'soapbox/components/icon'; -import StatusList from '../../components/status_list'; -import LoadingIndicator from '../../components/loading_indicator'; -import Column from 'soapbox/components/column'; -// import ColumnSettingsContainer from './containers/column_settings_container'; -import SubNavigation from 'soapbox/components/sub_navigation'; import { OrderedSet as ImmutableOrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; -import MissingIndicator from 'soapbox/components/missing_indicator'; +import { connect } from 'react-redux'; +// import ColumnSettingsContainer from './containers/column_settings_container'; import { NavLink } from 'react-router-dom'; -import { fetchPatronAccount } from '../../actions/patron'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; + import { getSettings } from 'soapbox/actions/settings'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import Column from 'soapbox/components/column'; +import Icon from 'soapbox/components/icon'; +import MissingIndicator from 'soapbox/components/missing_indicator'; +import SubNavigation from 'soapbox/components/sub_navigation'; import { makeGetStatusIds, findAccountByUsername } from 'soapbox/selectors'; +import { getFeatures } from 'soapbox/utils/features'; + +import { fetchAccount, fetchAccountByUsername } from '../../actions/accounts'; +import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; +import { fetchPatronAccount } from '../../actions/patron'; +import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines'; +import LoadingIndicator from '../../components/loading_indicator'; +import StatusList from '../../components/status_list'; const makeMapStateToProps = () => { const getStatusIds = makeGetStatusIds(); @@ -27,8 +30,9 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { params, withReplies = false }) => { const username = params.username || ''; const me = state.get('me'); - const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() === username.toLowerCase()); + const accountFetchError = ((state.getIn(['accounts', -1, 'username']) || '').toLowerCase() === username.toLowerCase()); const soapboxConfig = getSoapboxConfig(state); + const features = getFeatures(state.get('instance')); let accountId = -1; let accountUsername = username; @@ -45,7 +49,7 @@ const makeMapStateToProps = () => { const path = withReplies ? `${accountId}:with_replies` : accountId; const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false); - const unavailable = (me === accountId) ? false : isBlocked; + const unavailable = (me === accountId) ? false : (isBlocked && !features.blockersVisible); const showPins = getSettings(state).getIn(['account_timeline', 'shows', 'pinned']) && !withReplies; return { diff --git a/app/soapbox/features/admin/awaiting_approval.js b/app/soapbox/features/admin/awaiting_approval.js index 8193f9406..bdd909b3b 100644 --- a/app/soapbox/features/admin/awaiting_approval.js +++ b/app/soapbox/features/admin/awaiting_approval.js @@ -1,13 +1,16 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; -import ScrollableList from 'soapbox/components/scrollable_list'; -import UnapprovedAccount from './components/unapproved_account'; + import { fetchUsers } from 'soapbox/actions/admin'; +import ScrollableList from 'soapbox/components/scrollable_list'; + +import Column from '../ui/components/column'; + +import UnapprovedAccount from './components/unapproved_account'; const messages = defineMessages({ heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' }, diff --git a/app/soapbox/features/admin/components/admin_nav.js b/app/soapbox/features/admin/components/admin_nav.js index f500573ea..6195601ac 100644 --- a/app/soapbox/features/admin/components/admin_nav.js +++ b/app/soapbox/features/admin/components/admin_nav.js @@ -1,11 +1,12 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { NavLink } from 'react-router-dom'; + import Icon from 'soapbox/components/icon'; import IconWithCounter from 'soapbox/components/icon_with_counter'; -import { NavLink } from 'react-router-dom'; -import { FormattedMessage } from 'react-intl'; const mapStateToProps = (state, props) => ({ instance: state.get('instance'), diff --git a/app/soapbox/features/admin/components/latest_accounts_panel.js b/app/soapbox/features/admin/components/latest_accounts_panel.js index 55f64079d..6377b6810 100644 --- a/app/soapbox/features/admin/components/latest_accounts_panel.js +++ b/app/soapbox/features/admin/components/latest_accounts_panel.js @@ -1,13 +1,14 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { injectIntl, defineMessages } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import AccountListPanel from 'soapbox/features/ui/components/account_list_panel'; -import { fetchUsers } from 'soapbox/actions/admin'; import { is } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchUsers } from 'soapbox/actions/admin'; import compareId from 'soapbox/compare_id'; +import AccountListPanel from 'soapbox/features/ui/components/account_list_panel'; const messages = defineMessages({ title: { id: 'admin.latest_accounts_panel.title', defaultMessage: 'Latest Accounts' }, diff --git a/app/soapbox/features/admin/components/registration_mode_picker.js b/app/soapbox/features/admin/components/registration_mode_picker.js index 747964a02..275d9b0c0 100644 --- a/app/soapbox/features/admin/components/registration_mode_picker.js +++ b/app/soapbox/features/admin/components/registration_mode_picker.js @@ -1,15 +1,16 @@ import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; + +import { updateConfig } from 'soapbox/actions/admin'; +import snackbar from 'soapbox/actions/snackbar'; import { SimpleForm, FieldsGroup, RadioGroup, RadioItem, } from 'soapbox/features/forms'; -import { updateConfig } from 'soapbox/actions/admin'; -import snackbar from 'soapbox/actions/snackbar'; const messages = defineMessages({ saved: { id: 'admin.dashboard.settings_saved', defaultMessage: 'Settings saved!' }, diff --git a/app/soapbox/features/admin/components/report.js b/app/soapbox/features/admin/components/report.js index 8ef9a3172..2434b0e3e 100644 --- a/app/soapbox/features/admin/components/report.js +++ b/app/soapbox/features/admin/components/report.js @@ -1,17 +1,19 @@ import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; + +import { closeReports } from 'soapbox/actions/admin'; +import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; +import snackbar from 'soapbox/actions/snackbar'; import Avatar from 'soapbox/components/avatar'; import Button from 'soapbox/components/button'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; import Accordion from 'soapbox/features/ui/components/accordion'; + import ReportStatus from './report_status'; -import { closeReports } from 'soapbox/actions/admin'; -import snackbar from 'soapbox/actions/snackbar'; -import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ reportClosed: { id: 'admin.reports.report_closed_message', defaultMessage: 'Report on @{name} was closed' }, @@ -115,7 +117,7 @@ class Report extends ImmutablePureComponent { - +
); diff --git a/app/soapbox/features/admin/components/report_status.js b/app/soapbox/features/admin/components/report_status.js index 83bb4ef46..90c0d062f 100644 --- a/app/soapbox/features/admin/components/report_status.js +++ b/app/soapbox/features/admin/components/report_status.js @@ -1,15 +1,16 @@ +import noop from 'lodash/noop'; import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { openModal } from 'soapbox/actions/modals'; +import { deleteStatusModal } from 'soapbox/actions/moderation'; import StatusContent from 'soapbox/components/status_content'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; -import { openModal } from 'soapbox/actions/modal'; -import noop from 'lodash/noop'; -import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components'; import Bundle from 'soapbox/features/ui/components/bundle'; -import { deleteStatusModal } from 'soapbox/actions/moderation'; +import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components'; const messages = defineMessages({ viewStatus: { id: 'admin.reports.actions.view_status', defaultMessage: 'View post' }, @@ -37,6 +38,7 @@ class ReportStatus extends ImmutablePureComponent { text: intl.formatMessage(messages.deleteStatus, { acct: `@${acct}` }), action: this.handleDeleteStatus, icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }]; } @@ -118,7 +120,7 @@ class ReportStatus extends ImmutablePureComponent { {media}
- +
); diff --git a/app/soapbox/features/admin/components/unapproved_account.js b/app/soapbox/features/admin/components/unapproved_account.js index 621ffbe4b..f00b0dd6a 100644 --- a/app/soapbox/features/admin/components/unapproved_account.js +++ b/app/soapbox/features/admin/components/unapproved_account.js @@ -1,13 +1,16 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import IconButton from 'soapbox/components/icon_button'; -import { deleteUsers, approveUsers } from 'soapbox/actions/admin'; -import { makeGetAccount } from 'soapbox/selectors'; + +import { approveUsers } from 'soapbox/actions/admin'; import snackbar from 'soapbox/actions/snackbar'; +import IconButton from 'soapbox/components/icon_button'; +import { makeGetAccount } from 'soapbox/selectors'; + +import { rejectUserModal } from '../../../actions/moderation'; const messages = defineMessages({ approved: { id: 'admin.awaiting_approval.approved_message', defaultMessage: '{acct} was approved!' }, @@ -37,7 +40,6 @@ class UnapprovedAccount extends ImmutablePureComponent { handleApprove = () => { const { dispatch, intl, account } = this.props; - dispatch(approveUsers([account.get('id')])) .then(() => { const message = intl.formatMessage(messages.approved, { acct: `@${account.get('acct')}` }); @@ -49,12 +51,10 @@ class UnapprovedAccount extends ImmutablePureComponent { handleReject = () => { const { dispatch, intl, account } = this.props; - dispatch(deleteUsers([account.get('id')])) - .then(() => { - const message = intl.formatMessage(messages.rejected, { acct: `@${account.get('acct')}` }); - dispatch(snackbar.info(message)); - }) - .catch(() => {}); + dispatch(rejectUserModal(intl, account.get('id'), () => { + const message = intl.formatMessage(messages.rejected, { acct: `@${account.get('acct')}` }); + dispatch(snackbar.info(message)); + })); } render() { diff --git a/app/soapbox/features/admin/index.js b/app/soapbox/features/admin/index.js index b09affd66..db76d4407 100644 --- a/app/soapbox/features/admin/index.js +++ b/app/soapbox/features/admin/index.js @@ -1,17 +1,21 @@ -import React from 'react'; -import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; -import { Link } from 'react-router-dom'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; -import RegistrationModePicker from './components/registration_mode_picker'; -import { parseVersion } from 'soapbox/utils/features'; -import sourceCode from 'soapbox/utils/code'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email_list'; -import { getFeatures } from 'soapbox/utils/features'; import { isAdmin } from 'soapbox/utils/accounts'; +import sourceCode from 'soapbox/utils/code'; +import { parseVersion } from 'soapbox/utils/features'; +import { getFeatures } from 'soapbox/utils/features'; +import { isNumber } from 'soapbox/utils/numbers'; + +import Column from '../ui/components/column'; + +import RegistrationModePicker from './components/registration_mode_picker'; // https://stackoverflow.com/a/53230807 const download = (response, filename) => { @@ -102,16 +106,18 @@ class Dashboard extends ImmutablePureComponent {
- {retention &&
-
-
- {retention}% -
-
- + {isNumber(retention) && ( +
+
+
+ {retention}% +
+
+ +
-
} + )}
diff --git a/app/soapbox/features/admin/moderation_log.js b/app/soapbox/features/admin/moderation_log.js index 134699908..12c3cee82 100644 --- a/app/soapbox/features/admin/moderation_log.js +++ b/app/soapbox/features/admin/moderation_log.js @@ -1,12 +1,14 @@ +import PropTypes from 'prop-types'; import React from 'react'; -import { defineMessages, injectIntl, FormattedDate } from 'react-intl'; -import { connect } from 'react-redux'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import Column from '../ui/components/column'; -import ScrollableList from 'soapbox/components/scrollable_list'; +import { defineMessages, injectIntl, FormattedDate } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchModerationLog } from 'soapbox/actions/admin'; +import ScrollableList from 'soapbox/components/scrollable_list'; + +import Column from '../ui/components/column'; const messages = defineMessages({ heading: { id: 'column.admin.moderation_log', defaultMessage: 'Moderation Log' }, diff --git a/app/soapbox/features/admin/reports.js b/app/soapbox/features/admin/reports.js index ac34352c6..dbc3d5649 100644 --- a/app/soapbox/features/admin/reports.js +++ b/app/soapbox/features/admin/reports.js @@ -1,15 +1,18 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/better_column'; -import ScrollableList from 'soapbox/components/scrollable_list'; + import { fetchReports } from 'soapbox/actions/admin'; -import Report from './components/report'; +import ScrollableList from 'soapbox/components/scrollable_list'; import { makeGetReport } from 'soapbox/selectors'; +import Column from '../ui/components/better_column'; + +import Report from './components/report'; + const messages = defineMessages({ heading: { id: 'column.admin.reports', defaultMessage: 'Reports' }, modlog: { id: 'column.admin.reports.menu.moderation_log', defaultMessage: 'Moderation Log' }, diff --git a/app/soapbox/features/admin/user_index.js b/app/soapbox/features/admin/user_index.js index 4406a0aad..87c24f867 100644 --- a/app/soapbox/features/admin/user_index.js +++ b/app/soapbox/features/admin/user_index.js @@ -1,17 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import { debounce } from 'lodash'; -import { fetchUsers } from 'soapbox/actions/admin'; -import { injectIntl, defineMessages } from 'react-intl'; -import AccountContainer from 'soapbox/containers/account_container'; -import Column from 'soapbox/features/ui/components/column'; -import ScrollableList from 'soapbox/components/scrollable_list'; -import { SimpleForm, TextInput } from 'soapbox/features/forms'; import { Set as ImmutableSet, OrderedSet as ImmutableOrderedSet, is } from 'immutable'; +import { debounce } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchUsers } from 'soapbox/actions/admin'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import AccountContainer from 'soapbox/containers/account_container'; +import { SimpleForm, TextInput } from 'soapbox/features/forms'; +import Column from 'soapbox/features/ui/components/column'; const messages = defineMessages({ + heading: { id: 'column.admin.users', defaultMessage: 'Users' }, empty: { id: 'admin.user_index.empty', defaultMessage: 'No users found.' }, searchPlaceholder: { id: 'admin.user_index.search_input_placeholder', defaultMessage: 'Who are you looking for?' }, }); @@ -100,7 +102,7 @@ class UserIndex extends ImmutablePureComponent { const showLoading = isLoading && accountIds.isEmpty(); return ( - + { const getAccount = makeGetAccount(); - const mapStateToProps = (state, { accountId, added }) => { + const mapStateToProps = (state, { accountId, added, aliases }) => { const me = state.get('me'); - const ownAccount = getAccount(state, me); + + const instance = state.get('instance'); + const features = getFeatures(instance); const account = getAccount(state, accountId); const apId = account.getIn(['pleroma', 'ap_id']); + const name = features.accountMoving ? account.get('acct') : apId; return { account, apId, - added: typeof added === 'undefined' ? ownAccount.getIn(['pleroma', 'also_known_as']).includes(apId) : added, + added: typeof added === 'undefined' ? aliases.includes(name) : added, me, }; }; @@ -55,7 +60,7 @@ class Account extends ImmutablePureComponent { added: false, }; - handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.apId); + handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.account); render() { const { account, accountId, intl, added, me } = this.props; @@ -65,7 +70,7 @@ class Account extends ImmutablePureComponent { if (!added && accountId !== me) { button = (
- +
); } diff --git a/app/soapbox/features/aliases/components/search.js b/app/soapbox/features/aliases/components/search.js index 423063944..2c92ad9a5 100644 --- a/app/soapbox/features/aliases/components/search.js +++ b/app/soapbox/features/aliases/components/search.js @@ -1,11 +1,13 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl } from 'react-intl'; -import { fetchAliasesSuggestions, clearAliasesSuggestions, changeAliasesSuggestions } from '../../../actions/aliases'; import classNames from 'classnames'; -import Icon from 'soapbox/components/icon'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import Button from 'soapbox/components/button'; +import Icon from 'soapbox/components/icon'; + +import { fetchAliasesSuggestions, clearAliasesSuggestions, changeAliasesSuggestions } from '../../../actions/aliases'; const messages = defineMessages({ search: { id: 'aliases.search', defaultMessage: 'Search your old account' }, diff --git a/app/soapbox/features/aliases/index.js b/app/soapbox/features/aliases/index.js index 67759abe5..c9bd35749 100644 --- a/app/soapbox/features/aliases/index.js +++ b/app/soapbox/features/aliases/index.js @@ -1,15 +1,20 @@ +import { List as ImmutableList } from 'immutable'; import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchAliases, removeFromAliases } from 'soapbox/actions/aliases'; +import Icon from 'soapbox/components/icon'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import { makeGetAccount } from 'soapbox/selectors'; +import { getFeatures } from 'soapbox/utils/features'; + import Column from '../ui/components/column'; import ColumnSubheading from '../ui/components/column_subheading'; -import ScrollableList from '../../components/scrollable_list'; -import Icon from 'soapbox/components/icon'; -import Search from './components/search'; + import Account from './components/account'; -import { removeFromAliases } from '../../actions/aliases'; -import { makeGetAccount } from 'soapbox/selectors'; +import Search from './components/search'; const messages = defineMessages({ heading: { id: 'column.aliases', defaultMessage: 'Account aliases' }, @@ -27,8 +32,16 @@ const makeMapStateToProps = () => { const me = state.get('me'); const account = getAccount(state, me); + const instance = state.get('instance'); + const features = getFeatures(instance); + + let aliases; + + if (features.accountMoving) aliases = state.getIn(['aliases', 'aliases', 'items'], ImmutableList()); + else aliases = account.getIn(['pleroma', 'also_known_as']); + return { - aliases: account.getIn(['pleroma', 'also_known_as']), + aliases, searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']), loaded: state.getIn(['aliases', 'suggestions', 'loaded']), }; @@ -41,6 +54,11 @@ export default @connect(makeMapStateToProps) @injectIntl class Aliases extends ImmutablePureComponent { + componentDidMount = e => { + const { dispatch } = this.props; + dispatch(fetchAliases); + } + handleFilterDelete = e => { const { dispatch, intl } = this.props; dispatch(removeFromAliases(intl, e.currentTarget.dataset.value)); @@ -62,7 +80,7 @@ class Aliases extends ImmutablePureComponent {
) : (
- {searchAccountIds.map(accountId => )} + {searchAccountIds.map(accountId => )}
) } diff --git a/app/soapbox/features/audio/index.js b/app/soapbox/features/audio/index.js index ed6548434..7553f2388 100644 --- a/app/soapbox/features/audio/index.js +++ b/app/soapbox/features/audio/index.js @@ -1,12 +1,14 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; -import { formatTime } from 'soapbox/features/video'; -import Icon from 'soapbox/components/icon'; import classNames from 'classnames'; import { throttle } from 'lodash'; -import { getPointerPosition, fileNameFromURL } from 'soapbox/features/video'; import { debounce } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +import Icon from 'soapbox/components/icon'; +import { formatTime } from 'soapbox/features/video'; +import { getPointerPosition, fileNameFromURL } from 'soapbox/features/video'; + import Visualizer from './visualizer'; const messages = defineMessages({ diff --git a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap index ad357af03..ed6a494b2 100644 --- a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap +++ b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap @@ -25,19 +25,51 @@ exports[` renders for Mastodon 1`] = ` />
+

renders for Pleroma 1`] = ` />

+

renders correctly on load 1`] = ` />

+

', () => { it('renders null by default', () => { diff --git a/app/soapbox/features/auth_login/components/__tests__/login_form-test.js b/app/soapbox/features/auth_login/components/__tests__/login_form-test.js index 3fb0429c8..f672e6825 100644 --- a/app/soapbox/features/auth_login/components/__tests__/login_form-test.js +++ b/app/soapbox/features/auth_login/components/__tests__/login_form-test.js @@ -1,7 +1,9 @@ import React from 'react'; -import LoginForm from '../login_form'; -import { createComponent, mockStore } from 'soapbox/test_helpers'; + import rootReducer from 'soapbox/reducers'; +import { createComponent, mockStore } from 'soapbox/test_helpers'; + +import LoginForm from '../login_form'; describe('', () => { diff --git a/app/soapbox/features/auth_login/components/__tests__/login_page-test.js b/app/soapbox/features/auth_login/components/__tests__/login_page-test.js index 382037f45..0f75d266f 100644 --- a/app/soapbox/features/auth_login/components/__tests__/login_page-test.js +++ b/app/soapbox/features/auth_login/components/__tests__/login_page-test.js @@ -1,7 +1,9 @@ import React from 'react'; -import LoginPage from '../login_page'; -import { createComponent, mockStore } from 'soapbox/test_helpers'; + import rootReducer from 'soapbox/reducers'; +import { createComponent, mockStore } from 'soapbox/test_helpers'; + +import LoginPage from '../login_page'; describe('', () => { it('renders correctly on load', () => { diff --git a/app/soapbox/features/auth_login/components/__tests__/otp_auth_form-test.js b/app/soapbox/features/auth_login/components/__tests__/otp_auth_form-test.js index 335780280..cd7f1108a 100644 --- a/app/soapbox/features/auth_login/components/__tests__/otp_auth_form-test.js +++ b/app/soapbox/features/auth_login/components/__tests__/otp_auth_form-test.js @@ -1,7 +1,9 @@ -import React from 'react'; -import OtpAuthForm from '../otp_auth_form'; -import { createComponent, mockStore } from 'soapbox/test_helpers'; import { Map as ImmutableMap } from 'immutable'; +import React from 'react'; + +import { createComponent, mockStore } from 'soapbox/test_helpers'; + +import OtpAuthForm from '../otp_auth_form'; describe('', () => { it('renders correctly', () => { diff --git a/app/soapbox/features/auth_login/components/captcha.js b/app/soapbox/features/auth_login/components/captcha.js index e393c3e92..bcdaf74a4 100644 --- a/app/soapbox/features/auth_login/components/captcha.js +++ b/app/soapbox/features/auth_login/components/captcha.js @@ -1,11 +1,12 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; import { Map as ImmutableMap } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchCaptcha } from 'soapbox/actions/auth'; import { TextInput } from 'soapbox/features/forms'; -import { FormattedMessage } from 'react-intl'; const noOp = () => {}; diff --git a/app/soapbox/features/auth_login/components/login_form.js b/app/soapbox/features/auth_login/components/login_form.js index 842e38832..549ebb338 100644 --- a/app/soapbox/features/auth_login/components/login_form.js +++ b/app/soapbox/features/auth_login/components/login_form.js @@ -1,8 +1,10 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; -import { Link } from 'react-router-dom'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import ShowablePassword from 'soapbox/components/showable_password'; import { getFeatures } from 'soapbox/utils/features'; import { getBaseURL } from 'soapbox/utils/state'; @@ -13,11 +15,10 @@ const messages = defineMessages({ const mapStateToProps = state => { const instance = state.get('instance'); - const features = getFeatures(instance); return { baseURL: getBaseURL(state), - hasResetPasswordAPI: features.resetPasswordAPI, + features: getFeatures(instance), }; }; @@ -26,7 +27,7 @@ export default @connect(mapStateToProps) class LoginForm extends ImmutablePureComponent { render() { - const { intl, isLoading, handleSubmit, baseURL, hasResetPasswordAPI } = this.props; + const { intl, isLoading, handleSubmit, baseURL, features } = this.props; return (

@@ -45,21 +46,18 @@ class LoginForm extends ImmutablePureComponent { required />
-
- -
+

- {hasResetPasswordAPI ? ( + {features.resetPasswordAPI ? ( diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js index 720616616..45de99585 100644 --- a/app/soapbox/features/auth_login/components/login_page.js +++ b/app/soapbox/features/auth_login/components/login_page.js @@ -1,14 +1,16 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl } from 'react-intl'; -import LoginForm from './login_form'; -import OtpAuthForm from './otp_auth_form'; +import { connect } from 'react-redux'; +import { Redirect } from 'react-router-dom'; + import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { fetchInstance } from 'soapbox/actions/instance'; import { isStandalone } from 'soapbox/utils/state'; +import LoginForm from './login_form'; +import OtpAuthForm from './otp_auth_form'; + const mapStateToProps = state => ({ me: state.get('me'), isLoading: false, @@ -50,8 +52,9 @@ class LoginPage extends ImmutablePureComponent { dispatch(switchAccount(account.id)); } }).catch(error => { - if (error.response.data.error === 'mfa_required') { - this.setState({ mfa_auth_needed: true, mfa_token: error.response.data.mfa_token }); + const data = error.response?.data; + if (data?.error === 'mfa_required') { + this.setState({ mfa_auth_needed: true, mfa_token: data.mfa_token }); } this.setState({ isLoading: false }); }); diff --git a/app/soapbox/features/auth_login/components/otp_auth_form.js b/app/soapbox/features/auth_login/components/otp_auth_form.js index 132e4e3c5..9bd4afa6f 100644 --- a/app/soapbox/features/auth_login/components/otp_auth_form.js +++ b/app/soapbox/features/auth_login/components/otp_auth_form.js @@ -1,11 +1,12 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; -import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; + import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { SimpleInput } from 'soapbox/features/forms'; -import PropTypes from 'prop-types'; const messages = defineMessages({ otpCodeHint: { id: 'login.fields.otp_code_hint', defaultMessage: 'Enter the two-factor code generated by your phone app or use one of your recovery codes' }, @@ -44,10 +45,7 @@ class OtpAuthForm extends ImmutablePureComponent { this.setState({ shouldRedirect: true }); return dispatch(switchAccount(account.id)); }).catch(error => { - this.setState({ isLoading: false }); - if (error.response.data.error === 'Invalid code') { - this.setState({ code_error: true }); - } + this.setState({ isLoading: false, code_error: true }); }); this.setState({ isLoading: true }); event.preventDefault(); @@ -81,11 +79,11 @@ class OtpAuthForm extends ImmutablePureComponent {

- { code_error && + {code_error && (
- } + )}
diff --git a/app/soapbox/features/backups/index.js b/app/soapbox/features/backups/index.js index a247db302..2bd342222 100644 --- a/app/soapbox/features/backups/index.js +++ b/app/soapbox/features/backups/index.js @@ -1,15 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; -import Column from '../ui/components/better_column'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchBackups, createBackup, } from 'soapbox/actions/backups'; import ScrollableList from 'soapbox/components/scrollable_list'; -import classNames from 'classnames'; + +import Column from '../ui/components/better_column'; const messages = defineMessages({ heading: { id: 'column.backups', defaultMessage: 'Backups' }, diff --git a/app/soapbox/features/birthdays/account.js b/app/soapbox/features/birthdays/account.js new file mode 100644 index 000000000..d0961d0ae --- /dev/null +++ b/app/soapbox/features/birthdays/account.js @@ -0,0 +1,88 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import Avatar from 'soapbox/components/avatar'; +import DisplayName from 'soapbox/components/display_name'; +import Icon from 'soapbox/components/icon'; +import Permalink from 'soapbox/components/permalink'; +import { makeGetAccount } from 'soapbox/selectors'; + +const messages = defineMessages({ + birthday: { id: 'account.birthday', defaultMessage: 'Born {date}' }, +}); + +const makeMapStateToProps = () => { + const getAccount = makeGetAccount(); + + const mapStateToProps = (state, { accountId }) => { + const account = getAccount(state, accountId); + + return { + account, + }; + }; + + return mapStateToProps; +}; + +export default @connect(makeMapStateToProps) +@injectIntl +class Account extends ImmutablePureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + intl: PropTypes.object.isRequired, + account: ImmutablePropTypes.map, + }; + + static defaultProps = { + added: false, + }; + + componentDidMount() { + const { account, accountId } = this.props; + + if (accountId && !account) { + this.props.fetchAccount(accountId); + } + } + + render() { + const { account, intl } = this.props; + + if (!account) return null; + + const birthday = account.getIn(['pleroma', 'birthday']); + if (!birthday) return null; + + const formattedBirthday = intl.formatDate(birthday, { day: 'numeric', month: 'short', year: 'numeric' }); + + return ( +
+
+ +
+
+ + +
+
+
+ + {formattedBirthday} +
+
+
+ ); + } + +} diff --git a/app/soapbox/features/blocks/index.js b/app/soapbox/features/blocks/index.js index a0dbddfe6..10957c9c4 100644 --- a/app/soapbox/features/blocks/index.js +++ b/app/soapbox/features/blocks/index.js @@ -1,15 +1,16 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; import PropTypes from 'prop-types'; -import LoadingIndicator from '../../components/loading_indicator'; -import Column from '../ui/components/column'; -import AccountContainer from '../../containers/account_container'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchBlocks, expandBlocks } from '../../actions/blocks'; +import LoadingIndicator from '../../components/loading_indicator'; import ScrollableList from '../../components/scrollable_list'; +import AccountContainer from '../../containers/account_container'; +import Column from '../ui/components/column'; const messages = defineMessages({ heading: { id: 'column.blocks', defaultMessage: 'Blocked users' }, diff --git a/app/soapbox/features/bookmarks/index.js b/app/soapbox/features/bookmarks/index.js index ec4185f96..0d25bb2aa 100644 --- a/app/soapbox/features/bookmarks/index.js +++ b/app/soapbox/features/bookmarks/index.js @@ -1,14 +1,16 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { debounce } from 'lodash'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import Column from 'soapbox/components/column'; import SubNavigation from 'soapbox/components/sub_navigation'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import StatusList from '../../components/status_list'; + import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from '../../actions/bookmarks'; -import { debounce } from 'lodash'; +import StatusList from '../../components/status_list'; const messages = defineMessages({ heading: { id: 'column.bookmarks', defaultMessage: 'Bookmarks' }, diff --git a/app/soapbox/features/chats/chat_room.js b/app/soapbox/features/chats/chat_room.js index ecd19a495..0493ac764 100644 --- a/app/soapbox/features/chats/chat_room.js +++ b/app/soapbox/features/chats/chat_room.js @@ -1,23 +1,25 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { Map as ImmutableMap } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Avatar from 'soapbox/components/avatar'; -import { getAcct } from 'soapbox/utils/accounts'; +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + import { fetchChat, markChatRead } from 'soapbox/actions/chats'; -import ChatBox from './components/chat_box'; +import Avatar from 'soapbox/components/avatar'; import Column from 'soapbox/components/column'; import ColumnBackButton from 'soapbox/components/column_back_button'; -import { Map as ImmutableMap } from 'immutable'; import { makeGetChat } from 'soapbox/selectors'; +import { getAcct } from 'soapbox/utils/accounts'; import { displayFqn } from 'soapbox/utils/state'; +import ChatBox from './components/chat_box'; + const mapStateToProps = (state, { params }) => { const getChat = makeGetChat(); - const chat = state.getIn(['chats', params.chatId], ImmutableMap()).toJS(); + const chat = state.getIn(['chats', 'items', params.chatId], ImmutableMap()).toJS(); return { me: state.get('me'), diff --git a/app/soapbox/features/chats/components/audio_toggle.js b/app/soapbox/features/chats/components/audio_toggle.js index daf1eae0c..bc1dee76a 100644 --- a/app/soapbox/features/chats/components/audio_toggle.js +++ b/app/soapbox/features/chats/components/audio_toggle.js @@ -1,11 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; +import React from 'react'; import { injectIntl, defineMessages } from 'react-intl'; -import Icon from 'soapbox/components/icon'; -import { changeSetting, getSettings } from 'soapbox/actions/settings'; +import { connect } from 'react-redux'; import Toggle from 'react-toggle'; +import { changeSetting, getSettings } from 'soapbox/actions/settings'; +import Icon from 'soapbox/components/icon'; + const messages = defineMessages({ switchOn: { id: 'chats.audio_toggle_on', defaultMessage: 'Audio notification on' }, switchOff: { id: 'chats.audio_toggle_off', defaultMessage: 'Audio notification off' }, diff --git a/app/soapbox/features/chats/components/chat.js b/app/soapbox/features/chats/components/chat.js index 8db6ddb62..f19190bed 100644 --- a/app/soapbox/features/chats/components/chat.js +++ b/app/soapbox/features/chats/components/chat.js @@ -1,20 +1,23 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import Avatar from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { shortNumberFormat } from 'soapbox/utils/numbers'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import Icon from 'soapbox/components/icon'; import emojify from 'soapbox/features/emoji/emoji'; import { makeGetChat } from 'soapbox/selectors'; +import { shortNumberFormat } from 'soapbox/utils/numbers'; +import Avatar from '../../../components/avatar'; +import DisplayName from '../../../components/display_name'; const makeMapStateToProps = () => { const getChat = makeGetChat(); const mapStateToProps = (state, { chatId }) => { - const chat = state.getIn(['chats', chatId]); + const chat = state.getIn(['chats', 'items', chatId]); return { chat: chat ? getChat(state, chat.toJS()) : undefined, @@ -43,6 +46,8 @@ class Chat extends ImmutablePureComponent { const account = chat.get('account'); const unreadCount = chat.get('unread'); const content = chat.getIn(['last_message', 'content']); + const attachment = chat.getIn(['last_message', 'attachment']); + const image = attachment && attachment.getIn(['pleroma', 'mime_type'], '').startsWith('image/'); const parsedContent = content ? emojify(content) : ''; return ( @@ -54,10 +59,24 @@ class Chat extends ImmutablePureComponent {
- + {attachment && ( + + )} + {content ? ( + + ) : attachment && ( + + {image ? : } + + )} {unreadCount > 0 && {shortNumberFormat(unreadCount)}}
diff --git a/app/soapbox/features/chats/components/chat_box.js b/app/soapbox/features/chats/components/chat_box.js index e1403bccb..8a3569221 100644 --- a/app/soapbox/features/chats/components/chat_box.js +++ b/app/soapbox/features/chats/components/chat_box.js @@ -1,20 +1,22 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { OrderedSet as ImmutableOrderedSet } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl, defineMessages } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + import { sendChatMessage, markChatRead, } from 'soapbox/actions/chats'; -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import ChatMessageList from './chat_message_list'; -import UploadButton from 'soapbox/features/compose/components/upload_button'; import { uploadMedia } from 'soapbox/actions/media'; +import IconButton from 'soapbox/components/icon_button'; +import UploadButton from 'soapbox/features/compose/components/upload_button'; import UploadProgress from 'soapbox/features/compose/components/upload_progress'; import { truncateFilename } from 'soapbox/utils/media'; -import IconButton from 'soapbox/components/icon_button'; + +import ChatMessageList from './chat_message_list'; const messages = defineMessages({ placeholder: { id: 'chat_box.input.placeholder', defaultMessage: 'Send a message…' }, @@ -23,7 +25,7 @@ const messages = defineMessages({ const mapStateToProps = (state, { chatId }) => ({ me: state.get('me'), - chat: state.getIn(['chats', chatId]), + chat: state.getIn(['chats', 'items', chatId]), chatMessageIds: state.getIn(['chat_message_lists', chatId], ImmutableOrderedSet()), }); @@ -158,7 +160,10 @@ class ChatBox extends ImmutablePureComponent { {truncateFilename(attachment.preview_url, 20)}
- +
); diff --git a/app/soapbox/features/chats/components/chat_list.js b/app/soapbox/features/chats/components/chat_list.js index f89115363..b31219913 100644 --- a/app/soapbox/features/chats/components/chat_list.js +++ b/app/soapbox/features/chats/components/chat_list.js @@ -1,12 +1,22 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { debounce } from 'lodash'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Chat from './chat'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; import { createSelector } from 'reselect'; +import { expandChats } from 'soapbox/actions/chats'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import PlaceholderChat from 'soapbox/features/placeholder/components/placeholder_chat'; + +import Chat from './chat'; + +const messages = defineMessages({ + emptyMessage: { id: 'chat_panels.main_window.empty', defaultMessage: 'No chats found. To start a chat, visit a user\'s profile' }, +}); + const getSortedChatIds = chats => ( chats .toList() @@ -32,7 +42,9 @@ const makeMapStateToProps = () => { ); const mapStateToProps = state => ({ - chatIds: sortedChatIdsSelector(state.get('chats')), + chatIds: sortedChatIdsSelector(state.getIn(['chats', 'items'])), + hasMore: !!state.getIn(['chats', 'next']), + isLoading: state.getIn(['chats', 'loading']), }); return mapStateToProps; @@ -47,28 +59,40 @@ class ChatList extends ImmutablePureComponent { intl: PropTypes.object.isRequired, chatIds: ImmutablePropTypes.list, onClickChat: PropTypes.func, - emptyMessage: PropTypes.node, + onRefresh: PropTypes.func, + hasMore: PropTypes.func, + isLoading: PropTypes.bool, }; + handleLoadMore = debounce(() => { + this.props.dispatch(expandChats()); + }, 300, { leading: true }); + render() { - const { chatIds, emptyMessage } = this.props; + const { intl, chatIds, hasMore, isLoading } = this.props; return ( -
-
- {chatIds.count() === 0 && -
{emptyMessage}
- } - {chatIds.map(chatId => ( -
- -
- ))} -
-
+ + {chatIds.map(chatId => ( +
+ +
+ ))} +
); } diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js index 7689bb4f9..fec3196e2 100644 --- a/app/soapbox/features/chats/components/chat_message_list.js +++ b/app/soapbox/features/chats/components/chat_message_list.js @@ -1,20 +1,21 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl, defineMessages } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; -import { fetchChatMessages, deleteChatMessage } from 'soapbox/actions/chats'; -import emojify from 'soapbox/features/emoji/emoji'; import classNames from 'classnames'; -import { openModal } from 'soapbox/actions/modal'; +import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { escape, throttle } from 'lodash'; -import { MediaGallery } from 'soapbox/features/ui/util/async-components'; -import Bundle from 'soapbox/features/ui/components/bundle'; -import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; -import { initReportById } from 'soapbox/actions/reports'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; import { createSelector } from 'reselect'; + +import { fetchChatMessages, deleteChatMessage } from 'soapbox/actions/chats'; +import { openModal } from 'soapbox/actions/modals'; +import { initReportById } from 'soapbox/actions/reports'; +import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; +import emojify from 'soapbox/features/emoji/emoji'; +import Bundle from 'soapbox/features/ui/components/bundle'; +import { MediaGallery } from 'soapbox/features/ui/util/async-components'; import { onlyEmoji } from 'soapbox/utils/rich_content'; const BIG_EMOJI_LIMIT = 1; @@ -265,13 +266,17 @@ class ChatMessageList extends ImmutablePureComponent { text: intl.formatMessage(messages.delete), action: this.handleDeleteMessage(chatMessage.get('chat_id'), chatMessage.get('id')), icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }, - { + ]; + + if (chatMessage.get('account_id') !== me) { + menu.push({ text: intl.formatMessage(messages.report), action: this.handleReportUser(chatMessage.get('account_id')), icon: require('@tabler/icons/icons/flag.svg'), - }, - ]; + }); + } return (
diff --git a/app/soapbox/features/chats/components/chat_panes.js b/app/soapbox/features/chats/components/chat_panes.js index e6362e5b2..f70e71dc6 100644 --- a/app/soapbox/features/chats/components/chat_panes.js +++ b/app/soapbox/features/chats/components/chat_panes.js @@ -1,26 +1,28 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { List as ImmutableList } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { getSettings } from 'soapbox/actions/settings'; -import ChatList from './chat_list'; import { FormattedMessage } from 'react-intl'; -import { openChat, launchChat, toggleMainWindow } from 'soapbox/actions/chats'; -import ChatWindow from './chat_window'; -import { shortNumberFormat } from 'soapbox/utils/numbers'; -import AudioToggle from 'soapbox/features/chats/components/audio_toggle'; -import { List as ImmutableList } from 'immutable'; -import { createSelector } from 'reselect'; -import AccountSearch from 'soapbox/components/account_search'; import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; + +import { openChat, launchChat, toggleMainWindow } from 'soapbox/actions/chats'; +import { getSettings } from 'soapbox/actions/settings'; +import AccountSearch from 'soapbox/components/account_search'; +import AudioToggle from 'soapbox/features/chats/components/audio_toggle'; +import { shortNumberFormat } from 'soapbox/utils/numbers'; + +import ChatList from './chat_list'; +import ChatWindow from './chat_window'; const messages = defineMessages({ searchPlaceholder: { id: 'chats.search_placeholder', defaultMessage: 'Start a chat with…' }, }); const getChatsUnreadCount = state => { - const chats = state.get('chats'); + const chats = state.getIn(['chats', 'items']); return chats.reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0); }; @@ -30,7 +32,7 @@ const normalizePanes = (chats, panes = ImmutableList()) => ( ); const makeNormalizeChatPanes = () => createSelector([ - state => state.get('chats'), + state => state.getIn(['chats', 'items']), state => getSettings(state).getIn(['chats', 'panes']), ], normalizePanes); @@ -93,7 +95,6 @@ class ChatPanes extends ImmutablePureComponent { <> } /> { const getChat = makeGetChat(); const mapStateToProps = (state, { chatId }) => { - const chat = state.getIn(['chats', chatId]); + const chat = state.getIn(['chats', 'items', chatId]); return { me: state.get('me'), diff --git a/app/soapbox/features/chats/index.js b/app/soapbox/features/chats/index.js index a9f5d89af..06b7f9802 100644 --- a/app/soapbox/features/chats/index.js +++ b/app/soapbox/features/chats/index.js @@ -1,14 +1,16 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; + +import { fetchChats, launchChat } from 'soapbox/actions/chats'; +import AccountSearch from 'soapbox/components/account_search'; +import AudioToggle from 'soapbox/features/chats/components/audio_toggle'; + import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; -import { fetchChats, launchChat } from 'soapbox/actions/chats'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; + import ChatList from './components/chat_list'; -import AudioToggle from 'soapbox/features/chats/components/audio_toggle'; -import AccountSearch from 'soapbox/components/account_search'; -import PullToRefresh from 'soapbox/components/pull_to_refresh'; const messages = defineMessages({ title: { id: 'column.chats', defaultMessage: 'Chats' }, @@ -60,12 +62,10 @@ class ChatIndex extends React.PureComponent { onSelected={this.handleSuggestion} /> - - } - /> - + ); } diff --git a/app/soapbox/features/community_timeline/components/column_settings.js b/app/soapbox/features/community_timeline/components/column_settings.js index 1b00a9819..a5bf9a91f 100644 --- a/app/soapbox/features/community_timeline/components/column_settings.js +++ b/app/soapbox/features/community_timeline/components/column_settings.js @@ -1,8 +1,10 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; + import IconButton from 'soapbox/components/icon_button'; + import SettingToggle from '../../notifications/components/setting_toggle'; const messages = defineMessages({ diff --git a/app/soapbox/features/community_timeline/containers/column_settings_container.js b/app/soapbox/features/community_timeline/containers/column_settings_container.js index 1278eac33..d20838089 100644 --- a/app/soapbox/features/community_timeline/containers/column_settings_container.js +++ b/app/soapbox/features/community_timeline/containers/column_settings_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; + import { getSettings, changeSetting } from '../../../actions/settings'; +import ColumnSettings from '../components/column_settings'; const mapStateToProps = state => ({ settings: getSettings(state).get('community'), diff --git a/app/soapbox/features/community_timeline/index.js b/app/soapbox/features/community_timeline/index.js index 44ee6d45f..46e75aa6e 100644 --- a/app/soapbox/features/community_timeline/index.js +++ b/app/soapbox/features/community_timeline/index.js @@ -1,15 +1,18 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; -import StatusListContainer from '../ui/containers/status_list_container'; -import Column from '../../components/column'; -import ColumnSettings from './containers/column_settings_container'; -import { expandCommunityTimeline } from '../../actions/timelines'; -import { connectCommunityStream } from '../../actions/streaming'; +import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; import SubNavigation from 'soapbox/components/sub_navigation'; +import { connectCommunityStream } from '../../actions/streaming'; +import { expandCommunityTimeline } from '../../actions/timelines'; +import Column from '../../components/column'; +import StatusListContainer from '../ui/containers/status_list_container'; + +import ColumnSettings from './containers/column_settings_container'; + const messages = defineMessages({ title: { id: 'column.community', defaultMessage: 'Local timeline' }, }); diff --git a/app/soapbox/features/compose/components/autosuggest_account.js b/app/soapbox/features/compose/components/autosuggest_account.js index 16c769b87..078507731 100644 --- a/app/soapbox/features/compose/components/autosuggest_account.js +++ b/app/soapbox/features/compose/components/autosuggest_account.js @@ -1,9 +1,10 @@ import React from 'react'; -import Avatar from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import Avatar from '../../../components/avatar'; +import DisplayName from '../../../components/display_name'; + export default class AutosuggestAccount extends ImmutablePureComponent { static propTypes = { diff --git a/app/soapbox/features/compose/components/compose_form.js b/app/soapbox/features/compose/components/compose_form.js index 11a839f63..64a8910f9 100644 --- a/app/soapbox/features/compose/components/compose_form.js +++ b/app/soapbox/features/compose/components/compose_form.js @@ -1,33 +1,38 @@ +import classNames from 'classnames'; +import { get } from 'lodash'; +import PropTypes from 'prop-types'; import React from 'react'; // import TextCharacterCounter from './text_character_counter'; -import VisualCharacterCounter from './visual_character_counter'; -import Button from '../../../components/button'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { Link } from 'react-router-dom'; -import ReplyIndicatorContainer from '../containers/reply_indicator_container'; -import AutosuggestTextarea from '../../../components/autosuggest_textarea'; -import AutosuggestInput from '../../../components/autosuggest_input'; -import PollButtonContainer from '../containers/poll_button_container'; -import UploadButtonContainer from '../containers/upload_button_container'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, FormattedMessage } from 'react-intl'; -import SpoilerButtonContainer from '../containers/spoiler_button_container'; -import MarkdownButtonContainer from '../containers/markdown_button_container'; -import ScheduleFormContainer from '../containers/schedule_form_container'; -import ScheduleButtonContainer from '../containers/schedule_button_container'; -import PrivacyDropdownContainer from '../containers/privacy_dropdown_container'; +import { Link } from 'react-router-dom'; +import { length } from 'stringz'; + +import Icon from 'soapbox/components/icon'; + +import AutosuggestInput from '../../../components/autosuggest_input'; +import AutosuggestTextarea from '../../../components/autosuggest_textarea'; +import Button from '../../../components/button'; +import { isMobile } from '../../../is_mobile'; +import Warning from '../components/warning'; import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container'; +import MarkdownButtonContainer from '../containers/markdown_button_container'; +import PollButtonContainer from '../containers/poll_button_container'; import PollFormContainer from '../containers/poll_form_container'; +import PrivacyDropdownContainer from '../containers/privacy_dropdown_container'; +import QuotedStatusContainer from '../containers/quoted_status_container'; +import ReplyIndicatorContainer from '../containers/reply_indicator_container'; +import ReplyMentions from '../containers/reply_mentions_container'; +import ScheduleButtonContainer from '../containers/schedule_button_container'; +import ScheduleFormContainer from '../containers/schedule_form_container'; +import SpoilerButtonContainer from '../containers/spoiler_button_container'; +import UploadButtonContainer from '../containers/upload_button_container'; import UploadFormContainer from '../containers/upload_form_container'; import WarningContainer from '../containers/warning_container'; -import { isMobile } from '../../../is_mobile'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { length } from 'stringz'; import { countableText } from '../util/counter'; -import Icon from 'soapbox/components/icon'; -import { get } from 'lodash'; -import Warning from '../components/warning'; + +import VisualCharacterCounter from './visual_character_counter'; const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'; @@ -119,7 +124,7 @@ export default class ComposeForm extends ImmutablePureComponent { document.querySelector('.privacy-dropdown__dropdown'), document.querySelector('.emoji-picker-dropdown__menu'), document.querySelector('.modal-root__overlay'), - ].some(element => element && element.contains(e.target)); + ].some(element => element?.contains(e.target)); } handleClick = (e) => { @@ -308,7 +313,9 @@ export default class ComposeForm extends ImmutablePureComponent { - { !shouldCondense && } + {!shouldCondense && } + + {!shouldCondense && }
+ +
diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.js b/app/soapbox/features/compose/components/emoji_picker_dropdown.js index 29d3270c9..edd603060 100644 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.js +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.js @@ -1,14 +1,16 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; -import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; -import Overlay from 'react-overlays/lib/Overlay'; import classNames from 'classnames'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { supportsPassiveEvents } from 'detect-passive-events'; -import { buildCustomEmojis } from '../../emoji/emoji'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { defineMessages, injectIntl } from 'react-intl'; +import Overlay from 'react-overlays/lib/Overlay'; + import { joinPublicPath } from 'soapbox/utils/static'; +import { buildCustomEmojis } from '../../emoji/emoji'; +import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; + const messages = defineMessages({ emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search…' }, diff --git a/app/soapbox/features/compose/components/markdown_button.js b/app/soapbox/features/compose/components/markdown_button.js index f8443e249..d03217ee0 100644 --- a/app/soapbox/features/compose/components/markdown_button.js +++ b/app/soapbox/features/compose/components/markdown_button.js @@ -1,8 +1,9 @@ -import React from 'react'; -import IconButton from '../../../components/icon_button'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +import IconButton from '../../../components/icon_button'; const messages = defineMessages({ marked: { id: 'compose_form.markdown.marked', defaultMessage: 'Post markdown enabled' }, diff --git a/app/soapbox/features/compose/components/poll_button.js b/app/soapbox/features/compose/components/poll_button.js index 5a2f20769..a9d607d04 100644 --- a/app/soapbox/features/compose/components/poll_button.js +++ b/app/soapbox/features/compose/components/poll_button.js @@ -1,8 +1,9 @@ -import React from 'react'; -import IconButton from '../../../components/icon_button'; import PropTypes from 'prop-types'; +import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; +import IconButton from '../../../components/icon_button'; + const messages = defineMessages({ add_poll: { id: 'poll_button.add_poll', defaultMessage: 'Add a poll' }, remove_poll: { id: 'poll_button.remove_poll', defaultMessage: 'Remove poll' }, diff --git a/app/soapbox/features/compose/components/poll_form.js b/app/soapbox/features/compose/components/poll_form.js index 95d2cad7e..d566b3055 100644 --- a/app/soapbox/features/compose/components/poll_form.js +++ b/app/soapbox/features/compose/components/poll_form.js @@ -1,15 +1,16 @@ 'use strict'; -import React from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import IconButton from 'soapbox/components/icon_button'; -import Icon from 'soapbox/components/icon'; +import { connect } from 'react-redux'; + import AutosuggestInput from 'soapbox/components/autosuggest_input'; -import classNames from 'classnames'; +import Icon from 'soapbox/components/icon'; +import IconButton from 'soapbox/components/icon_button'; const messages = defineMessages({ option_placeholder: { id: 'compose_form.poll.option_placeholder', defaultMessage: 'Choice {number}' }, @@ -90,8 +91,8 @@ class Option extends React.PureComponent { onKeyPress={this.handleCheckboxKeypress} role='button' tabIndex='0' - title={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)} - aria-label={intl.formatMessage(isPollMultiple ? messages.switchToMultiple : messages.switchToSingle)} + title={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)} + aria-label={intl.formatMessage(isPollMultiple ? messages.switchToSingle : messages.switchToMultiple)} />
- +
); @@ -178,7 +179,7 @@ class PollForm extends ImmutablePureComponent {
{options.size < maxOptions && ( - + )}
`; diff --git a/app/soapbox/features/forms/__tests__/forms-test.js b/app/soapbox/features/forms/__tests__/forms-test.js index 881f6f053..566e87c0f 100644 --- a/app/soapbox/features/forms/__tests__/forms-test.js +++ b/app/soapbox/features/forms/__tests__/forms-test.js @@ -1,5 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; + import { InputContainer, SimpleInput, diff --git a/app/soapbox/features/forms/index.js b/app/soapbox/features/forms/index.js index 3273a0d4e..51c59c7ba 100644 --- a/app/soapbox/features/forms/index.js +++ b/app/soapbox/features/forms/index.js @@ -1,8 +1,8 @@ +import classNames from 'classnames'; +import PropTypes from 'prop-types'; import React, { useState } from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; import { v4 as uuidv4 } from 'uuid'; export const FormPropTypes = { @@ -18,6 +18,7 @@ export const InputContainer = (props) => { 'with_label': props.label, 'required': props.required, 'boolean': props.type === 'checkbox', + 'field_with_errors': props.error, }, props.extraClass); return ( @@ -35,6 +36,7 @@ InputContainer.propTypes = { type: PropTypes.string, children: PropTypes.node, extraClass: PropTypes.string, + error: PropTypes.bool, }; export const LabelInputContainer = ({ label, hint, children, ...props }) => { @@ -87,10 +89,11 @@ export class SimpleInput extends ImmutablePureComponent { static propTypes = { label: FormPropTypes.label, hint: PropTypes.node, + error: PropTypes.bool, } render() { - const { hint, ...props } = this.props; + const { hint, error, ...props } = this.props; const Input = this.props.label ? LabelInput : 'input'; return ( @@ -164,7 +167,7 @@ FieldsGroup.propTypes = { }; export const Checkbox = props => ( - + ); export class RadioGroup extends ImmutablePureComponent { diff --git a/app/soapbox/features/generic_not_found/index.js b/app/soapbox/features/generic_not_found/index.js index 0290be47f..4c45a1359 100644 --- a/app/soapbox/features/generic_not_found/index.js +++ b/app/soapbox/features/generic_not_found/index.js @@ -1,6 +1,7 @@ import React from 'react'; -import Column from '../ui/components/column'; + import MissingIndicator from '../../components/missing_indicator'; +import Column from '../ui/components/column'; const GenericNotFound = () => ( diff --git a/app/soapbox/features/groups/create/index.js b/app/soapbox/features/groups/create/index.js index cba67711b..271ac8402 100644 --- a/app/soapbox/features/groups/create/index.js +++ b/app/soapbox/features/groups/create/index.js @@ -1,9 +1,10 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import { changeValue, submit, reset } from '../../../actions/group_editor'; -import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import { changeValue, submit, reset } from '../../../actions/group_editor'; const messages = defineMessages({ title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' }, diff --git a/app/soapbox/features/groups/edit/index.js b/app/soapbox/features/groups/edit/index.js index 756b2640f..16a691bd6 100644 --- a/app/soapbox/features/groups/edit/index.js +++ b/app/soapbox/features/groups/edit/index.js @@ -1,13 +1,15 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { changeValue, submit, setUp } from '../../../actions/group_editor'; -import { defineMessages, injectIntl } from 'react-intl'; -import LoadingIndicator from '../../../components/loading_indicator'; -import MissingIndicator from 'soapbox/components/missing_indicator'; -import Column from '../../../components/column'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import MissingIndicator from 'soapbox/components/missing_indicator'; + +import { changeValue, submit, setUp } from '../../../actions/group_editor'; +import Column from '../../../components/column'; +import LoadingIndicator from '../../../components/loading_indicator'; const messages = defineMessages({ title: { id: 'groups.form.title', defaultMessage: 'Title' }, diff --git a/app/soapbox/features/groups/index/card.js b/app/soapbox/features/groups/index/card.js index 880f8a8a7..0632a053e 100644 --- a/app/soapbox/features/groups/index/card.js +++ b/app/soapbox/features/groups/index/card.js @@ -2,9 +2,10 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; -import { shortNumberFormat } from '../../../utils/numbers'; import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { shortNumberFormat } from '../../../utils/numbers'; const messages = defineMessages({ members: { id: 'groups.card.members', defaultMessage: 'Members' }, diff --git a/app/soapbox/features/groups/index/index.js b/app/soapbox/features/groups/index/index.js index 36269b08a..13be53b13 100644 --- a/app/soapbox/features/groups/index/index.js +++ b/app/soapbox/features/groups/index/index.js @@ -1,15 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { fetchGroups } from '../../../actions/groups'; -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { Link } from 'react-router-dom'; import classNames from 'classnames'; -import GroupCard from './card'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { fetchGroups } from '../../../actions/groups'; import GroupCreate from '../create'; +import GroupCard from './card'; + const messages = defineMessages({ heading: { id: 'column.groups', defaultMessage: 'Groups' }, create: { id: 'groups.create', defaultMessage: 'Create group' }, diff --git a/app/soapbox/features/groups/members/index.js b/app/soapbox/features/groups/members/index.js index 5629dcfcd..2ab6383aa 100644 --- a/app/soapbox/features/groups/members/index.js +++ b/app/soapbox/features/groups/members/index.js @@ -1,18 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; -import LoadingIndicator from '../../../components/loading_indicator'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchMembers, expandMembers, } from '../../../actions/groups'; -import { FormattedMessage } from 'react-intl'; +import LoadingIndicator from '../../../components/loading_indicator'; +import ScrollableList from '../../../components/scrollable_list'; import AccountContainer from '../../../containers/account_container'; import Column from '../../ui/components/column'; -import ScrollableList from '../../../components/scrollable_list'; const mapStateToProps = (state, { params: { id } }) => ({ group: state.getIn(['groups', id]), diff --git a/app/soapbox/features/groups/removed_accounts/index.js b/app/soapbox/features/groups/removed_accounts/index.js index d4d77a0fb..8e0d129e6 100644 --- a/app/soapbox/features/groups/removed_accounts/index.js +++ b/app/soapbox/features/groups/removed_accounts/index.js @@ -1,20 +1,21 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; -import LoadingIndicator from '../../../components/loading_indicator'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchRemovedAccounts, expandRemovedAccounts, removeRemovedAccount, } from '../../../actions/groups'; -import { FormattedMessage } from 'react-intl'; +import LoadingIndicator from '../../../components/loading_indicator'; +import ScrollableList from '../../../components/scrollable_list'; import AccountContainer from '../../../containers/account_container'; import Column from '../../ui/components/column'; -import ScrollableList from '../../../components/scrollable_list'; -import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ remove: { id: 'groups.removed_accounts', defaultMessage: 'Allow joining' }, diff --git a/app/soapbox/features/groups/sidebar_panel/index.js b/app/soapbox/features/groups/sidebar_panel/index.js index a091d876f..088fbee73 100644 --- a/app/soapbox/features/groups/sidebar_panel/index.js +++ b/app/soapbox/features/groups/sidebar_panel/index.js @@ -3,10 +3,12 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import Item from './item'; -import Icon from 'soapbox/components/icon'; import { Link } from 'react-router-dom'; +import Icon from 'soapbox/components/icon'; + +import Item from './item'; + const messages = defineMessages({ title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups You\'re In' }, show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' }, diff --git a/app/soapbox/features/groups/sidebar_panel/item.js b/app/soapbox/features/groups/sidebar_panel/item.js index 98b3fc92c..40ed8d421 100644 --- a/app/soapbox/features/groups/sidebar_panel/item.js +++ b/app/soapbox/features/groups/sidebar_panel/item.js @@ -2,9 +2,10 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; -import { shortNumberFormat } from '../../../utils/numbers'; import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { shortNumberFormat } from '../../../utils/numbers'; const messages = defineMessages({ new_statuses: { id: 'groups.sidebar-panel.item.view', defaultMessage: 'new posts' }, diff --git a/app/soapbox/features/groups/timeline/components/header.js b/app/soapbox/features/groups/timeline/components/header.js index 0355a1c4a..1b1faa08f 100644 --- a/app/soapbox/features/groups/timeline/components/header.js +++ b/app/soapbox/features/groups/timeline/components/header.js @@ -1,10 +1,12 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import Button from 'soapbox/components/button'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { NavLink } from 'react-router-dom'; + +import Button from 'soapbox/components/button'; + import DropdownMenuContainer from '../../../../containers/dropdown_menu_container'; const messages = defineMessages({ @@ -59,10 +61,11 @@ class Header extends ImmutablePureComponent { text: intl.formatMessage(messages.removed_accounts), to: `/groups/${group.get('id')}/removed_accounts`, icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, }, ]; - return ; + return ; } render() { diff --git a/app/soapbox/features/groups/timeline/components/panel.js b/app/soapbox/features/groups/timeline/components/panel.js index 3f431f559..9009bf33e 100644 --- a/app/soapbox/features/groups/timeline/components/panel.js +++ b/app/soapbox/features/groups/timeline/components/panel.js @@ -1,7 +1,8 @@ import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, defineMessages } from 'react-intl'; + import Icon from 'soapbox/components/icon'; const messages = defineMessages({ diff --git a/app/soapbox/features/groups/timeline/containers/header_container.js b/app/soapbox/features/groups/timeline/containers/header_container.js index 3602eebe9..bce37c3a9 100644 --- a/app/soapbox/features/groups/timeline/containers/header_container.js +++ b/app/soapbox/features/groups/timeline/containers/header_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; -import Header from '../components/header'; + import { joinGroup, leaveGroup } from '../../../../actions/groups'; +import Header from '../components/header'; const mapStateToProps = (state, { groupId }) => ({ group: state.getIn(['groups', groupId]), diff --git a/app/soapbox/features/groups/timeline/index.js b/app/soapbox/features/groups/timeline/index.js index c9f7d08cd..be58f51cd 100644 --- a/app/soapbox/features/groups/timeline/index.js +++ b/app/soapbox/features/groups/timeline/index.js @@ -1,17 +1,18 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { FormattedMessage, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import StatusListContainer from '../../ui/containers/status_list_container'; -import Column from '../../../components/column'; -import { FormattedMessage, injectIntl } from 'react-intl'; + +import ComposeFormContainer from '../../../../soapbox/features/compose/containers/compose_form_container'; import { connectGroupStream } from '../../../actions/streaming'; import { expandGroupTimeline } from '../../../actions/timelines'; -import MissingIndicator from '../../../components/missing_indicator'; -import LoadingIndicator from '../../../components/loading_indicator'; -import ComposeFormContainer from '../../../../soapbox/features/compose/containers/compose_form_container'; import Avatar from '../../../components/avatar'; +import Column from '../../../components/column'; +import LoadingIndicator from '../../../components/loading_indicator'; +import MissingIndicator from '../../../components/missing_indicator'; +import StatusListContainer from '../../ui/containers/status_list_container'; const mapStateToProps = (state, props) => { const me = state.get('me'); diff --git a/app/soapbox/features/hashtag_timeline/index.js b/app/soapbox/features/hashtag_timeline/index.js index a489c669e..ac4dfa2d8 100644 --- a/app/soapbox/features/hashtag_timeline/index.js +++ b/app/soapbox/features/hashtag_timeline/index.js @@ -1,13 +1,14 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { isEqual } from 'lodash'; import PropTypes from 'prop-types'; -import StatusListContainer from '../ui/containers/status_list_container'; +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { connectHashtagStream } from '../../actions/streaming'; +import { expandHashtagTimeline, clearTimeline } from '../../actions/timelines'; import Column from '../../components/column'; import ColumnHeader from '../../components/column_header'; -import { expandHashtagTimeline, clearTimeline } from '../../actions/timelines'; -import { FormattedMessage } from 'react-intl'; -import { connectHashtagStream } from '../../actions/streaming'; -import { isEqual } from 'lodash'; +import StatusListContainer from '../ui/containers/status_list_container'; const mapStateToProps = (state, props) => ({ hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0, diff --git a/app/soapbox/features/home_timeline/components/column_settings.js b/app/soapbox/features/home_timeline/components/column_settings.js index 892d4d813..78ca71919 100644 --- a/app/soapbox/features/home_timeline/components/column_settings.js +++ b/app/soapbox/features/home_timeline/components/column_settings.js @@ -1,10 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; -import SettingToggle from '../../notifications/components/setting_toggle'; + import IconButton from 'soapbox/components/icon_button'; +import SettingToggle from '../../notifications/components/setting_toggle'; + const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); diff --git a/app/soapbox/features/home_timeline/containers/column_settings_container.js b/app/soapbox/features/home_timeline/containers/column_settings_container.js index 69217a54c..0bcbafae8 100644 --- a/app/soapbox/features/home_timeline/containers/column_settings_container.js +++ b/app/soapbox/features/home_timeline/containers/column_settings_container.js @@ -1,10 +1,11 @@ import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; + import { getSettings, changeSetting, saveSettings, } from '../../../actions/settings'; +import ColumnSettings from '../components/column_settings'; const mapStateToProps = state => ({ settings: getSettings(state).get('home'), diff --git a/app/soapbox/features/home_timeline/index.js b/app/soapbox/features/home_timeline/index.js index f65198187..2eb1a49f3 100644 --- a/app/soapbox/features/home_timeline/index.js +++ b/app/soapbox/features/home_timeline/index.js @@ -1,15 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { expandHomeTimeline } from '../../actions/timelines'; -import PropTypes from 'prop-types'; -import StatusListContainer from '../ui/containers/status_list_container'; -import Column from '../../components/column'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { Link } from 'react-router-dom'; import { OrderedSet as ImmutableOrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { getFeatures } from 'soapbox/utils/features'; +import { expandHomeTimeline } from '../../actions/timelines'; +import Column from '../../components/column'; +import StatusListContainer from '../ui/containers/status_list_container'; + function FollowRecommendationsContainer() { return import(/* webpackChunkName: "features/follow_recommendations" */'soapbox/features/follow_recommendations/components/follow_recommendations_container'); } @@ -27,6 +29,7 @@ const mapStateToProps = state => { isPartial: state.getIn(['timelines', 'home', 'isPartial']), siteTitle: state.getIn(['instance', 'title']), isLoading: state.getIn(['timelines', 'home', 'isLoading'], true), + loadingFailed: state.getIn(['timelines', 'home', 'loadingFailed'], false), isEmpty: state.getIn(['timelines', 'home', 'items'], ImmutableOrderedSet()).isEmpty(), features, }; @@ -43,6 +46,7 @@ class HomeTimeline extends React.PureComponent { isPartial: PropTypes.bool, siteTitle: PropTypes.string, isLoading: PropTypes.bool, + loadingFailed: PropTypes.bool, isEmpty: PropTypes.bool, features: PropTypes.object.isRequired, }; @@ -99,9 +103,9 @@ class HomeTimeline extends React.PureComponent { } render() { - const { intl, siteTitle, isLoading, isEmpty, features } = this.props; + const { intl, siteTitle, isLoading, loadingFailed, isEmpty, features } = this.props; const { done } = this.state; - const showSuggestions = features.suggestions && isEmpty && !isLoading && !done; + const showSuggestions = features.suggestions && isEmpty && !isLoading && !loadingFailed && !done; return ( diff --git a/app/soapbox/features/import_data/components/csv_importer.js b/app/soapbox/features/import_data/components/csv_importer.js index aa7d967f4..c0cc0114f 100644 --- a/app/soapbox/features/import_data/components/csv_importer.js +++ b/app/soapbox/features/import_data/components/csv_importer.js @@ -1,8 +1,9 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { SimpleInput, SimpleForm, diff --git a/app/soapbox/features/import_data/index.js b/app/soapbox/features/import_data/index.js index 106c41cc0..5ca07e832 100644 --- a/app/soapbox/features/import_data/index.js +++ b/app/soapbox/features/import_data/index.js @@ -1,17 +1,20 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import PropTypes from 'prop-types'; -import Column from '../ui/components/column'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { importFollows, importBlocks, importMutes, } from 'soapbox/actions/import_data'; -import CSVImporter from './components/csv_importer'; import { getFeatures } from 'soapbox/utils/features'; +import Column from '../ui/components/column'; + +import CSVImporter from './components/csv_importer'; + const messages = defineMessages({ heading: { id: 'column.import_data', defaultMessage: 'Import data' }, submit: { id: 'import_data.actions.import', defaultMessage: 'Import' }, diff --git a/app/soapbox/features/introduction/index.js b/app/soapbox/features/introduction/index.js index 55408ceef..45af64e0c 100644 --- a/app/soapbox/features/introduction/index.js +++ b/app/soapbox/features/introduction/index.js @@ -1,9 +1,10 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ReactSwipeableViews from 'react-swipeable-views'; import classNames from 'classnames'; -import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import React from 'react'; import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import ReactSwipeableViews from 'react-swipeable-views'; + import { closeOnboarding } from '../../actions/onboarding'; const FrameWelcome = ({ domain, onNext }) => ( diff --git a/app/soapbox/features/landing_page/index.js b/app/soapbox/features/landing_page/index.js index 875bcd75b..463412557 100644 --- a/app/soapbox/features/landing_page/index.js +++ b/app/soapbox/features/landing_page/index.js @@ -1,8 +1,9 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; + import RegistrationForm from '../auth_login/components/registration_form'; import SiteBanner from '../public_layout/components/site_banner'; diff --git a/app/soapbox/features/list_adder/components/account.js b/app/soapbox/features/list_adder/components/account.js index 770e81e30..bbf792d17 100644 --- a/app/soapbox/features/list_adder/components/account.js +++ b/app/soapbox/features/list_adder/components/account.js @@ -1,11 +1,12 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { makeGetAccount } from '../../../selectors'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; -import { injectIntl } from 'react-intl'; +import { makeGetAccount } from '../../../selectors'; const makeMapStateToProps = () => { const getAccount = makeGetAccount(); diff --git a/app/soapbox/features/list_adder/components/list.js b/app/soapbox/features/list_adder/components/list.js index 9d5957f06..d9b23ec3e 100644 --- a/app/soapbox/features/list_adder/components/list.js +++ b/app/soapbox/features/list_adder/components/list.js @@ -1,13 +1,15 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import IconButton from '../../../components/icon_button'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; -import { removeFromListAdder, addToListAdder } from '../../../actions/lists'; +import { connect } from 'react-redux'; + import Icon from 'soapbox/components/icon'; +import { removeFromListAdder, addToListAdder } from '../../../actions/lists'; +import IconButton from '../../../components/icon_button'; + const messages = defineMessages({ remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, add: { id: 'lists.account.add', defaultMessage: 'Add to list' }, @@ -45,9 +47,9 @@ class List extends ImmutablePureComponent { let button; if (added) { - button = ; + button = ; } else { - button = ; + button = ; } return ( diff --git a/app/soapbox/features/list_adder/index.js b/app/soapbox/features/list_adder/index.js index af15b4485..3283ac04f 100644 --- a/app/soapbox/features/list_adder/index.js +++ b/app/soapbox/features/list_adder/index.js @@ -1,16 +1,19 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { setupListAdder, resetListAdder } from '../../actions/lists'; +import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import List from './components/list'; -import Account from './components/account'; + import IconButton from 'soapbox/components/icon_button'; + +import { setupListAdder, resetListAdder } from '../../actions/lists'; import NewListForm from '../lists/components/new_list_form'; import ColumnSubheading from '../ui/components/column_subheading'; + +import Account from './components/account'; +import List from './components/list'; // hack const getOrderedLists = createSelector([state => state.get('lists')], lists => { @@ -69,12 +72,12 @@ class ListAdder extends ImmutablePureComponent { const { accountId, listIds, intl } = this.props; return ( -
+

- +
diff --git a/app/soapbox/features/list_editor/components/account.js b/app/soapbox/features/list_editor/components/account.js index 1379ad336..eee56b97a 100644 --- a/app/soapbox/features/list_editor/components/account.js +++ b/app/soapbox/features/list_editor/components/account.js @@ -1,14 +1,15 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { makeGetAccount } from '../../../selectors'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import { removeFromListEditor, addToListEditor } from '../../../actions/lists'; import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; import IconButton from '../../../components/icon_button'; -import { defineMessages, injectIntl } from 'react-intl'; -import { removeFromListEditor, addToListEditor } from '../../../actions/lists'; +import { makeGetAccount } from '../../../selectors'; const messages = defineMessages({ remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, @@ -53,9 +54,9 @@ class Account extends ImmutablePureComponent { let button; if (added) { - button = ; + button = ; } else { - button = ; + button = ; } return ( diff --git a/app/soapbox/features/list_editor/components/edit_list_form.js b/app/soapbox/features/list_editor/components/edit_list_form.js index a3694508f..c0f893ff8 100644 --- a/app/soapbox/features/list_editor/components/edit_list_form.js +++ b/app/soapbox/features/list_editor/components/edit_list_form.js @@ -1,9 +1,10 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { changeListEditorTitle, submitListEditor } from '../../../actions/lists'; import Button from '../../../components/button'; -import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ title: { id: 'lists.edit.submit', defaultMessage: 'Change title' }, diff --git a/app/soapbox/features/list_editor/components/search.js b/app/soapbox/features/list_editor/components/search.js index c3d883745..e644acd37 100644 --- a/app/soapbox/features/list_editor/components/search.js +++ b/app/soapbox/features/list_editor/components/search.js @@ -1,11 +1,13 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl } from 'react-intl'; -import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists'; import classNames from 'classnames'; -import Icon from 'soapbox/components/icon'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import Button from 'soapbox/components/button'; +import Icon from 'soapbox/components/icon'; + +import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists'; const messages = defineMessages({ search: { id: 'lists.search', defaultMessage: 'Search among people you follow' }, diff --git a/app/soapbox/features/list_editor/index.js b/app/soapbox/features/list_editor/index.js index 004f41d59..0dad99ee8 100644 --- a/app/soapbox/features/list_editor/index.js +++ b/app/soapbox/features/list_editor/index.js @@ -1,16 +1,19 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, defineMessages } from 'react-intl'; -import { setupListEditor, clearListSuggestions, resetListEditor } from '../../actions/lists'; -import Account from './components/account'; -import Search from './components/search'; -import EditListForm from './components/edit_list_form'; -import ColumnSubheading from '../ui/components/column_subheading'; +import { connect } from 'react-redux'; + import IconButton from 'soapbox/components/icon_button'; +import { setupListEditor, clearListSuggestions, resetListEditor } from '../../actions/lists'; +import ColumnSubheading from '../ui/components/column_subheading'; + +import Account from './components/account'; +import EditListForm from './components/edit_list_form'; +import Search from './components/search'; + const mapStateToProps = state => ({ accountIds: state.getIn(['listEditor', 'accounts', 'items']), searchAccountIds: state.getIn(['listEditor', 'suggestions', 'items']), @@ -68,9 +71,9 @@ class ListEditor extends ImmutablePureComponent {

{intl.formatMessage(messages.editList)}

- +
-
+
diff --git a/app/soapbox/features/list_timeline/index.js b/app/soapbox/features/list_timeline/index.js index e45bcbcd6..584b11d45 100644 --- a/app/soapbox/features/list_timeline/index.js +++ b/app/soapbox/features/list_timeline/index.js @@ -1,19 +1,22 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import StatusListContainer from '../ui/containers/status_list_container'; -import Column from 'soapbox/features/ui/components/column'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import Button from 'soapbox/components/button'; +import Column from 'soapbox/features/ui/components/column'; + +import { fetchList, deleteList } from '../../actions/lists'; +import { openModal } from '../../actions/modals'; import { connectListStream } from '../../actions/streaming'; import { expandListTimeline } from '../../actions/timelines'; -import { fetchList, deleteList } from '../../actions/lists'; -import { openModal } from '../../actions/modal'; -import MissingIndicator from '../../components/missing_indicator'; import LoadingIndicator from '../../components/loading_indicator'; -import Button from 'soapbox/components/button'; +import MissingIndicator from '../../components/missing_indicator'; +import StatusListContainer from '../ui/containers/status_list_container'; const messages = defineMessages({ + deleteHeading: { id: 'confirmations.delete_list.heading', defaultMessage: 'Delete list' }, deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' }, deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' }, }); @@ -84,6 +87,8 @@ class ListTimeline extends React.PureComponent { const { id } = this.props.params; dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/trash.svg'), + heading: intl.formatMessage(messages.deleteHeading), message: intl.formatMessage(messages.deleteMessage), confirm: intl.formatMessage(messages.deleteConfirm), onConfirm: () => { diff --git a/app/soapbox/features/lists/components/new_list_form.js b/app/soapbox/features/lists/components/new_list_form.js index dd6075783..717bc757e 100644 --- a/app/soapbox/features/lists/components/new_list_form.js +++ b/app/soapbox/features/lists/components/new_list_form.js @@ -1,9 +1,10 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { changeListEditorTitle, submitListEditor } from '../../../actions/lists'; import Button from '../../../components/button'; -import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' }, diff --git a/app/soapbox/features/lists/index.js b/app/soapbox/features/lists/index.js index 4a26624ba..8e619869c 100644 --- a/app/soapbox/features/lists/index.js +++ b/app/soapbox/features/lists/index.js @@ -1,17 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import LoadingIndicator from '../../components/loading_indicator'; -import Column from '../ui/components/column'; -import { fetchLists } from '../../actions/lists'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; + +import { fetchLists } from '../../actions/lists'; +import LoadingIndicator from '../../components/loading_indicator'; +import ScrollableList from '../../components/scrollable_list'; +import Column from '../ui/components/column'; import ColumnLink from '../ui/components/column_link'; import ColumnSubheading from '../ui/components/column_subheading'; + import NewListForm from './components/new_list_form'; -import { createSelector } from 'reselect'; -import ScrollableList from '../../components/scrollable_list'; const messages = defineMessages({ heading: { id: 'column.lists', defaultMessage: 'Lists' }, @@ -71,7 +73,7 @@ class Lists extends ImmutablePureComponent { emptyMessage={emptyMessage} > {lists.map(list => - , + , )} diff --git a/app/soapbox/features/migration/index.js b/app/soapbox/features/migration/index.js new file mode 100644 index 000000000..a999ca030 --- /dev/null +++ b/app/soapbox/features/migration/index.js @@ -0,0 +1,115 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { moveAccount } from 'soapbox/actions/security'; +import snackbar from 'soapbox/actions/snackbar'; +import ShowablePassword from 'soapbox/components/showable_password'; +import { FieldsGroup, SimpleForm, TextInput } from 'soapbox/features/forms'; +import Column from 'soapbox/features/ui/components/column'; + +const messages = defineMessages({ + heading: { id: 'column.migration', defaultMessage: 'Account migration' }, + submit: { id: 'migration.submit', defaultMessage: 'Move followers' }, + moveAccountSuccess: { id: 'migration.move_account.success', defaultMessage: 'Account successfully moved.' }, + moveAccountFail: { id: 'migration.move_account.fail', defaultMessage: 'Account migration failed.' }, + acctFieldLabel: { id: 'migration.fields.acct.label', defaultMessage: 'Handle of the new account' }, + acctFieldPlaceholder: { id: 'migration.fields.acct.placeholder', defaultMessage: 'username@domain' }, + currentPasswordFieldLabel: { id: 'migration.fields.confirm_password.label', defaultMessage: 'Current password' }, +}); + +export default @connect() +@injectIntl +class Migration extends ImmutablePureComponent { + + static propTypes = { + dispatch: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + state = { + targetAccount: '', + password: '', + isLoading: false, + } + + handleInputChange = e => { + this.setState({ [e.target.name]: e.target.value }); + } + + clearForm = () => { + this.setState({ targetAccount: '', password: '' }); + } + + handleSubmit = e => { + const { targetAccount, password } = this.state; + const { dispatch, intl } = this.props; + this.setState({ isLoading: true }); + return dispatch(moveAccount(targetAccount, password)).then(() => { + this.clearForm(); + dispatch(snackbar.success(intl.formatMessage(messages.moveAccountSuccess))); + }).catch(error => { + dispatch(snackbar.error(intl.formatMessage(messages.moveAccountFail))); + }).then(() => { + this.setState({ isLoading: false }); + }); + } + + render() { + const { intl } = this.props; + + return ( + + +
+ +

+ + + + ), + }} + /> +

+ + +
+ +
+
+
+
+
+ ); + } + +} diff --git a/app/soapbox/features/mutes/index.js b/app/soapbox/features/mutes/index.js index 26278ec26..39b0b63f6 100644 --- a/app/soapbox/features/mutes/index.js +++ b/app/soapbox/features/mutes/index.js @@ -1,15 +1,16 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; -import LoadingIndicator from '../../components/loading_indicator'; -import Column from '../ui/components/column'; -import AccountContainer from '../../containers/account_container'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { fetchMutes, expandMutes } from '../../actions/mutes'; +import LoadingIndicator from '../../components/loading_indicator'; import ScrollableList from '../../components/scrollable_list'; +import AccountContainer from '../../containers/account_container'; +import Column from '../ui/components/column'; const messages = defineMessages({ heading: { id: 'column.mutes', defaultMessage: 'Muted users' }, diff --git a/app/soapbox/features/new_status/index.js b/app/soapbox/features/new_status/index.js index db53bb4ca..ef6092b11 100644 --- a/app/soapbox/features/new_status/index.js +++ b/app/soapbox/features/new_status/index.js @@ -1,8 +1,9 @@ +import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { openModal } from '../../actions/modal'; + +import { openModal } from '../../actions/modals'; const mapDispatchToProps = dispatch => ({ diff --git a/app/soapbox/features/notifications/components/clear_column_button.js b/app/soapbox/features/notifications/components/clear_column_button.js index 4218f662d..ebb27cfbe 100644 --- a/app/soapbox/features/notifications/components/clear_column_button.js +++ b/app/soapbox/features/notifications/components/clear_column_button.js @@ -1,6 +1,7 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import { FormattedMessage } from 'react-intl'; + import Icon from 'soapbox/components/icon'; export default class ClearColumnButton extends React.PureComponent { @@ -11,7 +12,7 @@ export default class ClearColumnButton extends React.PureComponent { render() { return ( - + ); } diff --git a/app/soapbox/features/notifications/components/column_settings.js b/app/soapbox/features/notifications/components/column_settings.js index aa55f5296..63093ec78 100644 --- a/app/soapbox/features/notifications/components/column_settings.js +++ b/app/soapbox/features/notifications/components/column_settings.js @@ -1,12 +1,14 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; -import ClearColumnButton from './clear_column_button'; -import SettingToggle from './setting_toggle'; -import MultiSettingToggle from './multi_setting_toggle'; + import IconButton from 'soapbox/components/icon_button'; +import ClearColumnButton from './clear_column_button'; +import MultiSettingToggle from './multi_setting_toggle'; +import SettingToggle from './setting_toggle'; + const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, }); @@ -22,6 +24,7 @@ class ColumnSettings extends React.PureComponent { onClear: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, supportsEmojiReacts: PropTypes.bool, + supportsBirthdays: PropTypes.bool, }; onPushChange = (path, checked) => { @@ -37,7 +40,7 @@ class ColumnSettings extends React.PureComponent { } render() { - const { intl, settings, pushSettings, onChange, onClear, onClose, supportsEmojiReacts } = this.props; + const { intl, settings, pushSettings, onChange, onClear, onClose, supportsEmojiReacts, supportsBirthdays } = this.props; const filterShowStr = ; const filterAdvancedStr = ; @@ -48,6 +51,7 @@ class ColumnSettings extends React.PureComponent { const soundSettings = [['sounds', 'follow'], ['sounds', 'favourite'], ['sounds', 'pleroma:emoji_reaction'], ['sounds', 'mention'], ['sounds', 'reblog'], ['sounds', 'poll'], ['sounds', 'move']]; const showPushSettings = pushSettings.get('browserSupport') && pushSettings.get('isSubscribed'); const pushStr = showPushSettings && ; + const birthdaysStr = ; return (
@@ -82,6 +86,17 @@ class ColumnSettings extends React.PureComponent {
+ {supportsBirthdays && +
+ + + +
+ +
+
+ } +
diff --git a/app/soapbox/features/notifications/components/filter_bar.js b/app/soapbox/features/notifications/components/filter_bar.js index 38f11feff..a95574036 100644 --- a/app/soapbox/features/notifications/components/filter_bar.js +++ b/app/soapbox/features/notifications/components/filter_bar.js @@ -1,9 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +import FilterBar from 'soapbox/components/filter_bar'; import Icon from 'soapbox/components/icon'; -const tooltips = defineMessages({ +const messages = defineMessages({ + all: { id: 'notifications.filter.all', defaultMessage: 'All' }, mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' }, favourites: { id: 'notifications.filter.favourites', defaultMessage: 'Likes' }, boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Reposts' }, @@ -14,7 +17,7 @@ const tooltips = defineMessages({ }); export default @injectIntl -class FilterBar extends React.PureComponent { +class NotificationFilterBar extends React.PureComponent { static propTypes = { selectFilter: PropTypes.func.isRequired, @@ -30,90 +33,67 @@ class FilterBar extends React.PureComponent { render() { const { selectedFilter, advancedMode, supportsEmojiReacts, intl } = this.props; - const renderedElement = !advancedMode ? ( -
- - -
- ) : ( -
- - - - {supportsEmojiReacts && } - - - - -
- ); - return renderedElement; + + const items = [ + { + text: intl.formatMessage(messages.all), + action: this.onClick('all'), + name: 'all', + }, + ]; + + if (!advancedMode) { + items.push({ + text: intl.formatMessage(messages.mentions), + action: this.onClick('mention'), + name: 'mention', + }); + } else { + items.push({ + text: , + title: intl.formatMessage(messages.mentions), + action: this.onClick('mention'), + name: 'mention', + }); + items.push({ + text: , + title: intl.formatMessage(messages.favourites), + action: this.onClick('favourite'), + name: 'favourite', + }); + if (supportsEmojiReacts) items.push({ + text: , + title: intl.formatMessage(messages.emoji_reacts), + action: this.onClick('pleroma:emoji_reaction'), + name: 'pleroma:emoji_reaction', + }); + items.push({ + text: , + title: intl.formatMessage(messages.boosts), + action: this.onClick('reblog'), + name: 'reblog', + }); + items.push({ + text: , + title: intl.formatMessage(messages.polls), + action: this.onClick('poll'), + name: 'poll', + }); + items.push({ + text: , + title: intl.formatMessage(messages.follows), + action: this.onClick('follow'), + name: 'follow', + }); + items.push({ + text: , + title: intl.formatMessage(messages.moves), + action: this.onClick('move'), + name: 'move', + }); + } + + return ; } } diff --git a/app/soapbox/features/notifications/components/follow_request.js b/app/soapbox/features/notifications/components/follow_request.js index c15d8de23..2a2e79269 100644 --- a/app/soapbox/features/notifications/components/follow_request.js +++ b/app/soapbox/features/notifications/components/follow_request.js @@ -1,12 +1,13 @@ +import PropTypes from 'prop-types'; import React, { Fragment } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; + import Avatar from 'soapbox/components/avatar'; import DisplayName from 'soapbox/components/display_name'; -import Permalink from 'soapbox/components/permalink'; import IconButton from 'soapbox/components/icon_button'; -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import Permalink from 'soapbox/components/permalink'; const messages = defineMessages({ authorize: { id: 'follow_request.authorize', defaultMessage: 'Authorize' }, @@ -48,8 +49,8 @@ class FollowRequest extends ImmutablePureComponent {
- - + +
diff --git a/app/soapbox/features/notifications/components/multi_setting_toggle.js b/app/soapbox/features/notifications/components/multi_setting_toggle.js index 9eae3d599..81a6f347d 100644 --- a/app/soapbox/features/notifications/components/multi_setting_toggle.js +++ b/app/soapbox/features/notifications/components/multi_setting_toggle.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Toggle from 'react-toggle'; diff --git a/app/soapbox/features/notifications/components/notification.js b/app/soapbox/features/notifications/components/notification.js index 18d24cd04..9f1598e24 100644 --- a/app/soapbox/features/notifications/components/notification.js +++ b/app/soapbox/features/notifications/components/notification.js @@ -1,16 +1,18 @@ -import React from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import StatusContainer from '../../../containers/status_container'; -import AccountContainer from '../../../containers/account_container'; -import { injectIntl, FormattedMessage } from 'react-intl'; -import Permalink from '../../../components/permalink'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import React from 'react'; import { HotKeys } from 'react-hotkeys'; -import FollowRequestContainer from '../containers/follow_request_container'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage } from 'react-intl'; + import Icon from 'soapbox/components/icon'; import emojify from 'soapbox/features/emoji/emoji'; -import classNames from 'classnames'; + +import Permalink from '../../../components/permalink'; +import AccountContainer from '../../../containers/account_container'; +import StatusContainer from '../../../containers/status_container'; +import FollowRequestContainer from '../containers/follow_request_container'; const notificationForScreenReader = (intl, message, timestamp) => { const output = [message]; @@ -174,7 +176,7 @@ class Notification extends ImmutablePureComponent { renderMention(notification) { return ( -
+
- +
diff --git a/app/soapbox/features/notifications/components/setting_toggle.js b/app/soapbox/features/notifications/components/setting_toggle.js index c9e649b6c..5b992092f 100644 --- a/app/soapbox/features/notifications/components/setting_toggle.js +++ b/app/soapbox/features/notifications/components/setting_toggle.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Toggle from 'react-toggle'; diff --git a/app/soapbox/features/notifications/containers/column_settings_container.js b/app/soapbox/features/notifications/containers/column_settings_container.js index b108d8b99..a60532d40 100644 --- a/app/soapbox/features/notifications/containers/column_settings_container.js +++ b/app/soapbox/features/notifications/containers/column_settings_container.js @@ -1,14 +1,17 @@ -import { connect } from 'react-redux'; import { defineMessages, injectIntl } from 'react-intl'; -import ColumnSettings from '../components/column_settings'; -import { getSettings, changeSetting } from '../../../actions/settings'; +import { connect } from 'react-redux'; + +import { getFeatures } from 'soapbox/utils/features'; + +import { openModal } from '../../../actions/modals'; import { setFilter } from '../../../actions/notifications'; import { clearNotifications } from '../../../actions/notifications'; import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications'; -import { openModal } from '../../../actions/modal'; -import { getFeatures } from 'soapbox/utils/features'; +import { getSettings, changeSetting } from '../../../actions/settings'; +import ColumnSettings from '../components/column_settings'; const messages = defineMessages({ + clearHeading: { id: 'notifications.clear_heading', defaultMessage: 'Clear notifications' }, clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' }, clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' }, }); @@ -21,6 +24,7 @@ const mapStateToProps = state => { settings: getSettings(state).get('notifications'), pushSettings: state.get('push_notifications'), supportsEmojiReacts: features.emojiReacts, + supportsBirthdays: features.birthdays, }; }; @@ -39,6 +43,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onClear() { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/eraser.svg'), + heading: intl.formatMessage(messages.clearHeading), message: intl.formatMessage(messages.clearMessage), confirm: intl.formatMessage(messages.clearConfirm), onConfirm: () => dispatch(clearNotifications()), diff --git a/app/soapbox/features/notifications/containers/filter_bar_container.js b/app/soapbox/features/notifications/containers/filter_bar_container.js index 231795c6f..82805136a 100644 --- a/app/soapbox/features/notifications/containers/filter_bar_container.js +++ b/app/soapbox/features/notifications/containers/filter_bar_container.js @@ -1,9 +1,11 @@ import { connect } from 'react-redux'; -import FilterBar from '../components/filter_bar'; -import { setFilter } from '../../../actions/notifications'; + import { getSettings } from 'soapbox/actions/settings'; import { getFeatures } from 'soapbox/utils/features'; +import { setFilter } from '../../../actions/notifications'; +import FilterBar from '../components/filter_bar'; + const makeMapStateToProps = state => { const settings = getSettings(state); const instance = state.get('instance'); diff --git a/app/soapbox/features/notifications/containers/follow_request_container.js b/app/soapbox/features/notifications/containers/follow_request_container.js index a539fc08c..c793ac3de 100644 --- a/app/soapbox/features/notifications/containers/follow_request_container.js +++ b/app/soapbox/features/notifications/containers/follow_request_container.js @@ -1,7 +1,9 @@ import { connect } from 'react-redux'; -import { makeGetAccount } from 'soapbox/selectors'; -import FollowRequest from '../components/follow_request'; + import { authorizeFollowRequest, rejectFollowRequest } from 'soapbox/actions/accounts'; +import { makeGetAccount } from 'soapbox/selectors'; + +import FollowRequest from '../components/follow_request'; const makeMapStateToProps = () => { const getAccount = makeGetAccount(); diff --git a/app/soapbox/features/notifications/containers/notification_container.js b/app/soapbox/features/notifications/containers/notification_container.js index fb407263a..f840f405c 100644 --- a/app/soapbox/features/notifications/containers/notification_container.js +++ b/app/soapbox/features/notifications/containers/notification_container.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux'; -import { makeGetNotification } from '../../../selectors'; -import Notification from '../components/notification'; -import { openModal } from '../../../actions/modal'; + +import { getSettings } from 'soapbox/actions/settings'; + import { mentionCompose } from '../../../actions/compose'; import { reblog, @@ -9,11 +9,13 @@ import { unreblog, unfavourite, } from '../../../actions/interactions'; +import { openModal } from '../../../actions/modals'; import { hideStatus, revealStatus, } from '../../../actions/statuses'; -import { getSettings } from 'soapbox/actions/settings'; +import { makeGetNotification } from '../../../selectors'; +import Notification from '../components/notification'; const makeMapStateToProps = () => { const getNotification = makeGetNotification(); diff --git a/app/soapbox/features/notifications/index.js b/app/soapbox/features/notifications/index.js index 58f567f7d..b3afd7c2f 100644 --- a/app/soapbox/features/notifications/index.js +++ b/app/soapbox/features/notifications/index.js @@ -1,26 +1,31 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { List as ImmutableList } from 'immutable'; +import { debounce } from 'lodash'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../../components/column'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; + +import { getSettings } from 'soapbox/actions/settings'; +import BirthdayReminders from 'soapbox/components/birthday_reminders'; +import SubNavigation from 'soapbox/components/sub_navigation'; +import PlaceholderNotification from 'soapbox/features/placeholder/components/placeholder_notification'; +import { getFeatures } from 'soapbox/utils/features'; + import { expandNotifications, scrollTopNotifications, dequeueNotifications, } from '../../actions/notifications'; -import NotificationContainer from './containers/notification_container'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import Column from '../../components/column'; +import LoadGap from '../../components/load_gap'; +import ScrollableList from '../../components/scrollable_list'; +import TimelineQueueButtonHeader from '../../components/timeline_queue_button_header'; + import ColumnSettingsContainer from './containers/column_settings_container'; import FilterBarContainer from './containers/filter_bar_container'; -import { createSelector } from 'reselect'; -import { List as ImmutableList } from 'immutable'; -import { debounce } from 'lodash'; -import ScrollableList from '../../components/scrollable_list'; -import LoadGap from '../../components/load_gap'; -import TimelineQueueButtonHeader from '../../components/timeline_queue_button_header'; -import { getSettings } from 'soapbox/actions/settings'; -import PlaceholderNotification from 'soapbox/features/placeholder/components/placeholder_notification'; -import SubNavigation from 'soapbox/components/sub_navigation'; +import NotificationContainer from './containers/notification_container'; const messages = defineMessages({ title: { id: 'column.notifications', defaultMessage: 'Notifications' }, @@ -42,14 +47,24 @@ const getNotifications = createSelector([ return notifications.filter(item => item !== null && allowedType === item.get('type')); }); -const mapStateToProps = state => ({ - showFilterBar: getSettings(state).getIn(['notifications', 'quickFilter', 'show']), - notifications: getNotifications(state), - isLoading: state.getIn(['notifications', 'isLoading'], true), - isUnread: state.getIn(['notifications', 'unread']) > 0, - hasMore: state.getIn(['notifications', 'hasMore']), - totalQueuedNotificationsCount: state.getIn(['notifications', 'totalQueuedNotificationsCount'], 0), -}); +const mapStateToProps = state => { + const settings = getSettings(state); + const instance = state.get('instance'); + const features = getFeatures(instance); + const showBirthdayReminders = settings.getIn(['notifications', 'birthdays', 'show']) && settings.getIn(['notifications', 'quickFilter', 'active']) === 'all' && features.birthdays; + const birthdays = showBirthdayReminders && state.getIn(['user_lists', 'birthday_reminders', state.get('me')]); + + return { + showFilterBar: settings.getIn(['notifications', 'quickFilter', 'show']), + notifications: getNotifications(state), + isLoading: state.getIn(['notifications', 'isLoading'], true), + isUnread: state.getIn(['notifications', 'unread']) > 0, + hasMore: state.getIn(['notifications', 'hasMore']), + totalQueuedNotificationsCount: state.getIn(['notifications', 'totalQueuedNotificationsCount'], 0), + showBirthdayReminders, + hasBirthdays: !!birthdays, + }; +}; export default @connect(mapStateToProps) @injectIntl @@ -65,6 +80,8 @@ class Notifications extends React.PureComponent { hasMore: PropTypes.bool, dequeueNotifications: PropTypes.func, totalQueuedNotificationsCount: PropTypes.number, + showBirthdayReminders: PropTypes.bool, + hasBirthdays: PropTypes.bool, }; componentWillUnmount() { @@ -101,15 +118,25 @@ class Notifications extends React.PureComponent { } handleMoveUp = id => { - const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1; + const { hasBirthdays } = this.props; + + let elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) - 1; + if (hasBirthdays) elementIndex++; this._selectChild(elementIndex, true); } handleMoveDown = id => { - const elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1; + const { hasBirthdays } = this.props; + + let elementIndex = this.props.notifications.findIndex(item => item !== null && item.get('id') === id) + 1; + if (hasBirthdays) elementIndex++; this._selectChild(elementIndex, false); } + handleMoveBelowBirthdays = () => { + this._selectChild(1, false); + } + _selectChild(index, align_top) { const container = this.column.node; const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`); @@ -134,7 +161,7 @@ class Notifications extends React.PureComponent { } render() { - const { intl, notifications, isLoading, hasMore, showFilterBar, totalQueuedNotificationsCount } = this.props; + const { intl, notifications, isLoading, hasMore, showFilterBar, totalQueuedNotificationsCount, showBirthdayReminders } = this.props; const emptyMessage = ; let scrollableContent = null; @@ -161,6 +188,13 @@ class Notifications extends React.PureComponent { onMoveDown={this.handleMoveDown} /> )); + + if (showBirthdayReminders) scrollableContent = scrollableContent.unshift( + , + ); } else { scrollableContent = null; } diff --git a/app/soapbox/features/pinned_statuses/index.js b/app/soapbox/features/pinned_statuses/index.js index bfa57417e..9309d24e2 100644 --- a/app/soapbox/features/pinned_statuses/index.js +++ b/app/soapbox/features/pinned_statuses/index.js @@ -1,14 +1,20 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { fetchPinnedStatuses } from '../../actions/pin_statuses'; -import Column from '../ui/components/column'; -import StatusList from '../../components/status_list'; -import { injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import MissingIndicator from 'soapbox/components/missing_indicator'; +import { fetchPinnedStatuses } from '../../actions/pin_statuses'; +import StatusList from '../../components/status_list'; +import Column from '../ui/components/column'; + +const messages = defineMessages({ + heading: { id: 'column.pins', defaultMessage: 'Pinned posts' }, +}); + const mapStateToProps = (state, { params }) => { const username = params.username || ''; const me = state.get('me'); @@ -37,7 +43,7 @@ class PinnedStatuses extends ImmutablePureComponent { } render() { - const { statusIds, hasMore, isMyAccount } = this.props; + const { intl, statusIds, hasMore, isMyAccount } = this.props; if (!isMyAccount) { return ( @@ -48,7 +54,7 @@ class PinnedStatuses extends ImmutablePureComponent { } return ( - + +
+
+ {generateText(randomIntFromInterval(5, 25))} +

+ {generateText(randomIntFromInterval(5, 75))} +

+ + {generateText(randomIntFromInterval(5, 15))} + +
+
+ ); + } + +} diff --git a/app/soapbox/features/placeholder/components/placeholder_chat.js b/app/soapbox/features/placeholder/components/placeholder_chat.js new file mode 100644 index 000000000..a3763b416 --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_chat.js @@ -0,0 +1,32 @@ +import React from 'react'; + +import { randomIntFromInterval, generateText } from '../utils'; + +import PlaceholderAvatar from './placeholder_avatar'; +import PlaceholderDisplayName from './placeholder_display_name'; + +export default class PlaceholderAccount extends React.Component { + + render() { + const messageLength = randomIntFromInterval(5, 75); + + return ( +
+
+
+
+
+ +
+ + + {generateText(messageLength)} + +
+
+
+
+ ); + } + +} diff --git a/app/soapbox/features/placeholder/components/placeholder_display_name.js b/app/soapbox/features/placeholder/components/placeholder_display_name.js index 96216ffab..8278297c9 100644 --- a/app/soapbox/features/placeholder/components/placeholder_display_name.js +++ b/app/soapbox/features/placeholder/components/placeholder_display_name.js @@ -1,5 +1,6 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; + import { randomIntFromInterval, generateText } from '../utils'; export default class DisplayName extends React.Component { diff --git a/app/soapbox/features/placeholder/components/placeholder_hashtag.js b/app/soapbox/features/placeholder/components/placeholder_hashtag.js index 66f11a479..81c788238 100644 --- a/app/soapbox/features/placeholder/components/placeholder_hashtag.js +++ b/app/soapbox/features/placeholder/components/placeholder_hashtag.js @@ -1,4 +1,5 @@ import React from 'react'; + import { generateText, randomIntFromInterval } from '../utils'; export default class PlaceholderHashtag extends React.Component { diff --git a/app/soapbox/features/placeholder/components/placeholder_material_status.js b/app/soapbox/features/placeholder/components/placeholder_material_status.js index f55d9d086..3199d42aa 100644 --- a/app/soapbox/features/placeholder/components/placeholder_material_status.js +++ b/app/soapbox/features/placeholder/components/placeholder_material_status.js @@ -1,4 +1,5 @@ import React from 'react'; + import PlaceholderStatus from './placeholder_status'; export default class PlaceholderMaterialStatus extends React.Component { diff --git a/app/soapbox/features/placeholder/components/placeholder_media_gallery.js b/app/soapbox/features/placeholder/components/placeholder_media_gallery.js new file mode 100644 index 000000000..c1b2dd3b9 --- /dev/null +++ b/app/soapbox/features/placeholder/components/placeholder_media_gallery.js @@ -0,0 +1,96 @@ +import { Map as ImmutableMap } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; + +export default class PlaceholderMediaGallery extends React.Component { + + static propTypes = { + media: ImmutablePropTypes.map.isRequired, + defaultWidth: PropTypes.number, + } + + state = { + width: this.props.defaultWidth, + }; + + handleRef = (node) => { + if (node) { + this.setState({ + width: node.offsetWidth, + }); + } + } + + getSizeData = size => { + const { defaultWidth } = this.props; + const width = this.state.width || defaultWidth; + + const style = {}; + let itemsDimensions = []; + + if (size === 1) { + style.height = width * 9 / 16; + + itemsDimensions = [ + { w: '100%', h: '100%' }, + ]; + } else if (size === 2) { + style.height = width / 2; + + itemsDimensions = [ + { w: '50%', h: '100%', r: '2px' }, + { w: '50%', h: '100%', l: '2px' }, + ]; + } else if (size === 3) { + style.height = width; + + itemsDimensions = [ + { w: '50%', h: '50%', b: '2px', r: '2px' }, + { w: '50%', h: '50%', b: '2px', l: '2px' }, + { w: '100%', h: '50%', t: '2px' }, + ]; + } else if (size >= 4) { + style.height = width; + + itemsDimensions = [ + { w: '50%', h: '50%', b: '2px', r: '2px' }, + { w: '50%', h: '50%', b: '2px', l: '2px' }, + { w: '50%', h: '50%', t: '2px', r: '2px' }, + { w: '50%', h: '50%', t: '2px', l: '2px' }, + ]; + } + + return ImmutableMap({ + style, + itemsDimensions, + size, + width, + }); + } + + renderItem = (dimensions, i) => { + const width = dimensions.w; + const height = dimensions.h; + const top = dimensions.t || 'auto'; + const right = dimensions.r || 'auto'; + const bottom = dimensions.b || 'auto'; + const left = dimensions.l || 'auto'; + const float = dimensions.float || 'left'; + const position = dimensions.pos || 'relative'; + + return
; + } + + render() { + const { media } = this.props; + const sizeData = this.getSizeData(media.size); + + return ( +
+ {media.take(4).map((_, i) => this.renderItem(sizeData.get('itemsDimensions')[i], i))} +
+ ); + } + +} diff --git a/app/soapbox/features/placeholder/components/placeholder_notification.js b/app/soapbox/features/placeholder/components/placeholder_notification.js index 813124e0e..aea226c4d 100644 --- a/app/soapbox/features/placeholder/components/placeholder_notification.js +++ b/app/soapbox/features/placeholder/components/placeholder_notification.js @@ -1,7 +1,9 @@ import React from 'react'; -import PlaceholderAccount from './placeholder_account'; + import { randomIntFromInterval, generateText } from '../utils'; +import PlaceholderAccount from './placeholder_account'; + export default class PlaceholderNotification extends React.Component { shouldComponentUpdate() { diff --git a/app/soapbox/features/placeholder/components/placeholder_status.js b/app/soapbox/features/placeholder/components/placeholder_status.js index 1fea821ca..52346f1e4 100644 --- a/app/soapbox/features/placeholder/components/placeholder_status.js +++ b/app/soapbox/features/placeholder/components/placeholder_status.js @@ -1,4 +1,5 @@ import React from 'react'; + import PlaceholderAvatar from './placeholder_avatar'; import PlaceholderDisplayName from './placeholder_display_name'; import PlaceholderStatusContent from './placeholder_status_content'; diff --git a/app/soapbox/features/placeholder/components/placeholder_status_content.js b/app/soapbox/features/placeholder/components/placeholder_status_content.js index f3f4e951c..02d2bb206 100644 --- a/app/soapbox/features/placeholder/components/placeholder_status_content.js +++ b/app/soapbox/features/placeholder/components/placeholder_status_content.js @@ -1,5 +1,6 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; + import { randomIntFromInterval, generateText } from '../utils'; export default class PlaceholderStatusContent extends React.Component { @@ -13,7 +14,7 @@ export default class PlaceholderStatusContent extends React.Component { const { maxLength, minLength } = this.props; const length = randomIntFromInterval(maxLength, minLength); - return( + return (
{generateText(length)}
diff --git a/app/soapbox/features/preferences/index.js b/app/soapbox/features/preferences/index.js index 14e41fbfe..77b59b4b5 100644 --- a/app/soapbox/features/preferences/index.js +++ b/app/soapbox/features/preferences/index.js @@ -1,12 +1,12 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSettings, changeSetting } from 'soapbox/actions/settings'; -import { getFeatures } from 'soapbox/utils/features'; -import Column from '../ui/components/column'; +import SettingsCheckbox from 'soapbox/components/settings_checkbox'; import { SimpleForm, FieldsGroup, @@ -14,7 +14,10 @@ import { RadioItem, SelectDropdown, } from 'soapbox/features/forms'; -import SettingsCheckbox from 'soapbox/components/settings_checkbox'; +import SettingToggle from 'soapbox/features/notifications/components/setting_toggle'; +import { getFeatures } from 'soapbox/utils/features'; + +import Column from '../ui/components/column'; export const languages = { en: 'English', @@ -29,6 +32,7 @@ export const languages = { da: 'Dansk', de: 'Deutsch', el: 'Ελληνικά', + 'en-Shaw': '𐑖𐑱𐑝𐑾𐑯', eo: 'Esperanto', es: 'Español', eu: 'Euskara', @@ -121,6 +125,11 @@ class Preferences extends ImmutablePureComponent { dispatch(changeSetting(['defaultContentType'], e.target.value)); } + onToggleChange = (key, checked) => { + const { dispatch } = this.props; + dispatch(changeSetting(key, checked)); + } + render() { const { settings, features, intl } = this.props; @@ -133,6 +142,20 @@ class Preferences extends ImmutablePureComponent { return ( + +
+
+ } /> +
+ +
+ } /> +
+ +
+ } /> +
+
} @@ -262,10 +285,6 @@ class Preferences extends ImmutablePureComponent { hint={} path={['demetricator']} /> - } - path={['isDeveloper']} - />
diff --git a/app/soapbox/features/public_layout/components/footer.js b/app/soapbox/features/public_layout/components/footer.js index 1c6d38354..2290276a5 100644 --- a/app/soapbox/features/public_layout/components/footer.js +++ b/app/soapbox/features/public_layout/components/footer.js @@ -1,10 +1,11 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { List as ImmutableList } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import { List as ImmutableList } from 'immutable'; + import { getSettings } from 'soapbox/actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; diff --git a/app/soapbox/features/public_layout/components/header.js b/app/soapbox/features/public_layout/components/header.js index 3c87739e6..2cb003b84 100644 --- a/app/soapbox/features/public_layout/components/header.js +++ b/app/soapbox/features/public_layout/components/header.js @@ -1,17 +1,19 @@ +import PropTypes from 'prop-types'; import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { Link } from 'react-router-dom'; -import LoginForm from 'soapbox/features/auth_login/components/login_form'; -import SiteLogo from './site_logo'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; import { defineMessages, injectIntl } from 'react-intl'; -import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + import { logIn, verifyCredentials } from 'soapbox/actions/auth'; import { fetchInstance } from 'soapbox/actions/instance'; -import OtpAuthForm from 'soapbox/features/auth_login/components/otp_auth_form'; import IconButton from 'soapbox/components/icon_button'; +import LoginForm from 'soapbox/features/auth_login/components/login_form'; +import OtpAuthForm from 'soapbox/features/auth_login/components/otp_auth_form'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; + +import SiteLogo from './site_logo'; const messages = defineMessages({ home: { id: 'header.home.label', defaultMessage: 'Home' }, @@ -88,7 +90,7 @@ class Header extends ImmutablePureComponent { { mfa_auth_needed &&
- +
diff --git a/app/soapbox/features/public_layout/components/site_banner.js b/app/soapbox/features/public_layout/components/site_banner.js index 2f0775bed..cdf685a9d 100644 --- a/app/soapbox/features/public_layout/components/site_banner.js +++ b/app/soapbox/features/public_layout/components/site_banner.js @@ -1,6 +1,7 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; + import { getSoapboxConfig } from 'soapbox/actions/soapbox'; const mapStateToProps = (state, props) => ({ diff --git a/app/soapbox/features/public_layout/components/site_logo.js b/app/soapbox/features/public_layout/components/site_logo.js index 14a24f691..0ee382e7b 100644 --- a/app/soapbox/features/public_layout/components/site_logo.js +++ b/app/soapbox/features/public_layout/components/site_logo.js @@ -1,6 +1,7 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; + import { getSoapboxConfig } from 'soapbox/actions/soapbox'; const mapStateToProps = (state, props) => ({ diff --git a/app/soapbox/features/public_layout/index.js b/app/soapbox/features/public_layout/index.js index fa33ef48a..19d83e3b9 100644 --- a/app/soapbox/features/public_layout/index.js +++ b/app/soapbox/features/public_layout/index.js @@ -1,19 +1,22 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { connect } from 'react-redux'; import { Switch, Route, Redirect } from 'react-router-dom'; + +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { NotificationsContainer, ModalContainer, } from 'soapbox/features/ui/util/async-components'; -import Header from './components/header'; -import Footer from './components/footer'; -import LandingPage from '../landing_page'; -import AboutPage from '../about'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { isStandalone } from 'soapbox/utils/state'; +import AboutPage from '../about'; +import LandingPage from '../landing_page'; + +import Footer from './components/footer'; +import Header from './components/header'; + const mapStateToProps = (state, props) => ({ soapbox: getSoapboxConfig(state), standalone: isStandalone(state), diff --git a/app/soapbox/features/public_timeline/components/column_settings.js b/app/soapbox/features/public_timeline/components/column_settings.js index 51c267b7f..a2b2ca6f8 100644 --- a/app/soapbox/features/public_timeline/components/column_settings.js +++ b/app/soapbox/features/public_timeline/components/column_settings.js @@ -1,8 +1,10 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; + import IconButton from 'soapbox/components/icon_button'; + import SettingToggle from '../../notifications/components/setting_toggle'; const messages = defineMessages({ diff --git a/app/soapbox/features/public_timeline/containers/column_settings_container.js b/app/soapbox/features/public_timeline/containers/column_settings_container.js index ac001bcab..63a629007 100644 --- a/app/soapbox/features/public_timeline/containers/column_settings_container.js +++ b/app/soapbox/features/public_timeline/containers/column_settings_container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; -import ColumnSettings from '../components/column_settings'; + import { getSettings, changeSetting } from '../../../actions/settings'; +import ColumnSettings from '../components/column_settings'; const mapStateToProps = state => ({ settings: getSettings(state).get('public'), diff --git a/app/soapbox/features/public_timeline/index.js b/app/soapbox/features/public_timeline/index.js index 1b3b0e358..224151b17 100644 --- a/app/soapbox/features/public_timeline/index.js +++ b/app/soapbox/features/public_timeline/index.js @@ -1,17 +1,20 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; -import StatusListContainer from '../ui/containers/status_list_container'; -import Column from '../../components/column'; -import ColumnSettings from './containers/column_settings_container'; -import Accordion from 'soapbox/features/ui/components/accordion'; -import PinnedHostsPicker from '../remote_timeline/components/pinned_hosts_picker'; -import { expandPublicTimeline } from '../../actions/timelines'; -import { connectPublicStream } from '../../actions/streaming'; +import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; + import { changeSetting, getSettings } from 'soapbox/actions/settings'; import SubNavigation from 'soapbox/components/sub_navigation'; +import Accordion from 'soapbox/features/ui/components/accordion'; + +import { connectPublicStream } from '../../actions/streaming'; +import { expandPublicTimeline } from '../../actions/timelines'; +import Column from '../../components/column'; +import PinnedHostsPicker from '../remote_timeline/components/pinned_hosts_picker'; +import StatusListContainer from '../ui/containers/status_list_container'; + +import ColumnSettings from './containers/column_settings_container'; const messages = defineMessages({ title: { id: 'column.public', defaultMessage: 'Fediverse timeline' }, diff --git a/app/soapbox/features/reactions/index.js b/app/soapbox/features/reactions/index.js deleted file mode 100644 index 73c4472ca..000000000 --- a/app/soapbox/features/reactions/index.js +++ /dev/null @@ -1,126 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import LoadingIndicator from '../../components/loading_indicator'; -import MissingIndicator from '../../components/missing_indicator'; -import { fetchFavourites, fetchReactions } from '../../actions/interactions'; -import { fetchStatus } from '../../actions/statuses'; -import { FormattedMessage } from 'react-intl'; -import AccountContainer from '../../containers/account_container'; -import Column from '../ui/components/column'; -import ScrollableList from '../../components/scrollable_list'; -import { makeGetStatus } from '../../selectors'; - -const mapStateToProps = (state, props) => { - const getStatus = makeGetStatus(); - const status = getStatus(state, { - id: props.params.statusId, - username: props.params.username, - }); - - const favourites = state.getIn(['user_lists', 'favourited_by', props.params.statusId]); - const reactions = state.getIn(['user_lists', 'reactions', props.params.statusId]); - const allReactions = favourites && reactions && ImmutableOrderedSet(favourites ? [{ accounts: favourites, count: favourites.size, name: '👍' }] : []).union(reactions || []); - - return { - status, - reactions: allReactions, - accounts: allReactions && (props.params.reaction - ? allReactions.find(reaction => reaction.name === props.params.reaction).accounts.map(account => ({ id: account, reaction: props.params.reaction })) - : allReactions.map(reaction => reaction.accounts.map(account => ({ id: account, reaction: reaction.name }))).flatten()), - }; -}; - -export default @connect(mapStateToProps) -class Reactions extends ImmutablePureComponent { - - static contextTypes = { - router: PropTypes.object.isRequired, - }; - - static propTypes = { - params: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, - reactions: ImmutablePropTypes.orderedSet, - accounts: ImmutablePropTypes.orderedSet, - status: ImmutablePropTypes.map, - }; - - fetchData = () => { - const { dispatch, params } = this.props; - const { statusId } = params; - - dispatch(fetchFavourites(statusId)); - dispatch(fetchReactions(statusId)); - dispatch(fetchStatus(statusId)); - } - - componentDidMount() { - this.fetchData(); - } - - componentDidUpdate(prevProps) { - const { params } = this.props; - - if (params.statusId !== prevProps.params.statusId) { - this.fetchData(); - } - } - - handleFilterChange = (reaction) => () => { - const { params } = this.props; - const { username, statusId } = params; - - this.context.router.history.replace(`/@${username}/posts/${statusId}/reactions/${reaction}`); - }; - - render() { - const { params, reactions, accounts, status } = this.props; - const { username, statusId } = params; - - const back = `/@${username}/posts/${statusId}`; - - if (!accounts) { - return ( - - - - ); - } - - if (!status) { - return ( - - - - ); - } - - const emptyMessage = ; - - return ( - - { - reactions.size > 0 && ( -
- - {reactions?.filter(reaction => reaction.count).map(reaction => )} -
- ) - } - - {accounts.map((account) => - , - )} - -
- ); - } - -} diff --git a/app/soapbox/features/reblogs/index.js b/app/soapbox/features/reblogs/index.js deleted file mode 100644 index ea536940c..000000000 --- a/app/soapbox/features/reblogs/index.js +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import LoadingIndicator from '../../components/loading_indicator'; -import MissingIndicator from '../../components/missing_indicator'; -import { fetchReblogs } from '../../actions/interactions'; -import { fetchStatus } from '../../actions/statuses'; -import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; -import AccountContainer from '../../containers/account_container'; -import Column from '../ui/components/column'; -import ScrollableList from '../../components/scrollable_list'; -import { makeGetStatus } from '../../selectors'; - -const messages = defineMessages({ - heading: { id: 'column.reblogs', defaultMessage: 'Reposts' }, -}); - -const mapStateToProps = (state, props) => { - const getStatus = makeGetStatus(); - const status = getStatus(state, { - id: props.params.statusId, - username: props.params.username, - }); - - return { - status, - accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]), - }; -}; - -export default @connect(mapStateToProps) -@injectIntl -class Reblogs extends ImmutablePureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - params: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, - accountIds: ImmutablePropTypes.orderedSet, - status: ImmutablePropTypes.map, - }; - - fetchData = () => { - const { dispatch, params } = this.props; - const { statusId } = params; - - dispatch(fetchReblogs(statusId)); - dispatch(fetchStatus(statusId)); - } - - componentDidMount() { - this.fetchData(); - } - - componentDidUpdate(prevProps) { - const { params } = this.props; - - if (params.statusId !== prevProps.params.statusId) { - this.fetchData(); - } - } - - render() { - const { intl, accountIds, status } = this.props; - - if (!accountIds) { - return ( - - - - ); - } - - if (!status) { - return ( - - - - ); - } - - const emptyMessage = ; - - return ( - - - {accountIds.map(id => - , - )} - - - ); - } - -} diff --git a/app/soapbox/features/register_invite/index.js b/app/soapbox/features/register_invite/index.js index f9d0bf1e0..486647bd2 100644 --- a/app/soapbox/features/register_invite/index.js +++ b/app/soapbox/features/register_invite/index.js @@ -1,7 +1,8 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import RegistrationForm from 'soapbox/features/auth_login/components/registration_form'; const mapStateToProps = state => { diff --git a/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.js b/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.js index a9af2c57c..a5858de9e 100644 --- a/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.js +++ b/app/soapbox/features/remote_timeline/components/pinned_hosts_picker.js @@ -1,11 +1,12 @@ 'use strict'; -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; + import { getSettings } from 'soapbox/actions/settings'; const mapStateToProps = state => { diff --git a/app/soapbox/features/remote_timeline/index.js b/app/soapbox/features/remote_timeline/index.js index 337081bb6..d6b6ab2ef 100644 --- a/app/soapbox/features/remote_timeline/index.js +++ b/app/soapbox/features/remote_timeline/index.js @@ -1,14 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; -import StatusListContainer from '../ui/containers/status_list_container'; -import Column from 'soapbox/features/ui/components/column'; -import PinnedHostsPicker from './components/pinned_hosts_picker'; -import IconButton from 'soapbox/components/icon_button'; -import { expandRemoteTimeline } from '../../actions/timelines'; -import { connectRemoteStream } from '../../actions/streaming'; +import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; +import IconButton from 'soapbox/components/icon_button'; +import Column from 'soapbox/features/ui/components/column'; + +import { connectRemoteStream } from '../../actions/streaming'; +import { expandRemoteTimeline } from '../../actions/timelines'; +import StatusListContainer from '../ui/containers/status_list_container'; + +import PinnedHostsPicker from './components/pinned_hosts_picker'; const messages = defineMessages({ title: { id: 'column.remote', defaultMessage: 'Federated timeline' }, @@ -87,7 +90,7 @@ class RemoteTimeline extends React.PureComponent { {!pinned &&
- + { + const getAccount = makeGetAccount(); + + const mapStateToProps = (state, { accountId }) => { + const account = getAccount(state, accountId); + + return { + added: !!account && state.getIn(['compose', 'to']).includes(account.get('acct')), + account, + }; + }; + + return mapStateToProps; +}; + +const mapDispatchToProps = (dispatch, { accountId }) => ({ + onRemove: () => dispatch(removeFromMentions(accountId)), + onAdd: () => dispatch(addToMentions(accountId)), + fetchAccount: () => dispatch(fetchAccount(accountId)), +}); + +export default @connect(makeMapStateToProps, mapDispatchToProps) +@injectIntl +class Account extends ImmutablePureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + intl: PropTypes.object.isRequired, + onRemove: PropTypes.func.isRequired, + onAdd: PropTypes.func.isRequired, + added: PropTypes.bool, + author: PropTypes.bool, + }; + + static defaultProps = { + added: false, + }; + + componentDidMount() { + const { account, accountId } = this.props; + + if (accountId && !account) { + this.props.fetchAccount(accountId); + } + } + + render() { + const { account, intl, onRemove, onAdd, added, author } = this.props; + + if (!account) return null; + + let button; + + if (added) { + button = ; + } else { + button = ; + } + + return ( +
+
+
+
+ +
+ +
+ {!author && button} +
+
+
+ ); + } + +} diff --git a/app/soapbox/features/report/components/status_check_box.js b/app/soapbox/features/report/components/status_check_box.js index 8543d7b0d..fcb73c902 100644 --- a/app/soapbox/features/report/components/status_check_box.js +++ b/app/soapbox/features/report/components/status_check_box.js @@ -1,11 +1,12 @@ -import React from 'react'; +import noop from 'lodash/noop'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Toggle from 'react-toggle'; -import noop from 'lodash/noop'; + import StatusContent from '../../../components/status_content'; -import { MediaGallery, Video, Audio } from '../../ui/util/async-components'; import Bundle from '../../ui/components/bundle'; +import { MediaGallery, Video, Audio } from '../../ui/util/async-components'; export default class StatusCheckBox extends React.PureComponent { diff --git a/app/soapbox/features/report/containers/status_check_box_container.js b/app/soapbox/features/report/containers/status_check_box_container.js index b3ef4cbd6..75daf7e2d 100644 --- a/app/soapbox/features/report/containers/status_check_box_container.js +++ b/app/soapbox/features/report/containers/status_check_box_container.js @@ -1,7 +1,8 @@ -import { connect } from 'react-redux'; -import StatusCheckBox from '../components/status_check_box'; -import { toggleStatusReport } from '../../../actions/reports'; import { Set as ImmutableSet } from 'immutable'; +import { connect } from 'react-redux'; + +import { toggleStatusReport } from '../../../actions/reports'; +import StatusCheckBox from '../components/status_check_box'; const mapStateToProps = (state, { id }) => ({ status: state.getIn(['statuses', id]), diff --git a/app/soapbox/features/scheduled_statuses/builder.js b/app/soapbox/features/scheduled_statuses/builder.js index 196a0f6f2..05cef642c 100644 --- a/app/soapbox/features/scheduled_statuses/builder.js +++ b/app/soapbox/features/scheduled_statuses/builder.js @@ -1,4 +1,5 @@ import { fromJS } from 'immutable'; + import { normalizeStatus } from 'soapbox/actions/importer/normalizer'; import { makeGetAccount } from 'soapbox/selectors'; diff --git a/app/soapbox/features/scheduled_statuses/components/scheduled_status.js b/app/soapbox/features/scheduled_statuses/components/scheduled_status.js index 5226125fc..b47e2b6d0 100644 --- a/app/soapbox/features/scheduled_statuses/components/scheduled_status.js +++ b/app/soapbox/features/scheduled_statuses/components/scheduled_status.js @@ -1,17 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import StatusContent from 'soapbox/components/status_content'; -import { buildStatus } from '../builder'; import classNames from 'classnames'; -import RelativeTimestamp from 'soapbox/components/relative_timestamp'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; import { Link, NavLink } from 'react-router-dom'; -import { getDomain } from 'soapbox/utils/accounts'; + +import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; import Avatar from 'soapbox/components/avatar'; import DisplayName from 'soapbox/components/display_name'; -import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; +import RelativeTimestamp from 'soapbox/components/relative_timestamp'; +import StatusContent from 'soapbox/components/status_content'; import PollPreview from 'soapbox/features/ui/components/poll_preview'; +import { getDomain } from 'soapbox/utils/accounts'; + +import { buildStatus } from '../builder'; + import ScheduledStatusActionBar from './scheduled_status_action_bar'; const mapStateToProps = (state, props) => { @@ -25,7 +27,7 @@ export default @connect(mapStateToProps) class ScheduledStatus extends ImmutablePureComponent { render() { - const { status, showThread, account, ...other } = this.props; + const { status, account, ...other } = this.props; if (!status.get('account')) return null; const statusUrl = `/scheduled_statuses/${status.get('id')}`; @@ -67,19 +69,15 @@ class ScheduledStatus extends ImmutablePureComponent { collapsable /> - + {status.get('media_attachments').size > 0 && ( + + )} {status.get('poll') && } - {showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && ( - - )} -
diff --git a/app/soapbox/features/scheduled_statuses/components/scheduled_status_action_bar.js b/app/soapbox/features/scheduled_statuses/components/scheduled_status_action_bar.js index e248c0eaf..2579cc338 100644 --- a/app/soapbox/features/scheduled_statuses/components/scheduled_status_action_bar.js +++ b/app/soapbox/features/scheduled_statuses/components/scheduled_status_action_bar.js @@ -1,15 +1,21 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import IconButton from 'soapbox/components/icon_button'; -import { defineMessages, injectIntl } from 'react-intl'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import { openModal } from 'soapbox/actions/modals'; import { cancelScheduledStatus } from 'soapbox/actions/scheduled_statuses'; +import { getSettings } from 'soapbox/actions/settings'; +import IconButton from 'soapbox/components/icon_button'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; const messages = defineMessages({ cancel: { id: 'scheduled_status.cancel', defaultMessage: 'Cancel' }, + deleteConfirm: { id: 'confirmations.scheduled_status_delete.confirm', defaultMessage: 'Cancel' }, + deleteHeading: { id: 'confirmations.scheduled_status_delete.heading', defaultMessage: 'Cancel scheduled post' }, + deleteMessage: { id: 'confirmations.scheduled_status_delete.message', defaultMessage: 'Are you sure you want to cancel this scheduled post?' }, }); const mapStateToProps = state => { @@ -19,8 +25,26 @@ const mapStateToProps = state => { }; }; -export default @connect(mapStateToProps, null, null, { forwardRef: true }) -@injectIntl +const mapDispatchToProps = (dispatch, { intl }) => ({ + onCancelClick: (status) => { + dispatch((_, getState) => { + + const deleteModal = getSettings(getState()).get('deleteModal'); + if (!deleteModal) { + dispatch(cancelScheduledStatus(status.get('id'))); + } else { + dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/calendar-stats.svg'), + heading: intl.formatMessage(messages.deleteHeading), + message: intl.formatMessage(messages.deleteMessage), + confirm: intl.formatMessage(messages.deleteConfirm), + onConfirm: () => dispatch(cancelScheduledStatus(status.get('id'))), + })); + } + }); + }, +}); + class ScheduledStatusActionBar extends ImmutablePureComponent { static contextTypes = { @@ -31,11 +55,13 @@ class ScheduledStatusActionBar extends ImmutablePureComponent { status: ImmutablePropTypes.map.isRequired, intl: PropTypes.object.isRequired, me: SoapboxPropTypes.me, + onCancelClick: PropTypes.func.isRequired, }; handleCancelClick = e => { - const { status, dispatch } = this.props; - dispatch(cancelScheduledStatus(status.get('id'))); + const { status, onCancelClick } = this.props; + + onCancelClick(status); } render() { @@ -47,7 +73,7 @@ class ScheduledStatusActionBar extends ImmutablePureComponent {
@@ -56,3 +82,6 @@ class ScheduledStatusActionBar extends ImmutablePureComponent { } } + + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ScheduledStatusActionBar)); diff --git a/app/soapbox/features/scheduled_statuses/index.js b/app/soapbox/features/scheduled_statuses/index.js index 03a4496ca..8b2fe3a56 100644 --- a/app/soapbox/features/scheduled_statuses/index.js +++ b/app/soapbox/features/scheduled_statuses/index.js @@ -1,14 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ScrollableList from 'soapbox/components/scrollable_list'; -import { fetchScheduledStatuses, expandScheduledStatuses } from '../../actions/scheduled_statuses'; -import ScheduledStatus from './components/scheduled_status'; import { debounce } from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import ScrollableList from 'soapbox/components/scrollable_list'; + +import { fetchScheduledStatuses, expandScheduledStatuses } from '../../actions/scheduled_statuses'; +import Column from '../ui/components/column'; + +import ScheduledStatus from './components/scheduled_status'; const messages = defineMessages({ heading: { id: 'column.scheduled_statuses', defaultMessage: 'Scheduled Posts' }, diff --git a/app/soapbox/features/search/components/filter_bar.js b/app/soapbox/features/search/components/filter_bar.js deleted file mode 100644 index 917ad99c7..000000000 --- a/app/soapbox/features/search/components/filter_bar.js +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage, injectIntl } from 'react-intl'; - -export default @injectIntl -class FilterBar extends React.PureComponent { - - static propTypes = { - selectFilter: PropTypes.func.isRequired, - selectedFilter: PropTypes.string.isRequired, - }; - - onClick(searchType) { - return () => this.props.selectFilter(searchType); - } - - render() { - const { selectedFilter } = this.props; - - return ( -
- - - -
- ); - } - -} diff --git a/app/soapbox/features/search/components/header.js b/app/soapbox/features/search/components/header.js index 6c047ffb1..14f9d5ddb 100644 --- a/app/soapbox/features/search/components/header.js +++ b/app/soapbox/features/search/components/header.js @@ -1,8 +1,8 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; import { NavLink } from 'react-router-dom'; const mapStateToProps = state => ({ diff --git a/app/soapbox/features/search/index.js b/app/soapbox/features/search/index.js index cb1148460..60b4655eb 100644 --- a/app/soapbox/features/search/index.js +++ b/app/soapbox/features/search/index.js @@ -1,6 +1,7 @@ +import PropTypes from 'prop-types'; import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; -import PropTypes from 'prop-types'; + import Column from 'soapbox/components/column'; import ColumnHeader from 'soapbox/components/column_header'; import SearchContainer from 'soapbox/features/compose/containers/search_container'; diff --git a/app/soapbox/features/security/index.js b/app/soapbox/features/security/index.js index 2327f70a4..887c16242 100644 --- a/app/soapbox/features/security/index.js +++ b/app/soapbox/features/security/index.js @@ -1,26 +1,28 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedDate } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; -import Button from 'soapbox/components/button'; -import { - SimpleForm, - SimpleInput, - FieldsGroup, - TextInput, -} from 'soapbox/features/forms'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedDate } from 'react-intl'; +import { connect } from 'react-redux'; + import { changeEmail, changePassword, deleteAccount, } from 'soapbox/actions/security'; import { fetchOAuthTokens, revokeOAuthTokenById } from 'soapbox/actions/security'; -import { fetchUserMfaSettings } from '../../actions/mfa'; +import { getSettings } from 'soapbox/actions/settings'; import snackbar from 'soapbox/actions/snackbar'; -import { changeSetting, getSettings } from 'soapbox/actions/settings'; +import Button from 'soapbox/components/button'; +import ShowablePassword from 'soapbox/components/showable_password'; +import { + SimpleForm, + FieldsGroup, + TextInput, +} from 'soapbox/features/forms'; + +import { fetchMfa } from '../../actions/mfa'; +import Column from '../ui/components/column'; /* Security settings page for user account @@ -64,6 +66,7 @@ const messages = defineMessages({ const mapStateToProps = state => ({ settings: getSettings(state), tokens: state.getIn(['security', 'tokens']), + mfa: state.getIn(['security', 'mfa']), }); export default @connect(mapStateToProps) @@ -141,8 +144,7 @@ class ChangeEmailForm extends ImmutablePureComponent { onChange={this.handleInputChange} value={this.state.email} /> - {intl.formatMessage(messages.passwordHeader)}
- - - { - this.props.dispatch(changeSetting(['otpEnabled'], response.data.settings.enabled)); - }).catch(e => e); - } - static contextTypes = { router: PropTypes.object, }; static propTypes = { intl: PropTypes.object.isRequired, - settings: ImmutablePropTypes.map.isRequired, + mfa: ImmutablePropTypes.map.isRequired, }; handleMfaClick = e => { this.context.router.history.push('../auth/mfa'); } + componentDidMount() { + this.props.dispatch(fetchMfa()); + } + render() { - const { intl, settings } = this.props; + const { intl, mfa } = this.props; return (

{intl.formatMessage(messages.mfaHeader)}

- { settings.get('otpEnabled') === false ? + {!mfa.getIn(['settings', 'totp']) ?

{intl.formatMessage(messages.mfa_setup_hint)} @@ -392,8 +388,7 @@ class DeactivateAccount extends ImmutablePureComponent {

- ({ backup_codes: state.getIn(['auth', 'backup_codes', 'codes']), - settings: getSettings(state), + mfa: state.getIn(['security', 'mfa']), }); export default @connect(mapStateToProps) @injectIntl class MfaForm extends ImmutablePureComponent { - constructor(props) { - super(props); - this.props.dispatch(fetchUserMfaSettings()).then(response => { - this.props.dispatch(changeSetting(['otpEnabled'], response.data.settings.enabled)); - // this.setState({ otpEnabled: response.data.settings.enabled }); - }).catch(e => e); - this.handleSetupProceedClick = this.handleSetupProceedClick.bind(this); - } - static contextTypes = { router: PropTypes.object, }; @@ -71,7 +67,7 @@ class MfaForm extends ImmutablePureComponent { static propTypes = { intl: PropTypes.object.isRequired, dispatch: PropTypes.func.isRequired, - settings: ImmutablePropTypes.map.isRequired, + mfa: ImmutablePropTypes.map.isRequired, }; state = { @@ -79,20 +75,29 @@ class MfaForm extends ImmutablePureComponent { } handleSetupProceedClick = e => { - e.preventDefault(); this.setState({ displayOtpForm: true }); + e.preventDefault(); + } + + componentDidMount() { + this.props.dispatch(fetchMfa()); } render() { - const { intl, settings } = this.props; + const { intl, mfa } = this.props; const { displayOtpForm } = this.state; return ( - { settings.get('otpEnabled') === true && } - { settings.get('otpEnabled') === false && } - { settings.get('otpEnabled') === false && displayOtpForm && } + {mfa.getIn(['settings', 'totp']) ? ( + + ) : ( + <> + + {displayOtpForm && } + + )} ); } @@ -115,43 +120,62 @@ class DisableOtpForm extends ImmutablePureComponent { state = { password: '', + isLoading: false, } handleInputChange = e => { this.setState({ [e.target.name]: e.target.value }); } - handleOtpDisableClick = e => { - e.preventDefault(); + handleSubmit = e => { const { password } = this.state; const { dispatch, intl } = this.props; - dispatch(disableToptSetup(password)).then(response => { + + this.setState({ isLoading: true }); + + dispatch(disableMfa('totp', password)).then(() => { + dispatch(snackbar.success(intl.formatMessage(messages.mfaDisableSuccess))); this.context.router.history.push('../auth/edit'); - dispatch(changeSetting(['otpEnabled'], false)); }).catch(error => { dispatch(snackbar.error(intl.formatMessage(messages.disableFail))); + this.setState({ isLoading: false }); }); + + e.preventDefault(); } render() { const { intl } = this.props; + const { isLoading, password } = this.state; return ( - -
+
+

-
-
- + + + } + disabled={isLoading} name='password' onChange={this.handleInputChange} + value={password} + required /> -
- +
+
+ +
); } @@ -177,8 +201,9 @@ class EnableOtpForm extends ImmutablePureComponent { componentDidMount() { const { dispatch, intl } = this.props; - dispatch(fetchBackupCodes()).then(response => { - this.setState({ backupCodes: response.data.codes }); + + dispatch(fetchBackupCodes()).then(({ codes: backupCodes }) => { + this.setState({ backupCodes }); }).catch(error => { dispatch(snackbar.error(intl.formatMessage(messages.codesFail))); }); @@ -186,6 +211,7 @@ class EnableOtpForm extends ImmutablePureComponent { handleCancelClick = e => { this.context.router.history.push('../auth/edit'); + e.preventDefault(); } render() { @@ -193,8 +219,8 @@ class EnableOtpForm extends ImmutablePureComponent { const { backupCodes, displayOtpForm } = this.state; return ( - -
+
+

@@ -208,28 +234,28 @@ class EnableOtpForm extends ImmutablePureComponent {
- { backupCodes.length ? + {backupCodes.length > 0 ? (
{backupCodes.map((code, i) => (
{code}
))} -
: +
+ ) : ( - } + )}
- { !displayOtpForm && + {!displayOtpForm && (
- } -
-
+ )} +
+
); } @@ -250,7 +276,7 @@ class OtpConfirmForm extends ImmutablePureComponent { state = { password: '', - done: false, + isLoading: false, code: '', qrCodeURI: '', confirm_key: '', @@ -258,8 +284,9 @@ class OtpConfirmForm extends ImmutablePureComponent { componentDidMount() { const { dispatch, intl } = this.props; - dispatch(fetchToptSetup()).then(response => { - this.setState({ qrCodeURI: response.data.provisioning_uri, confirm_key: response.data.key }); + + dispatch(setupMfa('totp')).then(data => { + this.setState({ qrCodeURI: data.provisioning_uri, confirm_key: data.key }); }).catch(error => { dispatch(snackbar.error(intl.formatMessage(messages.qrFail))); }); @@ -269,64 +296,96 @@ class OtpConfirmForm extends ImmutablePureComponent { this.setState({ [e.target.name]: e.target.value }); } - handleOtpConfirmClick = e => { + handleCancelClick = e => { + this.context.router.history.push('../auth/edit'); e.preventDefault(); - const { code, password } = this.state; + } + + handleSubmit = e => { const { dispatch, intl } = this.props; - dispatch(confirmToptSetup(code, password)).then(response => { - dispatch(changeSetting(['otpEnabled'], true)); + const { code, password } = this.state; + + this.setState({ isLoading: true }); + + dispatch(confirmMfa('totp', code, password)).then(() => { + dispatch(snackbar.success(intl.formatMessage(messages.mfaConfirmSuccess))); + this.context.router.history.push('../auth/edit'); }).catch(error => { dispatch(snackbar.error(intl.formatMessage(messages.confirmFail))); + this.setState({ isLoading: false }); }); + + e.preventDefault(); } render() { const { intl } = this.props; - const { qrCodeURI, confirm_key } = this.state; + const { isLoading, qrCodeURI, confirm_key, password, code } = this.state; return ( - -
+
+

-
+
- +
- +
+ {confirm_key} +
+
-
{confirm_key}

-
} + placeholder={intl.formatMessage(messages.codePlaceholder)} onChange={this.handleInputChange} autoComplete='off' + value={code} + disabled={isLoading} + required /> - -
- } + placeholder={intl.formatMessage(messages.passwordPlaceholder)} onChange={this.handleInputChange} + value={password} + disabled={isLoading} + required />
-
-
- + +
); } diff --git a/app/soapbox/features/server_info/index.js b/app/soapbox/features/server_info/index.js index f6c6193ae..ca532a966 100644 --- a/app/soapbox/features/server_info/index.js +++ b/app/soapbox/features/server_info/index.js @@ -1,11 +1,12 @@ +import PropTypes from 'prop-types'; import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import PropTypes from 'prop-types'; + import Column from '../ui/components/column'; -import PromoPanel from '../ui/components/promo_panel'; import LinkFooter from '../ui/components/link_footer'; +import PromoPanel from '../ui/components/promo_panel'; const messages = defineMessages({ heading: { id: 'column.info', defaultMessage: 'Server information' }, diff --git a/app/soapbox/features/share/index.js b/app/soapbox/features/share/index.js index 7649f5540..ff6dd18f3 100644 --- a/app/soapbox/features/share/index.js +++ b/app/soapbox/features/share/index.js @@ -1,7 +1,8 @@ +import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; -import PropTypes from 'prop-types'; + import { openComposeWithText } from '../../actions/compose'; const mapDispatchToProps = dispatch => ({ diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index a414c96e7..56258f5ad 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -1,10 +1,11 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; -import Picker from 'emoji-mart/dist-es/components/picker/picker'; -import Overlay from 'react-overlays/lib/Overlay'; import classNames from 'classnames'; import { supportsPassiveEvents } from 'detect-passive-events'; +import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; +import Overlay from 'react-overlays/lib/Overlay'; + import Icon from 'soapbox/components/icon'; const messages = defineMessages({ @@ -67,8 +68,10 @@ class IconPickerMenu extends React.PureComponent { if (!c) return; // Nice and dirty hack to display the icons - c.querySelectorAll('button.emoji-mart-emoji > span').forEach(elem => { - elem.innerHTML = ``; + c.querySelectorAll('button.emoji-mart-emoji > img').forEach(elem => { + const newIcon = document.createElement('span'); + newIcon.innerHTML = ``; + elem.parentNode.replaceChild(newIcon, elem); }); } diff --git a/app/soapbox/features/soapbox_config/components/site_preview.js b/app/soapbox/features/soapbox_config/components/site_preview.js index ee8714588..a51604695 100644 --- a/app/soapbox/features/soapbox_config/components/site_preview.js +++ b/app/soapbox/features/soapbox_config/components/site_preview.js @@ -1,6 +1,7 @@ +import classNames from 'classnames'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import classNames from 'classnames'; + import { defaultSettings } from 'soapbox/actions/settings'; import { brandColorToCSS } from 'soapbox/utils/theme'; diff --git a/app/soapbox/features/soapbox_config/index.js b/app/soapbox/features/soapbox_config/index.js index b3537e488..5ec7f0b39 100644 --- a/app/soapbox/features/soapbox_config/index.js +++ b/app/soapbox/features/soapbox_config/index.js @@ -1,10 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; +import { supportsPassiveEvents } from 'detect-passive-events'; +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; +import { SketchPicker } from 'react-color'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import Column from '../ui/components/column'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import Overlay from 'react-overlays/lib/Overlay'; +import { connect } from 'react-redux'; + +import { updateConfig } from 'soapbox/actions/admin'; +import { uploadMedia } from 'soapbox/actions/media'; +import snackbar from 'soapbox/actions/snackbar'; +import { makeDefaultConfig } from 'soapbox/actions/soapbox'; +import Icon from 'soapbox/components/icon'; import { SimpleForm, FieldsGroup, @@ -15,21 +24,15 @@ import { FormPropTypes, Checkbox, } from 'soapbox/features/forms'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; -import { updateConfig } from 'soapbox/actions/admin'; -import Icon from 'soapbox/components/icon'; -import { makeDefaultConfig } from 'soapbox/actions/soapbox'; -import { getFeatures } from 'soapbox/utils/features'; -import { uploadMedia } from 'soapbox/actions/media'; -import { SketchPicker } from 'react-color'; -import Overlay from 'react-overlays/lib/Overlay'; -import { isMobile } from 'soapbox/is_mobile'; -import { supportsPassiveEvents } from 'detect-passive-events'; -import Accordion from '../ui/components/accordion'; -import SitePreview from './components/site_preview'; import ThemeToggle from 'soapbox/features/ui/components/theme_toggle'; +import { isMobile } from 'soapbox/is_mobile'; +import { getFeatures } from 'soapbox/utils/features'; + +import Accordion from '../ui/components/accordion'; +import Column from '../ui/components/column'; + import IconPickerDropdown from './components/icon_picker_dropdown'; -import snackbar from 'soapbox/actions/snackbar'; +import SitePreview from './components/site_preview'; const messages = defineMessages({ heading: { id: 'column.soapbox_config', defaultMessage: 'Soapbox config' }, @@ -318,13 +321,13 @@ class SoapboxConfig extends ImmutablePureComponent { value={field.get('url')} onChange={this.handlePromoItemChange(i, 'url', field)} /> - +
)) }
- +
@@ -351,13 +354,13 @@ class SoapboxConfig extends ImmutablePureComponent { value={field.get('url')} onChange={this.handleHomeFooterItemChange(i, 'url', field)} /> - +
)) }
- +
@@ -390,13 +393,13 @@ class SoapboxConfig extends ImmutablePureComponent { value={address.get('note')} onChange={this.handleCryptoAdressItemChange(i, 'note', address)} /> - +
)) }
- +
diff --git a/app/soapbox/features/status/components/action_bar.js b/app/soapbox/features/status/components/action_bar.js index 272668a45..5908ab6ad 100644 --- a/app/soapbox/features/status/components/action_bar.js +++ b/app/soapbox/features/status/components/action_bar.js @@ -1,17 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { openModal } from '../../../actions/modal'; import PropTypes from 'prop-types'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import IconButton from '../../../components/icon_button'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; import { defineMessages, injectIntl } from 'react-intl'; -import { isStaff, isAdmin } from 'soapbox/utils/accounts'; -import { isUserTouching } from 'soapbox/is_mobile'; +import { connect } from 'react-redux'; + import EmojiSelector from 'soapbox/components/emoji_selector'; +import { isUserTouching } from 'soapbox/is_mobile'; +import { isStaff, isAdmin } from 'soapbox/utils/accounts'; import { getReactForStatus } from 'soapbox/utils/emoji_reacts'; import { getFeatures } from 'soapbox/utils/features'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; + +import { openModal } from '../../../actions/modals'; +import IconButton from '../../../components/icon_button'; +import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -51,6 +53,7 @@ const messages = defineMessages({ reactionCry: { id: 'status.reactions.cry', defaultMessage: 'Sad' }, reactionWeary: { id: 'status.reactions.weary', defaultMessage: 'Weary' }, emojiPickerExpand: { id: 'status.reactions_expand', defaultMessage: 'Select emoji' }, + quotePost: { id: 'status.quote', defaultMessage: 'Quote post' }, }); const mapStateToProps = state => { @@ -66,9 +69,12 @@ const mapStateToProps = state => { }; }; -const mapDispatchToProps = (dispatch) => ({ - onOpenUnauthorizedModal() { - dispatch(openModal('UNAUTHORIZED')); +const mapDispatchToProps = (dispatch, { status }) => ({ + onOpenUnauthorizedModal(action) { + dispatch(openModal('UNAUTHORIZED', { + action, + ap_id: status.get('url'), + })); }, }); @@ -82,6 +88,7 @@ class ActionBar extends React.PureComponent { status: ImmutablePropTypes.map.isRequired, onReply: PropTypes.func.isRequired, onReblog: PropTypes.func.isRequired, + onQuote: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired, onEmojiReact: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, @@ -121,20 +128,29 @@ class ActionBar extends React.PureComponent { } handleReplyClick = () => { - const { me } = this.props; + const { me, onReply, onOpenUnauthorizedModal } = this.props; if (me) { - this.props.onReply(this.props.status); + onReply(this.props.status); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('REPLY'); } } handleReblogClick = (e) => { - const { me } = this.props; + const { me, onReblog, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.onReblog(this.props.status, e); + onReblog(status, e); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('REBLOG'); + } + } + + handleQuoteClick = () => { + const { me, onQuote, onOpenUnauthorizedModal, status } = this.props; + if (me) { + onQuote(status, this.context.router.history); + } else { + onOpenUnauthorizedModal('REBLOG'); } } @@ -143,11 +159,11 @@ class ActionBar extends React.PureComponent { } handleFavouriteClick = () => { - const { me } = this.props; + const { me, onFavourite, onOpenUnauthorizedModal } = this.props; if (me) { - this.props.onFavourite(this.props.status); + onFavourite(status); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('FAVOURITE'); } } @@ -184,11 +200,11 @@ class ActionBar extends React.PureComponent { handleReactClick = emoji => { return e => { - const { me } = this.props; + const { me, onEmojiReact, onOpenUnauthorizedModal, status } = this.props; if (me) { - this.props.onEmojiReact(this.props.status, emoji); + onEmojiReact(status, emoji); } else { - this.props.onOpenUnauthorizedModal(); + onOpenUnauthorizedModal('FAVOURITE'); } this.setState({ emojiSelectorVisible: false, emojiSelectorFocused: false }); }; @@ -329,127 +345,133 @@ class ActionBar extends React.PureComponent { // }); } - if (features.bookmarks) { - menu.push({ - text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), - action: this.handleBookmarkClick, - icon: require(status.get('bookmarked') ? '@tabler/icons/icons/bookmark-off.svg' : '@tabler/icons/icons/bookmark.svg'), - }); - } - - menu.push(null); - - if (ownAccount) { - if (publicStatus) { + if (me) { + if (features.bookmarks) { menu.push({ - text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), - action: this.handlePinClick, - icon: require(mutingConversation ? '@tabler/icons/icons/pinned-off.svg' : '@tabler/icons/icons/pin.svg'), + text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), + action: this.handleBookmarkClick, + icon: require(status.get('bookmarked') ? '@tabler/icons/icons/bookmark-off.svg' : '@tabler/icons/icons/bookmark.svg'), + }); + } + + menu.push(null); + + if (ownAccount) { + if (publicStatus) { + menu.push({ + text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), + action: this.handlePinClick, + icon: require(mutingConversation ? '@tabler/icons/icons/pinned-off.svg' : '@tabler/icons/icons/pin.svg'), + }); + } else { + if (status.get('visibility') === 'private') { + menu.push({ + text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), + action: this.handleReblogClick, + icon: require('@tabler/icons/icons/repeat.svg'), + }); + } + } + + menu.push(null); + menu.push({ + text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), + action: this.handleConversationMuteClick, + icon: require(mutingConversation ? '@tabler/icons/icons/bell.svg' : '@tabler/icons/icons/bell-off.svg'), + }); + menu.push(null); + menu.push({ + text: intl.formatMessage(messages.delete), + action: this.handleDeleteClick, + icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, + }); + menu.push({ + text: intl.formatMessage(messages.redraft), + action: this.handleRedraftClick, + icon: require('@tabler/icons/icons/edit.svg'), + destructive: true, }); } else { - if (status.get('visibility') === 'private') { + menu.push({ + text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), + action: this.handleMentionClick, + icon: require('feather-icons/dist/icons/at-sign.svg'), + }); + + if (status.getIn(['account', 'pleroma', 'accepts_chat_messages'], false) === true) { menu.push({ - text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog_private), - action: this.handleReblogClick, - icon: require('@tabler/icons/icons/repeat.svg'), + text: intl.formatMessage(messages.chat, { name: status.getIn(['account', 'username']) }), + action: this.handleChatClick, + icon: require('@tabler/icons/icons/messages.svg'), + }); + } else { + menu.push({ + text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), + action: this.handleDirectClick, + icon: require('@tabler/icons/icons/mail.svg'), }); } - } - menu.push(null); - menu.push({ - text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), - action: this.handleConversationMuteClick, - icon: require(mutingConversation ? '@tabler/icons/icons/bell.svg' : '@tabler/icons/icons/bell-off.svg'), - }); - menu.push(null); - menu.push({ - text: intl.formatMessage(messages.delete), - action: this.handleDeleteClick, - icon: require('@tabler/icons/icons/trash.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.redraft), - action: this.handleRedraftClick, - icon: require('@tabler/icons/icons/edit.svg'), - }); - } else { - menu.push({ - text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), - action: this.handleMentionClick, - icon: require('feather-icons/dist/icons/at-sign.svg'), - }); - - if (status.getIn(['account', 'pleroma', 'accepts_chat_messages'], false) === true) { + menu.push(null); menu.push({ - text: intl.formatMessage(messages.chat, { name: status.getIn(['account', 'username']) }), - action: this.handleChatClick, - icon: require('@tabler/icons/icons/messages.svg'), + text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), + action: this.handleMuteClick, + icon: require('@tabler/icons/icons/circle-x.svg'), }); - } else { menu.push({ - text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), - action: this.handleDirectClick, - icon: require('@tabler/icons/icons/mail.svg'), + text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), + action: this.handleBlockClick, + icon: require('@tabler/icons/icons/ban.svg'), + }); + menu.push({ + text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), + action: this.handleReport, + icon: require('@tabler/icons/icons/flag.svg'), }); } - menu.push(null); - menu.push({ - text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), - action: this.handleMuteClick, - icon: require('@tabler/icons/icons/circle-x.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), - action: this.handleBlockClick, - icon: require('@tabler/icons/icons/ban.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), - action: this.handleReport, - icon: require('@tabler/icons/icons/flag.svg'), - }); - } + if (isStaff) { + menu.push(null); - if (isStaff) { - menu.push(null); + if (isAdmin) { + menu.push({ + text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), + href: `/pleroma/admin/#/users/${status.getIn(['account', 'id'])}/`, + icon: require('icons/gavel.svg'), + }); + menu.push({ + text: intl.formatMessage(messages.admin_status), + href: `/pleroma/admin/#/statuses/${status.get('id')}/`, + icon: require('@tabler/icons/icons/pencil.svg'), + }); + } - if (isAdmin) { menu.push({ - text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), - href: `/pleroma/admin/#/users/${status.getIn(['account', 'id'])}/`, - icon: require('icons/gavel.svg'), + text: intl.formatMessage(status.get('sensitive') === false ? messages.markStatusSensitive : messages.markStatusNotSensitive), + action: this.handleToggleStatusSensitivity, + icon: require('@tabler/icons/icons/alert-triangle.svg'), }); - menu.push({ - text: intl.formatMessage(messages.admin_status), - href: `/pleroma/admin/#/statuses/${status.get('id')}/`, - icon: require('@tabler/icons/icons/pencil.svg'), - }); - } - menu.push({ - text: intl.formatMessage(status.get('sensitive') === false ? messages.markStatusSensitive : messages.markStatusNotSensitive), - action: this.handleToggleStatusSensitivity, - icon: require('@tabler/icons/icons/alert-triangle.svg'), - }); - - if (!ownAccount) { - menu.push({ - text: intl.formatMessage(messages.deactivateUser, { name: status.getIn(['account', 'username']) }), - action: this.handleDeactivateUser, - icon: require('@tabler/icons/icons/user-off.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.deleteUser, { name: status.getIn(['account', 'username']) }), - action: this.handleDeleteUser, - icon: require('@tabler/icons/icons/user-minus.svg'), - }); - menu.push({ - text: intl.formatMessage(messages.deleteStatus), - action: this.handleDeleteStatus, - icon: require('@tabler/icons/icons/trash.svg'), - }); + if (!ownAccount) { + menu.push({ + text: intl.formatMessage(messages.deactivateUser, { name: status.getIn(['account', 'username']) }), + action: this.handleDeactivateUser, + icon: require('@tabler/icons/icons/user-off.svg'), + }); + menu.push({ + text: intl.formatMessage(messages.deleteUser, { name: status.getIn(['account', 'username']) }), + action: this.handleDeleteUser, + icon: require('@tabler/icons/icons/user-minus.svg'), + destructive: true, + }); + menu.push({ + text: intl.formatMessage(messages.deleteStatus), + action: this.handleDeleteStatus, + icon: require('@tabler/icons/icons/trash.svg'), + destructive: true, + }); + } } } @@ -475,6 +497,48 @@ class ActionBar extends React.PureComponent { const reblog_disabled = (status.get('visibility') === 'direct' || status.get('visibility') === 'private'); + let reblogButton; + + if (me && features.quotePosts) { + const reblogMenu = [ + { + text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog), + action: this.handleReblogClick, + icon: require('@tabler/icons/icons/repeat.svg'), + }, + { + text: intl.formatMessage(messages.quotePost), + action: this.handleQuoteClick, + icon: require('@tabler/icons/icons/quote.svg'), + }, + ]; + + reblogButton = ( + + ); + } else { + reblogButton = ( + + ); + } + return (
@@ -486,14 +550,7 @@ class ActionBar extends React.PureComponent { />
- + {reblogButton}
diff --git a/app/soapbox/features/status/components/card.js b/app/soapbox/features/status/components/card.js index 4e870640e..1f55f3785 100644 --- a/app/soapbox/features/status/components/card.js +++ b/app/soapbox/features/status/components/card.js @@ -1,9 +1,11 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { is, fromJS } from 'immutable'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import punycode from 'punycode'; + import classnames from 'classnames'; +import { is, fromJS } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; + import Icon from 'soapbox/components/icon'; const IDNA_PREFIX = 'xn--'; @@ -171,7 +173,7 @@ export default class Card extends React.PureComponent { const description = (
- {title} + {title}

{trim(card.get('description') || '', maxDescription)}

{provider}
diff --git a/app/soapbox/features/status/components/detailed_status.js b/app/soapbox/features/status/components/detailed_status.js index 91f0376e7..b0e1b6a6c 100644 --- a/app/soapbox/features/status/components/detailed_status.js +++ b/app/soapbox/features/status/components/detailed_status.js @@ -1,24 +1,31 @@ -import React from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage, injectIntl } from 'react-intl'; +import { FormattedDate } from 'react-intl'; +import { Link, NavLink } from 'react-router-dom'; + +import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; +import Icon from 'soapbox/components/icon'; +import QuotedStatus from 'soapbox/features/status/containers/quoted_status_container'; +import { getDomain } from 'soapbox/utils/accounts'; + import Avatar from '../../../components/avatar'; import DisplayName from '../../../components/display_name'; -import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; -import { Link, NavLink } from 'react-router-dom'; -import { FormattedDate } from 'react-intl'; -import Card from './card'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import Video from '../../video'; +import StatusContent from '../../../components/status_content'; +import StatusReplyMentions from '../../../components/status_reply_mentions'; import Audio from '../../audio'; import scheduleIdleTask from '../../ui/util/schedule_idle_task'; -import classNames from 'classnames'; -import Icon from 'soapbox/components/icon'; -import StatusInteractionBar from './status_interaction_bar'; -import { getDomain } from 'soapbox/utils/accounts'; -import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; +import Video from '../../video'; -export default class DetailedStatus extends ImmutablePureComponent { +import Card from './card'; +import StatusInteractionBar from './status_interaction_bar'; + +export default @injectIntl +class DetailedStatus extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, @@ -82,6 +89,7 @@ export default class DetailedStatus extends ImmutablePureComponent { window.open(href, 'soapbox-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); } + render() { const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; const outerStyle = { boxSizing: 'border-box' }; @@ -149,10 +157,24 @@ export default class DetailedStatus extends ImmutablePureComponent { /> ); } - } else if (status.get('spoiler_text').length === 0) { + } else if (status.get('spoiler_text').length === 0 && !status.get('quote')) { media = ; } + let quote; + + if (status.get('quote')) { + if (status.getIn(['pleroma', 'quote_visible'], true) === false) { + quote = ( +
+

+
+ ); + } else { + quote = ; + } + } + if (status.get('visibility') === 'direct') { statusTypeIcon = ; } else if (status.get('visibility') === 'private') { @@ -185,6 +207,8 @@ export default class DetailedStatus extends ImmutablePureComponent {
)} + + {media} + {quote}
diff --git a/app/soapbox/features/status/components/quoted_status.js b/app/soapbox/features/status/components/quoted_status.js new file mode 100644 index 000000000..3bb8b2367 --- /dev/null +++ b/app/soapbox/features/status/components/quoted_status.js @@ -0,0 +1,164 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { NavLink } from 'react-router-dom'; + +import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; +import Avatar from 'soapbox/components/avatar'; +import DisplayName from 'soapbox/components/display_name'; +import IconButton from 'soapbox/components/icon_button'; +import RelativeTimestamp from 'soapbox/components/relative_timestamp'; +import { isRtl } from 'soapbox/rtl'; + +const messages = defineMessages({ + cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }, +}); + +export default @injectIntl +class QuotedStatus extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + status: ImmutablePropTypes.map, + onCancel: PropTypes.func, + intl: PropTypes.object.isRequired, + compose: PropTypes.bool, + }; + + handleExpandClick = e => { + const { compose, status } = this.props; + + if (!compose && e.button === 0) { + if (!this.context.router) { + return; + } + + this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`); + + e.preventDefault(); + } + } + + handleClose = e => { + this.props.onCancel(); + + e.preventDefault(); + } + + renderReplyMentions = () => { + const { status } = this.props; + + if (!status.get('in_reply_to_id')) { + return null; + } + + const to = status.get('mentions', []); + + if (to.size === 0) { + if (status.get('in_reply_to_account_id') === status.getIn(['account', 'id'])) { + return ( +
+ +
+ ); + } else { + return ( +
+ +
+ ); + } + } + + return ( +
+ `@${account.get('username')} `), + more: to.size > 2 && , + }} + /> +
+ ); + } + + render() { + const { status, onCancel, intl, compose } = this.props; + + if (!status) { + return null; + } + + const content = { __html: status.get('contentHtml') }; + const style = { + direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr', + }; + + const displayName = (<> +
+ + ); + + const quotedStatus = ( +
+
+ {onCancel + ? ( +
+ +
+ ) : ( +
+ +
+ )} + {compose ? ( +
+ {displayName} +
+ ) : ( + + {displayName} + + )} +
+ + {this.renderReplyMentions()} + +
+ + {status.get('media_attachments').size > 0 && ( + + )} +
+ ); + + if (compose) { + return ( +
+ {quotedStatus} +
+ ); + } + + return quotedStatus; + } + +} diff --git a/app/soapbox/features/status/components/status_interaction_bar.js b/app/soapbox/features/status/components/status_interaction_bar.js index b75769d66..1d6171a5f 100644 --- a/app/soapbox/features/status/components/status_interaction_bar.js +++ b/app/soapbox/features/status/components/status_interaction_bar.js @@ -1,27 +1,55 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; import { FormattedNumber } from 'react-intl'; +import { connect } from 'react-redux'; + +import { openModal } from 'soapbox/actions/modals'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import Icon from 'soapbox/components/icon'; import emojify from 'soapbox/features/emoji/emoji'; import { reduceEmoji } from 'soapbox/utils/emoji_reacts'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; import { getFeatures } from 'soapbox/utils/features'; -import { Link } from 'react-router-dom'; -import Icon from 'soapbox/components/icon'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; const mapStateToProps = state => { + const me = state.get('me'); const instance = state.get('instance'); return { + me, allowedEmoji: getSoapboxConfig(state).get('allowedEmoji'), features: getFeatures(instance), }; }; -export default @connect(mapStateToProps) +const mapDispatchToProps = (dispatch) => ({ + onOpenUnauthorizedModal() { + dispatch(openModal('UNAUTHORIZED')); + }, + onOpenReblogsModal(username, statusId) { + dispatch(openModal('REBLOGS', { + username, + statusId, + })); + }, + onOpenFavouritesModal(username, statusId) { + dispatch(openModal('FAVOURITES', { + username, + statusId, + })); + }, + onOpenReactionsModal(username, statusId, reaction) { + dispatch(openModal('REACTIONS', { + username, + statusId, + reaction, + })); + }, +}); + +export default @connect(mapStateToProps, mapDispatchToProps) class StatusInteractionBar extends ImmutablePureComponent { static propTypes = { @@ -29,6 +57,8 @@ class StatusInteractionBar extends ImmutablePureComponent { me: SoapboxPropTypes.me, allowedEmoji: ImmutablePropTypes.list, features: PropTypes.object.isRequired, + onOpenReblogsModal: PropTypes.func, + onOpenReactionsModal: PropTypes.func, } getNormalizedReacts = () => { @@ -41,22 +71,42 @@ class StatusInteractionBar extends ImmutablePureComponent { ).reverse(); } + handleOpenReblogsModal = () => { + const { me, status, onOpenUnauthorizedModal, onOpenReblogsModal } = this.props; + + if (!me) onOpenUnauthorizedModal(); + else onOpenReblogsModal(status.getIn(['account', 'acct']), status.get('id')); + } + getReposts = () => { const { status } = this.props; + if (status.get('reblogs_count')) { return ( - + - + ); } return ''; } + handleOpenFavouritesModal = () => { + const { me, status, onOpenUnauthorizedModal, onOpenFavouritesModal } = this.props; + + if (!me) onOpenUnauthorizedModal(); + else onOpenFavouritesModal(status.getIn(['account', 'acct']), status.get('id')); + } + getFavourites = () => { const { features, status } = this.props; @@ -72,9 +122,14 @@ class StatusInteractionBar extends ImmutablePureComponent { if (features.exposableReactions) { return ( - + {favourites} - + ); } else { return ( @@ -88,8 +143,15 @@ class StatusInteractionBar extends ImmutablePureComponent { return ''; } + handleOpenReactionsModal = (reaction) => () => { + const { me, status, onOpenUnauthorizedModal, onOpenReactionsModal } = this.props; + + if (!me) onOpenUnauthorizedModal(); + else onOpenReactionsModal(status.getIn(['account', 'acct']), status.get('id'), reaction.get('name')); + } + getEmojiReacts = () => { - const { status, features } = this.props; + const { features } = this.props; const emojiReacts = this.getNormalizedReacts(); const count = emojiReacts.reduce((acc, cur) => ( @@ -112,7 +174,17 @@ class StatusInteractionBar extends ImmutablePureComponent { ); if (features.exposableReactions) { - return {emojiReact}; + return ( + + {emojiReact} + + ); } return {emojiReact}; diff --git a/app/soapbox/features/status/components/thread_status.js b/app/soapbox/features/status/components/thread_status.js index 91ba4bfad..dc204a5bf 100644 --- a/app/soapbox/features/status/components/thread_status.js +++ b/app/soapbox/features/status/components/thread_status.js @@ -1,10 +1,11 @@ +import classNames from 'classnames'; +import { OrderedSet as ImmutableOrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; + import StatusContainer from 'soapbox/containers/status_container'; -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; import PlaceholderStatus from 'soapbox/features/placeholder/components/placeholder_status'; -import classNames from 'classnames'; const mapStateToProps = (state, { id }) => { return { diff --git a/app/soapbox/features/status/containers/detailed_status_container.js b/app/soapbox/features/status/containers/detailed_status_container.js index cf4555cd1..ded96257d 100644 --- a/app/soapbox/features/status/containers/detailed_status_container.js +++ b/app/soapbox/features/status/containers/detailed_status_container.js @@ -1,7 +1,13 @@ import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import DetailedStatus from '../components/detailed_status'; -import { makeGetStatus } from '../../../selectors'; + +import { launchChat } from 'soapbox/actions/chats'; +import { deactivateUserModal, deleteUserModal, deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; +import { getSettings } from 'soapbox/actions/settings'; + +import { blockAccount } from '../../../actions/accounts'; +import { showAlertForError } from '../../../actions/alerts'; import { replyCompose, mentionCompose, @@ -17,7 +23,9 @@ import { pin, unpin, } from '../../../actions/interactions'; -import { blockAccount } from '../../../actions/accounts'; +import { openModal } from '../../../actions/modals'; +import { initMuteModal } from '../../../actions/mutes'; +import { initReport } from '../../../actions/reports'; import { muteStatus, unmuteStatus, @@ -25,19 +33,15 @@ import { hideStatus, revealStatus, } from '../../../actions/statuses'; -import { initMuteModal } from '../../../actions/mutes'; -import { initReport } from '../../../actions/reports'; -import { openModal } from '../../../actions/modal'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { showAlertForError } from '../../../actions/alerts'; -import { getSettings } from 'soapbox/actions/settings'; -import { deactivateUserModal, deleteUserModal, deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; -import { launchChat } from 'soapbox/actions/chats'; +import { makeGetStatus } from '../../../selectors'; +import DetailedStatus from '../components/detailed_status'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, + deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' }, redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, + redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' }, redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, @@ -94,9 +98,9 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onBookmark(status) { if (status.get('bookmarked')) { - dispatch(unbookmark(intl, status)); + dispatch(unbookmark(status)); } else { - dispatch(bookmark(intl, status)); + dispatch(bookmark(status)); } }, @@ -130,6 +134,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { dispatch(openModal('CONFIRM', { + icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'), + heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading), message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), @@ -161,6 +167,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onBlock(status) { const account = status.get('account'); dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), diff --git a/app/soapbox/features/status/containers/quoted_status_container.js b/app/soapbox/features/status/containers/quoted_status_container.js new file mode 100644 index 000000000..a375b2562 --- /dev/null +++ b/app/soapbox/features/status/containers/quoted_status_container.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; + +import { makeGetStatus } from 'soapbox/selectors'; + +import QuotedStatus from '../components/quoted_status'; + +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); + + const mapStateToProps = (state, { statusId }) => ({ + status: getStatus(state, { id: statusId }), + }); + + return mapStateToProps; +}; + +export default connect(makeMapStateToProps)(QuotedStatus); diff --git a/app/soapbox/features/status/index.js b/app/soapbox/features/status/index.js index fbb17bae6..9c63ccc78 100644 --- a/app/soapbox/features/status/index.js +++ b/app/soapbox/features/status/index.js @@ -1,14 +1,36 @@ -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; +import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { HotKeys } from 'react-hotkeys'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { fetchStatusWithContext } from '../../actions/statuses'; -import MissingIndicator from '../../components/missing_indicator'; -import DetailedStatus from './components/detailed_status'; -import ActionBar from './components/action_bar'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; + +import { launchChat } from 'soapbox/actions/chats'; +import { + deactivateUserModal, + deleteUserModal, + deleteStatusModal, + toggleStatusSensitivityModal, +} from 'soapbox/actions/moderation'; +import { getSettings } from 'soapbox/actions/settings'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import Column from 'soapbox/components/column'; +import PullToRefresh from 'soapbox/components/pull_to_refresh'; +import SubNavigation from 'soapbox/components/sub_navigation'; +import PendingStatus from 'soapbox/features/ui/components/pending_status'; + +import { blockAccount } from '../../actions/accounts'; +import { + replyCompose, + mentionCompose, + directCompose, + quoteCompose, +} from '../../actions/compose'; +import { simpleEmojiReact } from '../../actions/emoji_reacts'; import { favourite, unfavourite, @@ -19,13 +41,9 @@ import { pin, unpin, } from '../../actions/interactions'; -import { simpleEmojiReact } from '../../actions/emoji_reacts'; -import { - replyCompose, - mentionCompose, - directCompose, -} from '../../actions/compose'; -import { blockAccount } from '../../actions/accounts'; +import { openModal } from '../../actions/modals'; +import { initMuteModal } from '../../actions/mutes'; +import { initReport } from '../../actions/reports'; import { muteStatus, unmuteStatus, @@ -33,33 +51,24 @@ import { hideStatus, revealStatus, } from '../../actions/statuses'; -import { initMuteModal } from '../../actions/mutes'; -import { initReport } from '../../actions/reports'; -import { makeGetStatus } from '../../selectors'; -// import ColumnHeader from '../../components/column_header'; -import { openModal } from '../../actions/modal'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { createSelector } from 'reselect'; -import { HotKeys } from 'react-hotkeys'; -import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; +import { fetchStatusWithContext } from '../../actions/statuses'; +import MissingIndicator from '../../components/missing_indicator'; import { textForScreenReader, defaultMediaVisibility } from '../../components/status'; -// import Icon from 'soapbox/components/icon'; -import { getSettings } from 'soapbox/actions/settings'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; -import { deactivateUserModal, deleteUserModal, deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; +import { makeGetStatus } from '../../selectors'; +import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../ui/util/fullscreen'; + +import ActionBar from './components/action_bar'; +import DetailedStatus from './components/detailed_status'; import ThreadStatus from './components/thread_status'; -import PendingStatus from 'soapbox/features/ui/components/pending_status'; -import SubNavigation from 'soapbox/components/sub_navigation'; -import { launchChat } from 'soapbox/actions/chats'; -import PullToRefresh from 'soapbox/components/pull_to_refresh'; const messages = defineMessages({ title: { id: 'status.title', defaultMessage: 'Post' }, titleDirect: { id: 'status.title_direct', defaultMessage: 'Direct message' }, deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, + deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' }, deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' }, redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, + redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' }, redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' }, @@ -80,7 +89,7 @@ const makeMapStateToProps = () => { let ancestorsIds = ImmutableOrderedSet(); let id = statusId; - while (id) { + while (id && !ancestorsIds.includes(id)) { ancestorsIds = ImmutableOrderedSet([id]).union(ancestorsIds); id = inReplyTos.get(id); } @@ -99,6 +108,10 @@ const makeMapStateToProps = () => { const id = ids.shift(); const replies = contextReplies.get(id); + if (descendantsIds.includes(id)) { + break; + } + if (statusId !== id) { descendantsIds = descendantsIds.union([id]); } @@ -119,8 +132,11 @@ const makeMapStateToProps = () => { let descendantsIds = ImmutableOrderedSet(); if (status) { - ancestorsIds = getAncestorsIds(state, { id: state.getIn(['contexts', 'inReplyTos', status.get('id')]) }); - descendantsIds = getDescendantsIds(state, { id: status.get('id') }); + const statusId = status.get('id'); + ancestorsIds = getAncestorsIds(state, { id: state.getIn(['contexts', 'inReplyTos', statusId]) }); + descendantsIds = getDescendantsIds(state, { id: statusId }); + ancestorsIds = ancestorsIds.delete(statusId).subtract(descendantsIds); + descendantsIds = descendantsIds.delete(statusId).subtract(ancestorsIds); } const soapbox = getSoapboxConfig(state); @@ -205,9 +221,9 @@ class Status extends ImmutablePureComponent { handleBookmark = (status) => { if (status.get('bookmarked')) { - this.props.dispatch(unbookmark(this.props.intl, status)); + this.props.dispatch(unbookmark(status)); } else { - this.props.dispatch(bookmark(this.props.intl, status)); + this.props.dispatch(bookmark(status)); } } @@ -243,6 +259,19 @@ class Status extends ImmutablePureComponent { }); } + handleQuoteClick = (status, e) => { + const { askReplyConfirmation, dispatch, intl } = this.props; + if (askReplyConfirmation) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(quoteCompose(status, this.context.router.history)), + })); + } else { + dispatch(quoteCompose(status, this.context.router.history)); + } + } + handleDeleteClick = (status, history, withRedraft = false) => { const { dispatch, intl } = this.props; @@ -252,6 +281,8 @@ class Status extends ImmutablePureComponent { dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { dispatch(openModal('CONFIRM', { + icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'), + heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading), message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), @@ -331,6 +362,8 @@ class Status extends ImmutablePureComponent { const account = status.get('account'); dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), @@ -418,10 +451,10 @@ class Status extends ImmutablePureComponent { if (id === status.get('id')) { this._selectChild(ancestorsIds.size - 1, true); } else { - let index = ancestorsIds.indexOf(id); + let index = ImmutableList(ancestorsIds).indexOf(id); if (index === -1) { - index = descendantsIds.indexOf(id); + index = ImmutableList(descendantsIds).indexOf(id); this._selectChild(ancestorsIds.size + index, true); } else { this._selectChild(index - 1, true); @@ -435,10 +468,10 @@ class Status extends ImmutablePureComponent { if (id === status.get('id')) { this._selectChild(ancestorsIds.size + 1, false); } else { - let index = ancestorsIds.indexOf(id); + let index = ImmutableList(ancestorsIds).indexOf(id); if (index === -1) { - index = descendantsIds.indexOf(id); + index = ImmutableList(descendantsIds).indexOf(id); this._selectChild(ancestorsIds.size + index + 2, false); } else { this._selectChild(index + 1, false); @@ -662,6 +695,7 @@ class Status extends ImmutablePureComponent { onFavourite={this.handleFavouriteClick} onEmojiReact={this.handleEmojiReactClick} onReblog={this.handleReblogClick} + onQuote={this.handleQuoteClick} onDelete={this.handleDeleteClick} onDirect={this.handleDirectClick} onChat={this.handleChatClick} diff --git a/app/soapbox/features/ui/components/accordion.js b/app/soapbox/features/ui/components/accordion.js index 2697ee558..6b2b7b2bb 100644 --- a/app/soapbox/features/ui/components/accordion.js +++ b/app/soapbox/features/ui/components/accordion.js @@ -1,7 +1,8 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; const messages = defineMessages({ @@ -34,10 +35,10 @@ export default @injectIntl class Accordion extends React.PureComponent { const { headline, children, menu, expanded, intl } = this.props; return ( -
+
{menu && (
- +
)} ); + } + return ( @@ -102,8 +133,9 @@ class ActionButton extends ImmutablePureComponent { return ); diff --git a/app/soapbox/features/ui/components/actions_modal.js b/app/soapbox/features/ui/components/actions_modal.js index 69a5dce05..c3bf0a8e0 100644 --- a/app/soapbox/features/ui/components/actions_modal.js +++ b/app/soapbox/features/ui/components/actions_modal.js @@ -1,17 +1,18 @@ -import React from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage, injectIntl } from 'react-intl'; import spring from 'react-motion/lib/spring'; -import StatusContent from '../../../components/status_content'; + import Avatar from '../../../components/avatar'; -import RelativeTimestamp from '../../../components/relative_timestamp'; +import Button from '../../../components/button'; import DisplayName from '../../../components/display_name'; import Icon from '../../../components/icon'; -import Button from '../../../components/button'; +import RelativeTimestamp from '../../../components/relative_timestamp'; +import StatusContent from '../../../components/status_content'; import Motion from '../util/optional_motion'; -import classNames from 'classnames'; export default @injectIntl class ActionsModal extends ImmutablePureComponent { @@ -28,7 +29,7 @@ class ActionsModal extends ImmutablePureComponent { return
  • ; } - const { icon = null, text, meta = null, active = false, href = '#', isLogout } = action; + const { icon = null, text, meta = null, active = false, href = '#', isLogout, destructive } = action; return (
  • @@ -37,7 +38,7 @@ class ActionsModal extends ImmutablePureComponent { rel='noopener' onClick={this.props.onClick} data-index={i} - className={classNames({ active })} + className={classNames({ active, destructive })} data-method={isLogout ? 'delete' : null} > {icon && } @@ -51,7 +52,7 @@ class ActionsModal extends ImmutablePureComponent { } render() { - const { onClose } = this.props; + const { actions, onClose } = this.props; const status = this.props.status && (
    @@ -82,7 +83,7 @@ class ActionsModal extends ImmutablePureComponent { {status}
      - {this.props.actions.map(this.renderAction)} + {actions && actions.map(this.renderAction)} diff --git a/app/soapbox/features/ui/components/better_column.js b/app/soapbox/features/ui/components/better_column.js index 6d7e6e609..2127c91fb 100644 --- a/app/soapbox/features/ui/components/better_column.js +++ b/app/soapbox/features/ui/components/better_column.js @@ -1,9 +1,11 @@ -import React from 'react'; -import ColumnHeader from './column_header'; import PropTypes from 'prop-types'; +import React from 'react'; + import Column from 'soapbox/components/column'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; +import ColumnHeader from './column_header'; + // Yes, there are 3 types of columns at this point, but this one is better, I swear export default class BetterColumn extends React.PureComponent { diff --git a/app/soapbox/features/ui/components/birthdays_modal.js b/app/soapbox/features/ui/components/birthdays_modal.js new file mode 100644 index 000000000..9a0744ba7 --- /dev/null +++ b/app/soapbox/features/ui/components/birthdays_modal.js @@ -0,0 +1,97 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import IconButton from 'soapbox/components/icon_button'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import Account from 'soapbox/features/birthdays/account'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +const mapStateToProps = (state) => { + const me = state.get('me'); + + return { + accountIds: state.getIn(['user_lists', 'birthday_reminders', me]), + }; +}; + +export default @connect(mapStateToProps) +@injectIntl +class BirthdaysModal extends React.PureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + accountIds: ImmutablePropTypes.orderedSet, + }; + + componentDidMount() { + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); + } + + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = (_, noPop) => { + this.props.onClose('BIRTHDAYS', noPop); + }; + + render() { + const { intl, accountIds } = this.props; + + let body; + + if (!accountIds) { + body = ; + } else { + const emptyMessage = ; + + body = ( + + {accountIds.map(id => + , + )} + + ); + } + + + return ( +
      +
      +

      + +

      + +
      + {body} +
      + ); + } + +} diff --git a/app/soapbox/features/ui/components/boost_modal.js b/app/soapbox/features/ui/components/boost_modal.js index 97c9e0631..2bf508b97 100644 --- a/app/soapbox/features/ui/components/boost_modal.js +++ b/app/soapbox/features/ui/components/boost_modal.js @@ -1,15 +1,17 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import Button from '../../../components/button'; -import StatusContent from '../../../components/status_content'; -import Avatar from '../../../components/avatar'; -import RelativeTimestamp from '../../../components/relative_timestamp'; -import DisplayName from '../../../components/display_name'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Icon from 'soapbox/components/icon'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; + import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; +import Icon from 'soapbox/components/icon'; + +import Avatar from '../../../components/avatar'; +import Button from '../../../components/button'; +import DisplayName from '../../../components/display_name'; +import RelativeTimestamp from '../../../components/relative_timestamp'; +import StatusContent from '../../../components/status_content'; const messages = defineMessages({ cancel_reblog: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' }, diff --git a/app/soapbox/features/ui/components/bundle.js b/app/soapbox/features/ui/components/bundle.js index 7089597b6..11622ec19 100644 --- a/app/soapbox/features/ui/components/bundle.js +++ b/app/soapbox/features/ui/components/bundle.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; const emptyComponent = () => null; const noop = () => { }; diff --git a/app/soapbox/features/ui/components/bundle_column_error.js b/app/soapbox/features/ui/components/bundle_column_error.js index 5a36ad6f1..26186d26f 100644 --- a/app/soapbox/features/ui/components/bundle_column_error.js +++ b/app/soapbox/features/ui/components/bundle_column_error.js @@ -1,10 +1,11 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; +import IconButton from '../../../components/icon_button'; + import Column from './column'; import ColumnHeader from './column_header'; -import IconButton from '../../../components/icon_button'; const messages = defineMessages({ title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' }, diff --git a/app/soapbox/features/ui/components/bundle_modal_error.js b/app/soapbox/features/ui/components/bundle_modal_error.js index 4c5c82dcb..9f4749893 100644 --- a/app/soapbox/features/ui/components/bundle_modal_error.js +++ b/app/soapbox/features/ui/components/bundle_modal_error.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import IconButton from '../../../components/icon_button'; diff --git a/app/soapbox/features/ui/components/column.js b/app/soapbox/features/ui/components/column.js index c4a1be2dc..837d36f12 100644 --- a/app/soapbox/features/ui/components/column.js +++ b/app/soapbox/features/ui/components/column.js @@ -1,9 +1,11 @@ -import React from 'react'; -import ColumnHeader from './column_header'; import PropTypes from 'prop-types'; +import React from 'react'; + import Column from 'soapbox/components/column'; import Pullable from 'soapbox/components/pullable'; +import ColumnHeader from './column_header'; + export default class UIColumn extends React.PureComponent { static propTypes = { diff --git a/app/soapbox/features/ui/components/column_forbidden.js b/app/soapbox/features/ui/components/column_forbidden.js new file mode 100644 index 000000000..d4df027b3 --- /dev/null +++ b/app/soapbox/features/ui/components/column_forbidden.js @@ -0,0 +1,34 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl } from 'react-intl'; + +import Column from './column'; +import ColumnHeader from './column_header'; + +const messages = defineMessages({ + title: { id: 'column_forbidden.title', defaultMessage: 'Forbidden' }, + body: { id: 'column_forbidden.body', defaultMessage: 'You do not have permission to access this page.' }, +}); + +class ColumnForbidden extends React.PureComponent { + + static propTypes = { + intl: PropTypes.object.isRequired, + } + + render() { + const { intl: { formatMessage } } = this.props; + + return ( + + +
      + {formatMessage(messages.body)} +
      +
      + ); + } + +} + +export default injectIntl(ColumnForbidden); diff --git a/app/soapbox/features/ui/components/column_header.js b/app/soapbox/features/ui/components/column_header.js index 021421194..5f5153cc5 100644 --- a/app/soapbox/features/ui/components/column_header.js +++ b/app/soapbox/features/ui/components/column_header.js @@ -1,5 +1,6 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; + // import classNames from 'classnames'; // import Icon from 'soapbox/components/icon'; import SubNavigation from 'soapbox/components/sub_navigation'; diff --git a/app/soapbox/features/ui/components/column_link.js b/app/soapbox/features/ui/components/column_link.js index 3522dbfaf..9dbdf4c64 100644 --- a/app/soapbox/features/ui/components/column_link.js +++ b/app/soapbox/features/ui/components/column_link.js @@ -1,15 +1,16 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import { Link } from 'react-router-dom'; + import Icon from 'soapbox/components/icon'; -const ColumnLink = ({ icon, text, to, href, method, badge }) => { +const ColumnLink = ({ icon, src, text, to, href, method, badge }) => { const badgeElement = typeof badge !== 'undefined' ? {badge} : null; if (href) { return ( - + {text} {badgeElement} @@ -17,7 +18,7 @@ const ColumnLink = ({ icon, text, to, href, method, badge }) => { } else { return ( - + {text} {badgeElement} @@ -26,7 +27,8 @@ const ColumnLink = ({ icon, text, to, href, method, badge }) => { }; ColumnLink.propTypes = { - icon: PropTypes.string.isRequired, + icon: PropTypes.string, + src: PropTypes.string, text: PropTypes.string.isRequired, to: PropTypes.string, href: PropTypes.string, diff --git a/app/soapbox/features/ui/components/column_loading.js b/app/soapbox/features/ui/components/column_loading.js index 7ade977e2..21f218db1 100644 --- a/app/soapbox/features/ui/components/column_loading.js +++ b/app/soapbox/features/ui/components/column_loading.js @@ -1,10 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import Column from 'soapbox/components/column'; -import ColumnHeader from '../../../components/column_header'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; + +import Column from 'soapbox/components/column'; import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ColumnHeader from '../../../components/column_header'; + export default class ColumnLoading extends ImmutablePureComponent { static propTypes = { diff --git a/app/soapbox/features/ui/components/column_subheading.js b/app/soapbox/features/ui/components/column_subheading.js index 8160c4aa3..c586e27b7 100644 --- a/app/soapbox/features/ui/components/column_subheading.js +++ b/app/soapbox/features/ui/components/column_subheading.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; const ColumnSubheading = ({ text }) => { return ( diff --git a/app/soapbox/features/ui/components/columns_area.js b/app/soapbox/features/ui/components/columns_area.js index 57f1cd75f..f2409b589 100644 --- a/app/soapbox/features/ui/components/columns_area.js +++ b/app/soapbox/features/ui/components/columns_area.js @@ -1,8 +1,8 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { injectIntl } from 'react-intl'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl } from 'react-intl'; export default @(component => injectIntl(component, { withRef: true })) class ColumnsArea extends ImmutablePureComponent { @@ -16,7 +16,7 @@ class ColumnsArea extends ImmutablePureComponent { render() { const { children } = this.props; - const layout = this.props.layout || { LEFT:null, RIGHT:null }; + const layout = this.props.layout || { LEFT: null, RIGHT: null }; return (
      diff --git a/app/soapbox/features/ui/components/component_modal.js b/app/soapbox/features/ui/components/component_modal.js index f84609f14..51c23a8e1 100644 --- a/app/soapbox/features/ui/components/component_modal.js +++ b/app/soapbox/features/ui/components/component_modal.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; export default class ComponentModal extends React.PureComponent { diff --git a/app/soapbox/features/ui/components/compose_modal.js b/app/soapbox/features/ui/components/compose_modal.js index 9b24f9429..a62a59001 100644 --- a/app/soapbox/features/ui/components/compose_modal.js +++ b/app/soapbox/features/ui/components/compose_modal.js @@ -1,13 +1,15 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import ComposeFormContainer from '../../compose/containers/compose_form_container'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { cancelReplyCompose } from 'soapbox/actions/compose'; +import { openModal, closeModal } from 'soapbox/actions/modals'; import IconButton from 'soapbox/components/icon_button'; -import { openModal } from '../../../actions/modal'; -import { cancelReplyCompose } from '../../../actions/compose'; + +import ComposeFormContainer from '../../compose/containers/compose_form_container'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -20,6 +22,8 @@ const mapStateToProps = state => { account: state.getIn(['accounts', me]), composeText: state.getIn(['compose', 'text']), privacy: state.getIn(['compose', 'privacy']), + inReplyTo: state.getIn(['compose', 'in_reply_to']), + quote: state.getIn(['compose', 'quote']), }; }; @@ -31,6 +35,8 @@ class ComposeModal extends ImmutablePureComponent { onClose: PropTypes.func.isRequired, composeText: PropTypes.string, privacy: PropTypes.string, + inReplyTo: PropTypes.string, + quote: PropTypes.string, dispatch: PropTypes.func.isRequired, }; @@ -39,28 +45,42 @@ class ComposeModal extends ImmutablePureComponent { if (composeText) { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/trash.svg'), + heading: , message: , confirm: intl.formatMessage(messages.confirm), - onConfirm: () => dispatch(cancelReplyCompose()), - onCancel: () => dispatch(openModal('COMPOSE')), + onConfirm: () => { + dispatch(closeModal('COMPOSE')); + dispatch(cancelReplyCompose()); + }, })); } else { onClose('COMPOSE'); } }; + renderTitle = () => { + const { privacy, inReplyTo, quote } = this.props; + + if (privacy === 'direct') { + return ; + } else if (inReplyTo) { + return ; + } else if (quote) { + return ; + } else { + return ; + } + } + render() { - const { intl, privacy } = this.props; + const { intl } = this.props; return (

      - {privacy === 'direct' ? ( - - ) : ( - - )} + {this.renderTitle()}

      { - this.props.onClose(); + this.props.onClose('CONFIRM'); this.props.onConfirm(); } handleSecondary = () => { - this.props.onClose(); + this.props.onClose('CONFIRM'); this.props.onSecondary(); } handleCancel = () => { const { onClose, onCancel } = this.props; - onClose(); + onClose('CONFIRM'); if (onCancel) onCancel(); } @@ -52,11 +57,18 @@ class ConfirmationModal extends React.PureComponent { } render() { - const { message, confirm, secondary, checkbox } = this.props; + const { heading, icon, message, confirm, secondary, checkbox } = this.props; const { checked } = this.state; return (
      + {heading && ( +
      + {icon && } + {heading} +
      + )} +
      {message}
      diff --git a/app/soapbox/features/ui/components/crypto_donate_modal.js b/app/soapbox/features/ui/components/crypto_donate_modal.js index 90ae87842..73d8b25db 100644 --- a/app/soapbox/features/ui/components/crypto_donate_modal.js +++ b/app/soapbox/features/ui/components/crypto_donate_modal.js @@ -1,5 +1,6 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; + import DetailedCryptoAddress from 'soapbox/features/crypto_donate/components/detailed_crypto_address'; export default class CryptoDonateModal extends React.PureComponent { diff --git a/app/soapbox/features/ui/components/edit_federation_modal.js b/app/soapbox/features/ui/components/edit_federation_modal.js index ff284316d..53e21078f 100644 --- a/app/soapbox/features/ui/components/edit_federation_modal.js +++ b/app/soapbox/features/ui/components/edit_federation_modal.js @@ -1,14 +1,15 @@ -import React from 'react'; +import { Map as ImmutableMap, is } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; import { defineMessages, injectIntl } from 'react-intl'; -import { SimpleForm, Checkbox } from 'soapbox/features/forms'; -import { makeGetRemoteInstance } from 'soapbox/selectors'; -import { Map as ImmutableMap, is } from 'immutable'; +import { connect } from 'react-redux'; + import { updateMrf } from 'soapbox/actions/mrf'; import snackbar from 'soapbox/actions/snackbar'; +import { SimpleForm, Checkbox } from 'soapbox/features/forms'; +import { makeGetRemoteInstance } from 'soapbox/selectors'; const getRemoteInstance = makeGetRemoteInstance(); diff --git a/app/soapbox/features/ui/components/embed_modal.js b/app/soapbox/features/ui/components/embed_modal.js index 86b79e2f3..6d10ee5bc 100644 --- a/app/soapbox/features/ui/components/embed_modal.js +++ b/app/soapbox/features/ui/components/embed_modal.js @@ -1,8 +1,8 @@ -import React from 'react'; +import axios from 'axios'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage, injectIntl } from 'react-intl'; -import axios from 'axios'; export default @injectIntl class EmbedModal extends ImmutablePureComponent { diff --git a/app/soapbox/features/ui/components/favourites_modal.js b/app/soapbox/features/ui/components/favourites_modal.js new file mode 100644 index 000000000..4df4d4da8 --- /dev/null +++ b/app/soapbox/features/ui/components/favourites_modal.js @@ -0,0 +1,91 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchFavourites } from 'soapbox/actions/interactions'; +import IconButton from 'soapbox/components/icon_button'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import AccountContainer from 'soapbox/containers/account_container'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +const mapStateToProps = (state, props) => { + return { + accountIds: state.getIn(['user_lists', 'favourited_by', props.statusId]), + }; +}; + +export default @connect(mapStateToProps) +@injectIntl +class FavouritesModal extends React.PureComponent { + + static propTypes = { + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + statusId: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + dispatch: PropTypes.func.isRequired, + accountIds: ImmutablePropTypes.orderedSet, + }; + + fetchData = () => { + const { dispatch, statusId } = this.props; + + dispatch(fetchFavourites(statusId)); + } + + componentDidMount() { + this.fetchData(); + } + + onClickClose = () => { + this.props.onClose('FAVOURITES'); + }; + + render() { + const { intl, accountIds } = this.props; + + let body; + + if (!accountIds) { + body = ; + } else { + const emptyMessage = ; + + body = ( + + {accountIds.map(id => + , + )} + + ); + } + + + return ( +
      +
      +

      + +

      + +
      + {body} +
      + ); + } + +} diff --git a/app/soapbox/features/ui/components/features_panel.js b/app/soapbox/features/ui/components/features_panel.js index 2704344ff..ba1d46676 100644 --- a/app/soapbox/features/ui/components/features_panel.js +++ b/app/soapbox/features/ui/components/features_panel.js @@ -1,13 +1,14 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import { OrderedSet as ImmutableOrderedSet } from 'immutable'; import PropTypes from 'prop-types'; +import React from 'react'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; +import { NavLink } from 'react-router-dom'; + import Icon from 'soapbox/components/icon'; import IconWithCounter from 'soapbox/components/icon_with_counter'; -import { NavLink } from 'react-router-dom'; -import { injectIntl, defineMessages } from 'react-intl'; -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import { getFeatures } from 'soapbox/utils/features'; import { getBaseURL } from 'soapbox/utils/accounts'; +import { getFeatures } from 'soapbox/utils/features'; const messages = defineMessages({ edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit Profile' }, diff --git a/app/soapbox/features/ui/components/focal_point_modal.js b/app/soapbox/features/ui/components/focal_point_modal.js index 189c051fd..777b40ecb 100644 --- a/app/soapbox/features/ui/components/focal_point_modal.js +++ b/app/soapbox/features/ui/components/focal_point_modal.js @@ -1,12 +1,14 @@ +import classNames from 'classnames'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; -import ImageLoader from './image_loader'; -import classNames from 'classnames'; + import { changeUploadCompose } from '../../../actions/compose'; import { getPointerPosition } from '../../video'; +import ImageLoader from './image_loader'; + const mapStateToProps = (state, { id }) => ({ media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id), }); diff --git a/app/soapbox/features/ui/components/funding_panel.js b/app/soapbox/features/ui/components/funding_panel.js index dfcb31a75..45010360c 100644 --- a/app/soapbox/features/ui/components/funding_panel.js +++ b/app/soapbox/features/ui/components/funding_panel.js @@ -1,12 +1,14 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ProgressBar from '../../../components/progress_bar'; -import { fetchPatronInstance } from 'soapbox/actions/patron'; import { Map as ImmutableMap } from 'immutable'; +import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchPatronInstance } from 'soapbox/actions/patron'; import Icon from 'soapbox/components/icon'; +import ProgressBar from '../../../components/progress_bar'; + const moneyFormat = amount => ( new Intl .NumberFormat('en-US', { diff --git a/app/soapbox/features/ui/components/hotkeys_modal.js b/app/soapbox/features/ui/components/hotkeys_modal.js index 6d1434135..70ecf3198 100644 --- a/app/soapbox/features/ui/components/hotkeys_modal.js +++ b/app/soapbox/features/ui/components/hotkeys_modal.js @@ -1,7 +1,8 @@ -import React from 'react'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; + import IconButton from 'soapbox/components/icon_button'; const messages = defineMessages({ @@ -23,7 +24,7 @@ class HotkeysModal extends ImmutablePureComponent {

      - +
      diff --git a/app/soapbox/features/ui/components/image_loader.js b/app/soapbox/features/ui/components/image_loader.js index 99f7c2981..a8f50772e 100644 --- a/app/soapbox/features/ui/components/image_loader.js +++ b/app/soapbox/features/ui/components/image_loader.js @@ -1,6 +1,7 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; + import ZoomableImage from './zoomable_image'; export default class ImageLoader extends React.PureComponent { diff --git a/app/soapbox/features/ui/components/instance_info_panel.js b/app/soapbox/features/ui/components/instance_info_panel.js index 6d6356871..20582ddcf 100644 --- a/app/soapbox/features/ui/components/instance_info_panel.js +++ b/app/soapbox/features/ui/components/instance_info_panel.js @@ -1,15 +1,16 @@ 'use strict'; +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { injectIntl, defineMessages } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { makeGetRemoteInstance } from 'soapbox/selectors'; -import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; +import { injectIntl, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + import { pinHost, unpinHost } from 'soapbox/actions/remote_timeline'; import { getSettings } from 'soapbox/actions/settings'; +import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; +import { makeGetRemoteInstance } from 'soapbox/selectors'; const getRemoteInstance = makeGetRemoteInstance(); @@ -73,7 +74,7 @@ class InstanceInfoPanel extends ImmutablePureComponent { {remoteInstance.get('host')}
      - +
      diff --git a/app/soapbox/features/ui/components/instance_moderation_panel.js b/app/soapbox/features/ui/components/instance_moderation_panel.js index c52950457..ad54c4db1 100644 --- a/app/soapbox/features/ui/components/instance_moderation_panel.js +++ b/app/soapbox/features/ui/components/instance_moderation_panel.js @@ -1,15 +1,16 @@ 'use strict'; +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { makeGetRemoteInstance } from 'soapbox/selectors'; -import InstanceRestrictions from 'soapbox/features/federation_restrictions/components/instance_restrictions'; +import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { openModal } from 'soapbox/actions/modals'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; -import { openModal } from 'soapbox/actions/modal'; +import InstanceRestrictions from 'soapbox/features/federation_restrictions/components/instance_restrictions'; +import { makeGetRemoteInstance } from 'soapbox/selectors'; import { isAdmin } from 'soapbox/utils/accounts'; const getRemoteInstance = makeGetRemoteInstance(); @@ -68,7 +69,7 @@ class InstanceModerationPanel extends ImmutablePureComponent { {isAdmin &&
      - +
      }
      diff --git a/app/soapbox/features/ui/components/link_footer.js b/app/soapbox/features/ui/components/link_footer.js index ed89dc8dd..0e1d66aae 100644 --- a/app/soapbox/features/ui/components/link_footer.js +++ b/app/soapbox/features/ui/components/link_footer.js @@ -1,33 +1,33 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage, injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; import { connect } from 'react-redux'; -import { openModal } from '../../../actions/modal'; +import { Link } from 'react-router-dom'; + import { logOut } from 'soapbox/actions/auth'; import { getBaseURL, isAdmin } from 'soapbox/utils/accounts'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; +import { openModal } from '../../../actions/modals'; + const mapStateToProps = state => { const me = state.get('me'); const account = state.getIn(['accounts', me]); const instance = state.get('instance'); - const features = getFeatures(instance); return { account, - federating: features.federating, - showAliases: features.accountAliasesAPI, - importAPI: features.importAPI, + features: getFeatures(instance), baseURL: getBaseURL(account), }; }; const mapDispatchToProps = (dispatch, { intl }) => ({ - onOpenHotkeys() { + onOpenHotkeys(e) { dispatch(openModal('HOTKEYS')); + e.preventDefault(); }, onClickLogOut(e) { dispatch(logOut(intl)); @@ -35,24 +35,25 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, }); -const LinkFooter = ({ onOpenHotkeys, account, federating, showAliases, importAPI, onClickLogOut, baseURL }) => ( +const LinkFooter = ({ onOpenHotkeys, account, features, onClickLogOut, baseURL }) => (
        {account && <> + {features.profileDirectory &&
      • }
      • - {federating &&
      • } + {features.federating &&
      • }
      • {isAdmin(account) &&
      • } {isAdmin(account) &&
      • }
      • -
      • {importAPI ? ( +
      • {features.importAPI ? ( ) : ( )}
      • - {(federating && showAliases) &&
      • } + {(features.federating && features.accountMoving) &&
      • }
      • }
      • @@ -75,9 +76,7 @@ const LinkFooter = ({ onOpenHotkeys, account, federating, showAliases, importAPI LinkFooter.propTypes = { account: ImmutablePropTypes.map, - federating: PropTypes.bool, - showAliases: PropTypes.bool, - importAPI: PropTypes.bool, + features: PropTypes.object.isRequired, onOpenHotkeys: PropTypes.func.isRequired, onClickLogOut: PropTypes.func.isRequired, baseURL: PropTypes.string, diff --git a/app/soapbox/features/ui/components/list_panel.js b/app/soapbox/features/ui/components/list_panel.js index 74ce8a889..4ca1a78ff 100644 --- a/app/soapbox/features/ui/components/list_panel.js +++ b/app/soapbox/features/ui/components/list_panel.js @@ -1,11 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { fetchLists } from 'soapbox/actions/lists'; import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; import { NavLink, withRouter } from 'react-router-dom'; +import { createSelector } from 'reselect'; + +import { fetchLists } from 'soapbox/actions/lists'; import Icon from 'soapbox/components/icon'; const getOrderedLists = createSelector([state => state.get('lists')], lists => { diff --git a/app/soapbox/features/ui/components/media_modal.js b/app/soapbox/features/ui/components/media_modal.js index b93e23edf..786433ec3 100644 --- a/app/soapbox/features/ui/components/media_modal.js +++ b/app/soapbox/features/ui/components/media_modal.js @@ -1,16 +1,18 @@ -import React from 'react'; -import ReactSwipeableViews from 'react-swipeable-views'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import Video from 'soapbox/features/video'; -import Audio from 'soapbox/features/audio'; -import ExtendedVideoPlayer from 'soapbox/components/extended_video_player'; import classNames from 'classnames'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import IconButton from 'soapbox/components/icon_button'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImageLoader from './image_loader'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import ReactSwipeableViews from 'react-swipeable-views'; + +import ExtendedVideoPlayer from 'soapbox/components/extended_video_player'; import Icon from 'soapbox/components/icon'; +import IconButton from 'soapbox/components/icon_button'; +import Audio from 'soapbox/features/audio'; +import Video from 'soapbox/features/video'; + +import ImageLoader from './image_loader'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -18,8 +20,6 @@ const messages = defineMessages({ next: { id: 'lightbox.next', defaultMessage: 'Next' }, }); -export const previewState = 'previewMediaModal'; - export default @injectIntl class MediaModal extends ImmutablePureComponent { @@ -34,7 +34,7 @@ class MediaModal extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, - }; + } state = { index: null, @@ -75,28 +75,10 @@ class MediaModal extends ImmutablePureComponent { componentDidMount() { window.addEventListener('keydown', this.handleKeyDown, false); - - if (this.context.router) { - const history = this.context.router.history; - - history.push(history.location.pathname, previewState); - - this.unlistenHistory = history.listen(() => { - this.props.onClose(); - }); - } } componentWillUnmount() { window.removeEventListener('keydown', this.handleKeyDown); - - if (this.context.router) { - this.unlistenHistory(); - - if (this.context.router.history.location.state === previewState) { - this.context.router.history.goBack(); - } - } } getIndex() { @@ -116,6 +98,7 @@ class MediaModal extends ImmutablePureComponent { const acct = account.get('acct'); const statusId = status.get('id'); this.context.router.history.push(`/@${acct}/posts/${statusId}`); + this.props.onClose(null, true); } } @@ -271,7 +254,7 @@ class MediaModal extends ImmutablePureComponent {
      - + {leftNav} {rightNav} diff --git a/app/soapbox/features/ui/components/mentions_modal.js b/app/soapbox/features/ui/components/mentions_modal.js new file mode 100644 index 000000000..ebd814a86 --- /dev/null +++ b/app/soapbox/features/ui/components/mentions_modal.js @@ -0,0 +1,95 @@ +import { OrderedSet as ImmutableOrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchStatusWithContext } from 'soapbox/actions/statuses'; +import IconButton from 'soapbox/components/icon_button'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import AccountContainer from 'soapbox/containers/account_container'; +import { makeGetStatus } from 'soapbox/selectors'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +const mapStateToProps = (state, props) => { + const getStatus = makeGetStatus(); + const status = getStatus(state, { + id: props.statusId, + username: props.username, + }); + + return { + accountIds: status ? ImmutableOrderedSet(status.get('mentions').map(m => m.get('id'))) : null, + }; +}; + +export default @connect(mapStateToProps) +@injectIntl +class MentionsModal extends React.PureComponent { + + static propTypes = { + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + statusId: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + dispatch: PropTypes.func.isRequired, + accountIds: ImmutablePropTypes.orderedSet, + }; + + fetchData = () => { + const { dispatch, statusId } = this.props; + + dispatch(fetchStatusWithContext(statusId)); + } + + componentDidMount() { + this.fetchData(); + } + + onClickClose = () => { + this.props.onClose('MENTIONS'); + }; + + render() { + const { intl, accountIds } = this.props; + + let body; + + if (!accountIds) { + body = ; + } else { + body = ( + + {accountIds.map(id => + , + )} + + ); + } + + return ( +
      +
      +

      + +

      + +
      + {body} +
      + ); + } + +} diff --git a/app/soapbox/features/ui/components/missing_description_modal.js b/app/soapbox/features/ui/components/missing_description_modal.js index 0cbdad660..ba31c6c8f 100644 --- a/app/soapbox/features/ui/components/missing_description_modal.js +++ b/app/soapbox/features/ui/components/missing_description_modal.js @@ -1,6 +1,7 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; import { injectIntl, FormattedMessage } from 'react-intl'; + import Button from '../../../components/button'; export default @injectIntl diff --git a/app/soapbox/features/ui/components/modal_root.js b/app/soapbox/features/ui/components/modal_root.js index eed1278aa..5b7e43a8a 100644 --- a/app/soapbox/features/ui/components/modal_root.js +++ b/app/soapbox/features/ui/components/modal_root.js @@ -1,10 +1,7 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import Base from '../../../components/modal_root'; -import BundleContainer from '../containers/bundle_container'; -import BundleModalError from './bundle_modal_error'; -import ModalLoading from './modal_loading'; +import React from 'react'; +import Base from '../../../components/modal_root'; import { MediaModal, VideoModal, @@ -21,10 +18,21 @@ import { FocalPointModal, HotkeysModal, ComposeModal, + ReplyMentionsModal, UnauthorizedModal, EditFederationModal, ComponentModal, + ReactionsModal, + FavouritesModal, + ReblogsModal, + MentionsModal, + BirthdaysModal, } from '../../../features/ui/util/async-components'; +import BundleContainer from '../containers/bundle_container'; + +import BundleModalError from './bundle_modal_error'; +import ModalLoading from './modal_loading'; + const MODAL_COMPONENTS = { 'MEDIA': MediaModal, @@ -38,13 +46,19 @@ const MODAL_COMPONENTS = { 'EMBED': EmbedModal, 'LIST_EDITOR': ListEditor, 'FOCAL_POINT': FocalPointModal, - 'LIST_ADDER':ListAdder, + 'LIST_ADDER': ListAdder, 'HOTKEYS': HotkeysModal, 'COMPOSE': ComposeModal, + 'REPLY_MENTIONS': ReplyMentionsModal, 'UNAUTHORIZED': UnauthorizedModal, 'CRYPTO_DONATE': CryptoDonateModal, 'EDIT_FEDERATION': EditFederationModal, 'COMPONENT': ComponentModal, + 'REBLOGS': ReblogsModal, + 'FAVOURITES': FavouritesModal, + 'REACTIONS': ReactionsModal, + 'MENTIONS': MentionsModal, + 'BIRTHDAYS': BirthdaysModal, }; export default class ModalRoot extends React.PureComponent { @@ -75,7 +89,7 @@ export default class ModalRoot extends React.PureComponent { return ; } - onClickClose = () => { + onClickClose = (_) => { const { onClose, type } = this.props; onClose(type); } diff --git a/app/soapbox/features/ui/components/mute_modal.js b/app/soapbox/features/ui/components/mute_modal.js index d998ac627..5f8cdb466 100644 --- a/app/soapbox/features/ui/components/mute_modal.js +++ b/app/soapbox/features/ui/components/mute_modal.js @@ -1,12 +1,14 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import React from 'react'; import { injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; import Toggle from 'react-toggle'; -import Button from '../../../components/button'; -import { closeModal } from '../../../actions/modal'; -import { muteAccount } from '../../../actions/accounts'; -import { toggleHideNotifications } from '../../../actions/mutes'; + +import { muteAccount } from 'soapbox/actions/accounts'; +import { closeModal } from 'soapbox/actions/modals'; +import { toggleHideNotifications } from 'soapbox/actions/mutes'; +import Button from 'soapbox/components/button'; +import Icon from 'soapbox/components/icon'; const mapStateToProps = state => { @@ -73,6 +75,14 @@ class MuteModal extends React.PureComponent { return (
      +
      + + +

      { + return Boolean(pendingStatus.get('content').match(/https?:\/\/\S*/)); +}; + const mapStateToProps = (state, props) => { const { idempotencyKey } = props; const pendingStatus = state.getIn(['pending_statuses', idempotencyKey]); @@ -22,10 +31,77 @@ const mapStateToProps = (state, props) => { }; export default @connect(mapStateToProps) +@injectIntl class PendingStatus extends ImmutablePureComponent { + renderMedia = () => { + const { status } = this.props; + + if (status.get('media_attachments') && !status.get('media_attachments').isEmpty()) { + return ( + + ); + } else if (!status.get('quote') && shouldHaveCard(status)) { + return ; + } else { + return null; + } + } + + renderReplyMentions = () => { + const { status } = this.props; + + if (!status.get('in_reply_to_id')) { + return null; + } + + const to = status.get('mentions', []); + + if (to.size === 0) { + if (status.get('in_reply_to_account_id') === status.getIn(['account', 'id'])) { + return ( +

      + @{status.getIn(['account', 'username'])}, + more: false, + }} + /> +
      + ); + } else { + return ( +
      + +
      + ); + } + } + + + return ( +
      + (<> + @{account.username} + {' '} + )), + more: to.size > 2 && , + }} + /> +
      + ); + } + render() { - const { status, className, showThread } = this.props; + const { status, className } = this.props; if (!status) return null; if (!status.get('account')) return null; @@ -61,24 +137,18 @@ class PendingStatus extends ImmutablePureComponent {
      + {this.renderReplyMentions()} + - - + {this.renderMedia()} {status.get('poll') && } - {showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && ( - - )} + {status.get('quote') && } {/* TODO */} {/* */} diff --git a/app/soapbox/features/ui/components/pinned_accounts_panel.js b/app/soapbox/features/ui/components/pinned_accounts_panel.js new file mode 100644 index 000000000..da779b160 --- /dev/null +++ b/app/soapbox/features/ui/components/pinned_accounts_panel.js @@ -0,0 +1,79 @@ +import { List as ImmutableList } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import Icon from 'soapbox/components/icon'; + +import { fetchPinnedAccounts } from '../../../actions/accounts'; +import AccountContainer from '../../../containers/account_container'; + +class PinnedAccountsPanel extends ImmutablePureComponent { + + static propTypes = { + pinned: ImmutablePropTypes.list.isRequired, + fetchPinned: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + componentDidMount() { + this.props.fetchPinned(); + } + + render() { + const { account } = this.props; + const pinned = this.props.pinned.slice(0, this.props.limit); + + if (pinned.isEmpty()) { + return null; + } + + return ( +
      +
      + + + + +
      +
      +
      + {pinned && pinned.map(suggestion => ( + + ))} +
      +
      +
      + ); + } + +} + +const mapStateToProps = (state, { account }) => ({ + pinned: state.getIn(['user_lists', 'pinned', account.get('id'), 'items'], ImmutableList()), +}); + +const mapDispatchToProps = (dispatch, { account }) => { + return { + fetchPinned: () => dispatch(fetchPinnedAccounts(account.get('id'))), + }; +}; + +export default injectIntl( + connect(mapStateToProps, mapDispatchToProps, null, { + forwardRef: true, + }, + )(PinnedAccountsPanel)); diff --git a/app/soapbox/features/ui/components/poll_preview.js b/app/soapbox/features/ui/components/poll_preview.js index edc3c9ed2..40766abe4 100644 --- a/app/soapbox/features/ui/components/poll_preview.js +++ b/app/soapbox/features/ui/components/poll_preview.js @@ -1,7 +1,7 @@ +import classNames from 'classnames'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import classNames from 'classnames'; export default class PollPreview extends ImmutablePureComponent { diff --git a/app/soapbox/features/ui/components/profile_dropdown.js b/app/soapbox/features/ui/components/profile_dropdown.js index b5a29856a..d26915c19 100644 --- a/app/soapbox/features/ui/components/profile_dropdown.js +++ b/app/soapbox/features/ui/components/profile_dropdown.js @@ -1,17 +1,19 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { fetchOwnAccounts } from 'soapbox/actions/auth'; +import { is as ImmutableIs } from 'immutable'; import { throttle } from 'lodash'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; -import { isStaff } from 'soapbox/utils/accounts'; import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { logOut, switchAccount } from 'soapbox/actions/auth'; -import { is as ImmutableIs } from 'immutable'; +import { fetchOwnAccounts } from 'soapbox/actions/auth'; import Avatar from 'soapbox/components/avatar'; import DisplayName from 'soapbox/components/display_name'; import { makeGetOtherAccounts } from 'soapbox/selectors'; +import { isStaff } from 'soapbox/utils/accounts'; + +import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; const messages = defineMessages({ add: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, @@ -127,7 +129,7 @@ class ProfileDropdown extends React.PureComponent { }); return ( -
      +
      diff --git a/app/soapbox/features/ui/components/profile_info_panel.js b/app/soapbox/features/ui/components/profile_info_panel.js index 9a42a9a27..8cd4dfb5d 100644 --- a/app/soapbox/features/ui/components/profile_info_panel.js +++ b/app/soapbox/features/ui/components/profile_info_panel.js @@ -1,20 +1,22 @@ 'use strict'; +import classNames from 'classnames'; +import { List as ImmutableList } from 'immutable'; +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import Badge from 'soapbox/components/badge'; import Icon from 'soapbox/components/icon'; import VerificationBadge from 'soapbox/components/verification_badge'; -import Badge from 'soapbox/components/badge'; -import { List as ImmutableList } from 'immutable'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { CryptoAddress } from 'soapbox/features/ui/util/async-components'; import { getAcct, isAdmin, isModerator, isLocal, isVerified } from 'soapbox/utils/accounts'; import { displayFqn } from 'soapbox/utils/state'; -import classNames from 'classnames'; -import { CryptoAddress } from 'soapbox/features/ui/util/async-components'; + import ProfileStats from './profile_stats'; const TICKER_REGEX = /\$([a-zA-Z]*)/i; @@ -78,6 +80,41 @@ class ProfileInfoPanel extends ImmutablePureComponent { return badges; } + getBirthday = () => { + const { account, intl } = this.props; + + const birthday = account.getIn(['pleroma', 'birthday']); + if (!birthday) return null; + + const formattedBirthday = intl.formatDate(birthday, { timeZone: 'UTC', day: 'numeric', month: 'long', year: 'numeric' }); + + const date = new Date(birthday); + const today = new Date(); + + const hasBirthday = date.getDate() === today.getDate() && date.getMonth() === today.getMonth(); + + if (hasBirthday) { + return ( +
      + + +
      + ); + } + return ( +
      + + +
      + ); + } + render() { const { account, displayFqn, intl, identity_proofs, username } = this.props; @@ -148,6 +185,8 @@ class ProfileInfoPanel extends ImmutablePureComponent { />
      } + {this.getBirthday()} + ({ promoItems: getSoapboxConfig(state).getIn(['promoPanel', 'items']), diff --git a/app/soapbox/features/ui/components/reactions_modal.js b/app/soapbox/features/ui/components/reactions_modal.js new file mode 100644 index 000000000..eabe50042 --- /dev/null +++ b/app/soapbox/features/ui/components/reactions_modal.js @@ -0,0 +1,138 @@ +import { List as ImmutableList } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchFavourites, fetchReactions } from 'soapbox/actions/interactions'; +import FilterBar from 'soapbox/components/filter_bar'; +import IconButton from 'soapbox/components/icon_button'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import AccountContainer from 'soapbox/containers/account_container'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + all: { id: 'reactions.all', defaultMessage: 'All' }, +}); + +const mapStateToProps = (state, props) => { + + const favourites = state.getIn(['user_lists', 'favourited_by', props.statusId]); + const reactions = state.getIn(['user_lists', 'reactions', props.statusId]); + const allReactions = favourites && reactions && ImmutableList(favourites ? [{ accounts: favourites, count: favourites.size, name: '👍' }] : []).concat(reactions || []); + + return { + reactions: allReactions, + }; +}; + +export default @connect(mapStateToProps) +@injectIntl +class ReactionsModal extends React.PureComponent { + + static propTypes = { + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + statusId: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + reaction: PropTypes.string, + dispatch: PropTypes.func.isRequired, + reactions: ImmutablePropTypes.list, + }; + + state = { + reaction: this.props.reaction, + } + + fetchData = () => { + const { dispatch, statusId } = this.props; + + dispatch(fetchFavourites(statusId)); + dispatch(fetchReactions(statusId)); + } + + componentDidMount() { + this.fetchData(); + } + + onClickClose = () => { + this.props.onClose('REACTIONS'); + }; + + handleFilterChange = (reaction) => () => { + this.setState({ reaction }); + }; + + renderFilterBar() { + const { intl, reactions } = this.props; + const { reaction } = this.state; + + const items = [ + { + text: intl.formatMessage(messages.all), + action: this.handleFilterChange(''), + name: 'all', + }, + ]; + + reactions.forEach(reaction => items.push( + { + text: `${reaction.name} ${reaction.count}`, + action: this.handleFilterChange(reaction.name), + name: reaction.name, + }, + )); + + return ; + } + + render() { + const { intl, reactions } = this.props; + const { reaction } = this.state; + + const accounts = reactions && (reaction + ? reactions.find(reaction => reaction.name === this.state.reaction).accounts.map(account => ({ id: account, reaction: this.state.reaction })) + : reactions.map(reaction => reaction.accounts.map(account => ({ id: account, reaction: reaction.name }))).flatten()); + + let body; + + if (!accounts) { + body = ; + } else { + const emptyMessage = ; + + body = (<> + {reactions.size > 0 && this.renderFilterBar()} + + {accounts.map((account) => + , + )} + + ); + } + + + return ( +
      +
      +

      + +

      + +
      + {body} +
      + ); + } + +} diff --git a/app/soapbox/features/ui/components/reblogs_modal.js b/app/soapbox/features/ui/components/reblogs_modal.js new file mode 100644 index 000000000..662ec48c7 --- /dev/null +++ b/app/soapbox/features/ui/components/reblogs_modal.js @@ -0,0 +1,108 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; +import { connect } from 'react-redux'; + +import { fetchReblogs } from 'soapbox/actions/interactions'; +import { fetchStatus } from 'soapbox/actions/statuses'; +import IconButton from 'soapbox/components/icon_button'; +import LoadingIndicator from 'soapbox/components/loading_indicator'; +import ScrollableList from 'soapbox/components/scrollable_list'; +import AccountContainer from 'soapbox/containers/account_container'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, +}); + +const mapStateToProps = (state, props) => { + return { + accountIds: state.getIn(['user_lists', 'reblogged_by', props.statusId]), + }; +}; + +export default @connect(mapStateToProps) +@injectIntl +class ReblogsModal extends React.PureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + statusId: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + dispatch: PropTypes.func.isRequired, + accountIds: ImmutablePropTypes.orderedSet, + }; + + fetchData = () => { + const { dispatch, statusId } = this.props; + + dispatch(fetchReblogs(statusId)); + dispatch(fetchStatus(statusId)); + } + + componentDidMount() { + this.fetchData(); + this.unlistenHistory = this.context.router.history.listen((_, action) => { + if (action === 'PUSH') { + this.onClickClose(null, true); + } + }); + } + + componentWillUnmount() { + if (this.unlistenHistory) { + this.unlistenHistory(); + } + } + + onClickClose = () => { + this.props.onClose('REBLOGS'); + }; + + render() { + const { intl, accountIds } = this.props; + + let body; + + if (!accountIds) { + body = ; + } else { + const emptyMessage = ; + + body = ( + + {accountIds.map(id => + , + )} + + ); + } + + + return ( +
      +
      +

      + +

      + +
      + {body} +
      + ); + } + +} diff --git a/app/soapbox/features/ui/components/reply_mentions_modal.js b/app/soapbox/features/ui/components/reply_mentions_modal.js new file mode 100644 index 000000000..3685b0a51 --- /dev/null +++ b/app/soapbox/features/ui/components/reply_mentions_modal.js @@ -0,0 +1,85 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + +import IconButton from 'soapbox/components/icon_button'; +import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose'; +import { makeGetStatus } from 'soapbox/selectors'; + +import Account from '../../reply_mentions/account'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, +}); + +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); + + return state => { + const status = getStatus(state, { id: state.getIn(['compose', 'in_reply_to']) }); + + if (!status) { + return { + isReply: false, + }; + } + + const me = state.get('me'); + const account = state.getIn(['accounts', me]); + + const mentions = statusToMentionsAccountIdsArray(state, status, account); + + return { + mentions, + author: status.getIn(['account', 'id']), + isReply: true, + }; + }; +}; + +class ReplyMentionsModal extends ImmutablePureComponent { + + static propTypes = { + mentions: ImmutablePropTypes.OrderedSet, + author: PropTypes.string, + intl: PropTypes.object.isRequired, + onClose: PropTypes.func.isRequired, + dispatch: PropTypes.func.isRequired, + }; + + onClickClose = () => { + const { onClose } = this.props; + onClose('REPLY_MENTIONS'); + }; + + render() { + const { intl, mentions, author } = this.props; + + return ( +
      +
      + +

      + +

      +
      +
      + {mentions.map(accountId => )} +
      +
      + ); + } + +} + +export default injectIntl(connect(makeMapStateToProps)(ReplyMentionsModal)); diff --git a/app/soapbox/features/ui/components/report_modal.js b/app/soapbox/features/ui/components/report_modal.js index fd34da406..7202a5383 100644 --- a/app/soapbox/features/ui/components/report_modal.js +++ b/app/soapbox/features/ui/components/report_modal.js @@ -1,21 +1,23 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { changeReportComment, changeReportForward, changeReportBlock, submitReport } from '../../../actions/reports'; -import { blockAccount } from '../../../actions/accounts'; -import { expandAccountTimeline } from '../../../actions/timelines'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { makeGetAccount } from '../../../selectors'; -import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; -import StatusCheckBox from '../../report/containers/status_check_box_container'; import { OrderedSet } from 'immutable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Button from '../../../components/button'; +import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; import Toggle from 'react-toggle'; -import IconButton from '../../../components/icon_button'; + import { isRemote, getDomain } from 'soapbox/utils/accounts'; import { getFeatures } from 'soapbox/utils/features'; +import { blockAccount } from '../../../actions/accounts'; +import { changeReportComment, changeReportForward, changeReportBlock, submitReport } from '../../../actions/reports'; +import { expandAccountTimeline } from '../../../actions/timelines'; +import Button from '../../../components/button'; +import IconButton from '../../../components/icon_button'; +import { makeGetAccount } from '../../../selectors'; +import StatusCheckBox from '../../report/containers/status_check_box_container'; + const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, @@ -107,7 +109,7 @@ class ReportModal extends ImmutablePureComponent { return (
      - + {account.get('acct')} }} />
      diff --git a/app/soapbox/features/ui/components/sign_up_panel.js b/app/soapbox/features/ui/components/sign_up_panel.js index c9497b9e0..cee57bb0d 100644 --- a/app/soapbox/features/ui/components/sign_up_panel.js +++ b/app/soapbox/features/ui/components/sign_up_panel.js @@ -1,8 +1,9 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import { connect } from 'react-redux'; +import React from 'react'; import { FormattedMessage, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; const mapStateToProps = state => { return { diff --git a/app/soapbox/features/ui/components/subscription_button.js b/app/soapbox/features/ui/components/subscription_button.js index 131f55b9a..30de7185e 100644 --- a/app/soapbox/features/ui/components/subscription_button.js +++ b/app/soapbox/features/ui/components/subscription_button.js @@ -1,15 +1,18 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages, injectIntl } from 'react-intl'; import classNames from 'classnames'; -import Button from 'soapbox/components/button'; -import Icon from 'soapbox/components/icon'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + import { + followAccount, subscribeAccount, unsubscribeAccount, } from 'soapbox/actions/accounts'; +import Button from 'soapbox/components/button'; +import Icon from 'soapbox/components/icon'; const messages = defineMessages({ subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' }, @@ -32,6 +35,13 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(subscribeAccount(account.get('id'))); } }, + onNotifyToggle(account) { + if (account.getIn(['relationship', 'notifying'])) { + dispatch(followAccount(account.get('id'), { notify: false })); + } else { + dispatch(followAccount(account.get('id'), { notify: true })); + } + }, }); export default @connect(mapStateToProps, mapDispatchToProps) @@ -40,15 +50,17 @@ class SubscriptionButton extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, + features: PropTypes.object.isRequired, }; handleSubscriptionToggle = () => { - this.props.onSubscriptionToggle(this.props.account); + if (this.props.features.accountNotifies) this.props.onNotifyToggle(this.props.account); + else this.props.onSubscriptionToggle(this.props.account); } render() { - const { account, intl } = this.props; - const subscribing = account.getIn(['relationship', 'subscribing']); + const { account, intl, features } = this.props; + const subscribing = features.accountNotifies ? account.getIn(['relationship', 'notifying']) : account.getIn(['relationship', 'subscribing']); const following = account.getIn(['relationship', 'following']); const requested = account.getIn(['relationship', 'requested']); diff --git a/app/soapbox/features/ui/components/tabs_bar.js b/app/soapbox/features/ui/components/tabs_bar.js index 959ce245c..70f7fbd26 100644 --- a/app/soapbox/features/ui/components/tabs_bar.js +++ b/app/soapbox/features/ui/components/tabs_bar.js @@ -1,22 +1,26 @@ -import React from 'react'; +import classNames from 'classnames'; import PropTypes from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { Link, NavLink, withRouter } from 'react-router-dom'; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; import { connect } from 'react-redux'; -import classNames from 'classnames'; +import { Link, NavLink, withRouter } from 'react-router-dom'; + +import { getSettings } from 'soapbox/actions/settings'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import Icon from 'soapbox/components/icon'; import IconWithCounter from 'soapbox/components/icon_with_counter'; import SearchContainer from 'soapbox/features/compose/containers/search_container'; -import Avatar from '../../../components/avatar'; -import Icon from 'soapbox/components/icon'; -import ProfileDropdown from './profile_dropdown'; -import { openModal } from '../../../actions/modal'; -import { openSidebar } from '../../../actions/sidebar'; -import ThemeToggle from '../../ui/components/theme_toggle_container'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { isStaff } from 'soapbox/utils/accounts'; import { getFeatures } from 'soapbox/utils/features'; +import { openModal } from '../../../actions/modals'; +import { openSidebar } from '../../../actions/sidebar'; +import Avatar from '../../../components/avatar'; +import ThemeToggle from '../../ui/components/theme_toggle_container'; + +import ProfileDropdown from './profile_dropdown'; + const messages = defineMessages({ post: { id: 'tabs_bar.post', defaultMessage: 'Post' }, }); @@ -53,10 +57,10 @@ class TabsBar extends React.PureComponent { return pathname === '/' || pathname.startsWith('/timeline/'); } - onProfilePage = () => { + shouldShowLinks = () => { try { const { pathname } = this.context.router.route.location; - return pathname.startsWith('/@') && !pathname.includes('/posts/'); + return (pathname.startsWith('/@') && !pathname.includes('/posts/')) || pathname.startsWith('/admin'); } catch { return false; } @@ -65,7 +69,7 @@ class TabsBar extends React.PureComponent { render() { const { intl, account, logo, onOpenCompose, onOpenSidebar, features, dashboardCount, notificationCount, chatsCount } = this.props; const { collapsed } = this.state; - const profilePage = this.onProfilePage(); + const showLinks = this.shouldShowLinks(); const classes = classNames('tabs-bar', { 'tabs-bar--collapsed': collapsed, @@ -94,7 +98,7 @@ class TabsBar extends React.PureComponent {
      {account ? ( <> - {profilePage && ( + {showLinks && ( <> { const reportsCount = state.getIn(['admin', 'openReports']).count(); const approvalCount = state.getIn(['admin', 'awaitingApproval']).count(); const instance = state.get('instance'); + const settings = getSettings(state); + + // In demo mode, use the Soapbox logo + const logo = settings.get('demo') ? require('images/soapbox-logo.svg') : getSoapboxConfig(state).get('logo'); return { account: state.getIn(['accounts', me]), - logo: getSoapboxConfig(state).get('logo'), + logo, features: getFeatures(instance), notificationCount: state.getIn(['notifications', 'unread']), - chatsCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0), + chatsCount: state.getIn(['chats', 'items']).reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0), dashboardCount: reportsCount + approvalCount, }; }; diff --git a/app/soapbox/features/ui/components/theme_toggle.js b/app/soapbox/features/ui/components/theme_toggle.js index 4eb54f588..73a6d95ad 100644 --- a/app/soapbox/features/ui/components/theme_toggle.js +++ b/app/soapbox/features/ui/components/theme_toggle.js @@ -1,10 +1,11 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { defineMessages } from 'react-intl'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Icon from '../../../components/icon'; +import { defineMessages } from 'react-intl'; import Toggle from 'react-toggle'; +import Icon from '../../../components/icon'; + const messages = defineMessages({ switchToLight: { id: 'tabs_bar.theme_toggle_light', defaultMessage: 'Switch to light theme' }, switchToDark: { id: 'tabs_bar.theme_toggle_dark', defaultMessage: 'Switch to dark theme' }, diff --git a/app/soapbox/features/ui/components/theme_toggle_container.js b/app/soapbox/features/ui/components/theme_toggle_container.js index f9b1d5b73..b000d1ba5 100644 --- a/app/soapbox/features/ui/components/theme_toggle_container.js +++ b/app/soapbox/features/ui/components/theme_toggle_container.js @@ -1,6 +1,8 @@ -import { connect } from 'react-redux'; -import { changeSetting, getSettings } from 'soapbox/actions/settings'; import { injectIntl } from 'react-intl'; +import { connect } from 'react-redux'; + +import { changeSetting, getSettings } from 'soapbox/actions/settings'; + import ThemeToggle from './theme_toggle'; const mapStateToProps = state => { diff --git a/app/soapbox/features/ui/components/trends_panel.js b/app/soapbox/features/ui/components/trends_panel.js index 9a45977cb..1460d352b 100644 --- a/app/soapbox/features/ui/components/trends_panel.js +++ b/app/soapbox/features/ui/components/trends_panel.js @@ -1,11 +1,13 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import { fetchTrends } from '../../../actions/trends'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImmutablePropTypes from 'react-immutable-proptypes'; + import Icon from 'soapbox/components/icon'; + +import { fetchTrends } from '../../../actions/trends'; import Hashtag from '../../../components/hashtag'; class TrendsPanel extends ImmutablePureComponent { @@ -35,7 +37,7 @@ class TrendsPanel extends ImmutablePureComponent { return (
      - + diff --git a/app/soapbox/features/ui/components/unauthorized_modal.js b/app/soapbox/features/ui/components/unauthorized_modal.js index 4a7167e6e..be54a6bec 100644 --- a/app/soapbox/features/ui/components/unauthorized_modal.js +++ b/app/soapbox/features/ui/components/unauthorized_modal.js @@ -1,42 +1,161 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { Link } from 'react-router-dom'; +import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + +import { remoteInteraction } from 'soapbox/actions/interactions'; +import snackbar from 'soapbox/actions/snackbar'; import IconButton from 'soapbox/components/icon_button'; +import { getFeatures } from 'soapbox/utils/features'; const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, + accountPlaceholder: { id: 'remote_interaction.account_placeholder', defaultMessage: 'Enter your username@domain you want to act from' }, + userNotFoundError: { id: 'remote_interaction.user_not_found_error', defaultMessage: 'Couldn\'t find given user' }, }); -const mapStateToProps = state => { - const me = state.get('me'); +const mapStateToProps = (state, props) => { + const instance = state.get('instance'); + const features = getFeatures(instance); + + if (props.action !== 'FOLLOW') { + return { + features, + siteTitle: state.getIn(['instance', 'title']), + remoteInteractionsAPI: features.remoteInteractionsAPI, + }; + } + + const userName = state.getIn(['accounts', props.account, 'display_name']); + return { - account: state.getIn(['accounts', me]), + features, siteTitle: state.getIn(['instance', 'title']), + userName, + remoteInteractionsAPI: features.remoteInteractionsAPI, }; }; +const mapDispatchToProps = dispatch => ({ + dispatch, + onRemoteInteraction(ap_id, account) { + return dispatch(remoteInteraction(ap_id, account)); + }, +}); + class UnauthorizedModal extends ImmutablePureComponent { static propTypes = { intl: PropTypes.object.isRequired, + features: PropTypes.object.isRequired, onClose: PropTypes.func.isRequired, + onRemoteInteraction: PropTypes.func.isRequired, + userName: PropTypes.string, }; + state = { + account: '', + }; + + onAccountChange = e => { + this.setState({ account: e.target.value }); + } + onClickClose = () => { this.props.onClose('UNAUTHORIZED'); }; + onClickProceed = e => { + e.preventDefault(); + + const { intl, ap_id, dispatch, onClose, onRemoteInteraction } = this.props; + const { account } = this.state; + + onRemoteInteraction(ap_id, account) + .then(url => { + window.open(url, '_new', 'noopener,noreferrer'); + onClose('UNAUTHORIZED'); + }) + .catch(error => { + if (error.message === 'Couldn\'t find user') { + dispatch(snackbar.error(intl.formatMessage(messages.userNotFoundError))); + } + }); + } + + renderRemoteInteractions() { + const { intl, siteTitle, userName, action } = this.props; + const { account } = this.state; + + let header; + let button; + + if (action === 'FOLLOW') { + header = ; + button = ; + } else if (action === 'REPLY') { + header = ; + button = ; + } else if (action === 'REBLOG') { + header = ; + button = ; + } else if (action === 'FAVOURITE') { + header = ; + button = ; + } else if (action === 'POLL_VOTE') { + header = ; + button = ; + } + + return ( +
      +
      +

      {header}

      + +
      +
      + + + + +
      + + + +
      +

      + + + + + + +
      +
      + ); + } + render() { - const { intl, siteTitle } = this.props; + const { intl, features, siteTitle, action } = this.props; + + if (action && features.remoteInteractionsAPI && features.federating) return this.renderRemoteInteractions(); return (

      - +
      @@ -61,4 +180,4 @@ class UnauthorizedModal extends ImmutablePureComponent { } -export default injectIntl(connect(mapStateToProps)(UnauthorizedModal)); +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(UnauthorizedModal)); diff --git a/app/soapbox/features/ui/components/upload_area.js b/app/soapbox/features/ui/components/upload_area.js index 4491135a3..a78534106 100644 --- a/app/soapbox/features/ui/components/upload_area.js +++ b/app/soapbox/features/ui/components/upload_area.js @@ -1,8 +1,9 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import Motion from '../../ui/util/optional_motion'; -import spring from 'react-motion/lib/spring'; +import React from 'react'; import { FormattedMessage } from 'react-intl'; +import spring from 'react-motion/lib/spring'; + +import Motion from '../../ui/util/optional_motion'; export default class UploadArea extends React.PureComponent { diff --git a/app/soapbox/features/ui/components/user_panel.js b/app/soapbox/features/ui/components/user_panel.js index f7b3bcd31..9bf52c4da 100644 --- a/app/soapbox/features/ui/components/user_panel.js +++ b/app/soapbox/features/ui/components/user_panel.js @@ -1,17 +1,19 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { Link } from 'react-router-dom'; -import { injectIntl, FormattedMessage } from 'react-intl'; -import { makeGetAccount } from '../../../selectors'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + import Avatar from 'soapbox/components/avatar'; -import { shortNumberFormat } from 'soapbox/utils/numbers'; -import { getAcct, isVerified } from 'soapbox/utils/accounts'; -import { displayFqn } from 'soapbox/utils/state'; import StillImage from 'soapbox/components/still_image'; import VerificationBadge from 'soapbox/components/verification_badge'; +import { getAcct, isVerified } from 'soapbox/utils/accounts'; +import { shortNumberFormat } from 'soapbox/utils/numbers'; +import { displayFqn } from 'soapbox/utils/state'; + +import { makeGetAccount } from '../../../selectors'; class UserPanel extends ImmutablePureComponent { diff --git a/app/soapbox/features/ui/components/video_modal.js b/app/soapbox/features/ui/components/video_modal.js index 20bedb48a..1291d32b1 100644 --- a/app/soapbox/features/ui/components/video_modal.js +++ b/app/soapbox/features/ui/components/video_modal.js @@ -1,11 +1,10 @@ +import PropTypes from 'prop-types'; import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import Video from 'soapbox/features/video'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -export const previewState = 'previewVideoModal'; +import Video from 'soapbox/features/video'; export default class VideoModal extends ImmutablePureComponent { @@ -17,32 +16,6 @@ export default class VideoModal extends ImmutablePureComponent { onClose: PropTypes.func.isRequired, }; - static contextTypes = { - router: PropTypes.object, - }; - - componentDidMount() { - if (this.context.router) { - const history = this.context.router.history; - - history.push(history.location.pathname, previewState); - - this.unlistenHistory = history.listen(() => { - this.props.onClose(); - }); - } - } - - componentWillUnmount() { - if (this.context.router) { - this.unlistenHistory(); - - if (this.context.router.history.location.state === previewState) { - this.context.router.history.goBack(); - } - } - } - handleStatusClick = e => { const { status, account } = this.props; if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { diff --git a/app/soapbox/features/ui/components/who_to_follow_panel.js b/app/soapbox/features/ui/components/who_to_follow_panel.js index 34bac9e81..24ecafc4a 100644 --- a/app/soapbox/features/ui/components/who_to_follow_panel.js +++ b/app/soapbox/features/ui/components/who_to_follow_panel.js @@ -1,11 +1,13 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import ImmutablePropTypes from 'react-immutable-proptypes'; + import Icon from 'soapbox/components/icon'; + +import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions'; import AccountContainer from '../../../containers/account_container'; const messages = defineMessages({ diff --git a/app/soapbox/features/ui/components/zoomable_image.js b/app/soapbox/features/ui/components/zoomable_image.js index eec87aafd..b9064fa4f 100644 --- a/app/soapbox/features/ui/components/zoomable_image.js +++ b/app/soapbox/features/ui/components/zoomable_image.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; const MIN_SCALE = 1; const MAX_SCALE = 4; diff --git a/app/soapbox/features/ui/containers/bundle_container.js b/app/soapbox/features/ui/containers/bundle_container.js index 3af058789..dc2802822 100644 --- a/app/soapbox/features/ui/containers/bundle_container.js +++ b/app/soapbox/features/ui/containers/bundle_container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux'; +import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from '../../../actions/bundles'; import Bundle from '../components/bundle'; -import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from '../../../actions/bundles'; const mapDispatchToProps = dispatch => ({ onFetch() { diff --git a/app/soapbox/features/ui/containers/columns_area_container.js b/app/soapbox/features/ui/containers/columns_area_container.js index 05f99cc75..184a831fa 100644 --- a/app/soapbox/features/ui/containers/columns_area_container.js +++ b/app/soapbox/features/ui/containers/columns_area_container.js @@ -1,7 +1,9 @@ import { connect } from 'react-redux'; -import ColumnsArea from '../components/columns_area'; + import { getSettings } from 'soapbox/actions/settings'; +import ColumnsArea from '../components/columns_area'; + const mapStateToProps = state => ({ columns: getSettings(state).get('columns'), }); diff --git a/app/soapbox/features/ui/containers/modal_container.js b/app/soapbox/features/ui/containers/modal_container.js index ba0e52785..a3f01dcd7 100644 --- a/app/soapbox/features/ui/containers/modal_container.js +++ b/app/soapbox/features/ui/containers/modal_container.js @@ -1,20 +1,28 @@ import { connect } from 'react-redux'; -import { closeModal } from '../../../actions/modal'; + import { cancelReplyCompose } from '../../../actions/compose'; +import { closeModal } from '../../../actions/modals'; import ModalRoot from '../components/modal_root'; -const mapStateToProps = state => ({ - type: state.get('modal').modalType, - props: state.get('modal').modalProps, -}); +const mapStateToProps = state => { + const modal = state.get('modals').last({ + modalType: null, + modalProps: {}, + }); + + return { + type: modal.modalType, + props: modal.modalProps, + }; +}; const mapDispatchToProps = (dispatch) => ({ - onClose(optionalType) { - if (optionalType === 'COMPOSE') { + onClose(type) { + if (type === 'COMPOSE') { dispatch(cancelReplyCompose()); } - dispatch(closeModal()); + dispatch(closeModal(type)); }, }); diff --git a/app/soapbox/features/ui/containers/notifications_container.js b/app/soapbox/features/ui/containers/notifications_container.js index 79488b1af..5904a8d66 100644 --- a/app/soapbox/features/ui/containers/notifications_container.js +++ b/app/soapbox/features/ui/containers/notifications_container.js @@ -1,6 +1,9 @@ +import React from 'react'; import { injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; import { NotificationStack } from 'react-notification'; +import { connect } from 'react-redux'; +import { Link } from 'react-router-dom'; + import { dismissAlert } from '../../../actions/alerts'; import { getAlerts } from '../../../selectors'; @@ -15,22 +18,35 @@ const defaultBarStyleFactory = (index, style, notification) => { const mapStateToProps = (state, { intl }) => { const notifications = getAlerts(state); - notifications.forEach(notification => ['title', 'message'].forEach(key => { - const value = notification[key]; + notifications.forEach(notification => { + ['title', 'message', 'actionLabel'].forEach(key => { + const value = notification[key]; - if (typeof value === 'object') { - notification[key] = intl.formatMessage(value); + if (typeof value === 'object') { + notification[key] = intl.formatMessage(value); + } + }); + + if (notification.actionLabel) { + notification.action = ( + + {notification.actionLabel} + + ); } - })); + }); - return { notifications }; + return { notifications, linkComponent: Link }; }; const mapDispatchToProps = (dispatch) => { + const onDismiss = alert => { + dispatch(dismissAlert(alert)); + }; + return { - onDismiss: alert => { - dispatch(dismissAlert(alert)); - }, + onDismiss, + onClick: onDismiss, barStyleFactory: defaultBarStyleFactory, activeBarStyleFactory: defaultBarStyleFactory, }; diff --git a/app/soapbox/features/ui/containers/status_list_container.js b/app/soapbox/features/ui/containers/status_list_container.js index c5afed275..925c5d732 100644 --- a/app/soapbox/features/ui/containers/status_list_container.js +++ b/app/soapbox/features/ui/containers/status_list_container.js @@ -1,10 +1,12 @@ -import { connect } from 'react-redux'; -import StatusList from '../../../components/status_list'; import { OrderedSet as ImmutableOrderedSet } from 'immutable'; -import { makeGetStatusIds } from 'soapbox/selectors'; import { debounce } from 'lodash'; +import { connect } from 'react-redux'; + import { dequeueTimeline } from 'soapbox/actions/timelines'; +import { makeGetStatusIds } from 'soapbox/selectors'; + import { scrollTopTimeline } from '../../../actions/timelines'; +import StatusList from '../../../components/status_list'; const makeMapStateToProps = () => { const getStatusIds = makeGetStatusIds(); diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 4256988b6..ca9c94e18 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -1,50 +1,52 @@ 'use strict'; import classNames from 'classnames'; +import { debounce } from 'lodash'; +import PropTypes from 'prop-types'; import React from 'react'; import { HotKeys } from 'react-hotkeys'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { Switch, withRouter } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import { debounce } from 'lodash'; -import { uploadCompose, resetCompose } from '../../actions/compose'; -import { expandHomeTimeline } from '../../actions/timelines'; -import { expandNotifications } from '../../actions/notifications'; -import { fetchMarker } from 'soapbox/actions/markers'; -import { fetchReports, fetchUsers, fetchConfig } from '../../actions/admin'; -import { fetchFilters } from '../../actions/filters'; +import { Redirect } from 'react-router-dom'; + import { fetchChats } from 'soapbox/actions/chats'; -import { clearHeight } from '../../actions/height_cache'; -import { openModal } from '../../actions/modal'; -import { fetchFollowRequests } from '../../actions/accounts'; -import { fetchScheduledStatuses } from '../../actions/scheduled_statuses'; -import { WrappedRoute } from './util/react_router_helpers'; -import BundleContainer from './containers/bundle_container'; -import TabsBar from './components/tabs_bar'; -import ProfilePage from 'soapbox/pages/profile_page'; +import { fetchCustomEmojis } from 'soapbox/actions/custom_emojis'; +import { fetchMarker } from 'soapbox/actions/markers'; +import { register as registerPushNotifications } from 'soapbox/actions/push_notifications'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import Icon from 'soapbox/components/icon'; +import ThumbNavigation from 'soapbox/components/thumb_navigation'; +import AdminPage from 'soapbox/pages/admin_page'; +import DefaultPage from 'soapbox/pages/default_page'; // import GroupsPage from 'soapbox/pages/groups_page'; // import GroupPage from 'soapbox/pages/group_page'; -// import GroupSidebarPanel from '../groups/sidebar_panel'; -import HomePage from 'soapbox/pages/home_page'; -import DefaultPage from 'soapbox/pages/default_page'; -import StatusPage from 'soapbox/pages/status_page'; import EmptyPage from 'soapbox/pages/default_page'; -import AdminPage from 'soapbox/pages/admin_page'; +import HomePage from 'soapbox/pages/home_page'; +import ProfilePage from 'soapbox/pages/profile_page'; import RemoteInstancePage from 'soapbox/pages/remote_instance_page'; -import { connectUserStream } from '../../actions/streaming'; -import { register as registerPushNotifications } from 'soapbox/actions/push_notifications'; -import { Redirect } from 'react-router-dom'; -import Icon from 'soapbox/components/icon'; +import StatusPage from 'soapbox/pages/status_page'; import { isStaff, isAdmin } from 'soapbox/utils/accounts'; import { getAccessToken } from 'soapbox/utils/auth'; +import { getVapidKey } from 'soapbox/utils/auth'; import { getFeatures } from 'soapbox/utils/features'; -import { fetchCustomEmojis } from 'soapbox/actions/custom_emojis'; -import ThumbNavigation from 'soapbox/components/thumb_navigation'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; +import { fetchFollowRequests } from '../../actions/accounts'; +import { fetchReports, fetchUsers, fetchConfig } from '../../actions/admin'; +import { uploadCompose, resetCompose } from '../../actions/compose'; +import { fetchFilters } from '../../actions/filters'; +import { clearHeight } from '../../actions/height_cache'; +import { openModal } from '../../actions/modals'; +import { expandNotifications } from '../../actions/notifications'; +import { fetchScheduledStatuses } from '../../actions/scheduled_statuses'; +import { connectUserStream } from '../../actions/streaming'; +import { expandHomeTimeline } from '../../actions/timelines'; + +// import GroupSidebarPanel from '../groups/sidebar_panel'; +import TabsBar from './components/tabs_bar'; +import BundleContainer from './containers/bundle_container'; import { Status, CommunityTimeline, @@ -55,9 +57,6 @@ import { HomeTimeline, Followers, Following, - Reblogs, - Reactions, - Favourites, DirectTimeline, Conversations, HashtagTimeline, @@ -105,7 +104,9 @@ import { UserIndex, FederationRestrictions, Aliases, + Migration, FollowRecommendations, + Directory, SidebarMenu, UploadArea, NotificationsContainer, @@ -117,7 +118,10 @@ import { IntentionalError, Developers, CreateApp, + SettingsStore, } from './util/async-components'; +import { WrappedRoute } from './util/react_router_helpers'; + // Dummy import, to make sure that ends up in the application bundle. // Without this it ends up in ~8 very commonly used bundles. @@ -135,6 +139,7 @@ const mapStateToProps = state => { const account = state.getIn(['accounts', me]); const instance = state.get('instance'); const soapbox = getSoapboxConfig(state); + const vapidKey = getVapidKey(state); return { dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null, @@ -144,6 +149,7 @@ const mapStateToProps = state => { account, features: getFeatures(instance), soapbox, + vapidKey, }; }; @@ -254,6 +260,7 @@ class SwitchingColumnsArea extends React.PureComponent { + @@ -273,6 +280,7 @@ class SwitchingColumnsArea extends React.PureComponent { + @@ -291,9 +299,6 @@ class SwitchingColumnsArea extends React.PureComponent { - - - @@ -310,18 +315,20 @@ class SwitchingColumnsArea extends React.PureComponent { + - + - - - - - + + + + + - + + @@ -357,6 +364,7 @@ class UI extends React.PureComponent { account: PropTypes.object, features: PropTypes.object.isRequired, soapbox: ImmutablePropTypes.map.isRequired, + vapidKey: PropTypes.string, }; state = { @@ -465,9 +473,40 @@ class UI extends React.PureComponent { trailing: true, }); - componentDidMount() { + // Load initial data when a user is logged in + loadAccountData = () => { const { account, features, dispatch } = this.props; - if (!account) return; + + dispatch(expandHomeTimeline()); + + dispatch(expandNotifications()) + .then(() => dispatch(fetchMarker(['notifications']))) + .catch(console.error); + + if (features.chats) { + dispatch(fetchChats()); + } + + if (isStaff(account)) { + dispatch(fetchReports({ state: 'open' })); + dispatch(fetchUsers(['local', 'need_approval'])); + } + + if (isAdmin(account)) { + dispatch(fetchConfig()); + } + + setTimeout(() => dispatch(fetchFilters()), 500); + + if (account.get('locked')) { + setTimeout(() => dispatch(fetchFollowRequests()), 700); + } + + setTimeout(() => dispatch(fetchScheduledStatuses()), 900); + } + + componentDidMount() { + const { account, vapidKey, dispatch } = this.props; window.addEventListener('resize', this.handleResize, { passive: true }); document.addEventListener('dragenter', this.handleDragEnter, false); @@ -485,47 +524,33 @@ class UI extends React.PureComponent { } if (account) { - dispatch(expandHomeTimeline()); - - dispatch(expandNotifications()) - .then(() => dispatch(fetchMarker(['notifications']))) - .catch(console.error); - - if (features.chats) { - dispatch(fetchChats()); - } - - if (isStaff(account)) { - dispatch(fetchReports({ state: 'open' })); - dispatch(fetchUsers(['local', 'need_approval'])); - } - - if (isAdmin(account)) { - dispatch(fetchConfig()); - } - - setTimeout(() => dispatch(fetchFilters()), 500); - - if (account.get('locked')) { - setTimeout(() => dispatch(fetchFollowRequests()), 700); - } - - setTimeout(() => dispatch(fetchScheduledStatuses()), 900); + this.loadAccountData(); } dispatch(fetchCustomEmojis()); this.connectStreaming(); - dispatch(registerPushNotifications()); + + if (vapidKey) { + dispatch(registerPushNotifications()); + } } componentDidUpdate(prevProps) { this.connectStreaming(); - const { dispatch, account, features } = this.props; + const { dispatch, account, features, vapidKey } = this.props; - if (features.chats && account && !prevProps.features.chats) { + // The user has logged in + if (account && !prevProps.account) { + this.loadAccountData(); + // The instance has loaded + } else if (account && features.chats && !prevProps.features.chats) { dispatch(fetchChats()); } + + if (vapidKey && !prevProps.vapidKey) { + dispatch(registerPushNotifications()); + } } componentWillUnmount() { @@ -647,14 +672,12 @@ class UI extends React.PureComponent { } render() { - const { streamingUrl, features, soapbox } = this.props; + const { features, soapbox } = this.props; const { draggingOver, mobile } = this.state; const { intl, children, location, dropdownMenuIsOpen, me } = this.props; // Wait for login to succeed or fail if (me === null) return null; - // If login didn't fail, wait for streaming to become available - if (me !== false && !streamingUrl) return null; const handlers = me ? { help: this.handleHotkeyToggleHelp, diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index b01582ac1..5f44a2801 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -94,18 +94,6 @@ export function Following() { return import(/* webpackChunkName: "features/following" */'../../following'); } -export function Reblogs() { - return import(/* webpackChunkName: "features/reblogs" */'../../reblogs'); -} - -export function Reactions() { - return import(/* webpackChunkName: "features/reactions" */'../../reactions'); -} - -export function Favourites() { - return import(/* webpackChunkName: "features/favourites" */'../../favourites'); -} - export function FollowRequests() { return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests'); } @@ -190,6 +178,10 @@ export function ComposeModal() { return import(/* webpackChunkName: "features/ui" */'../components/compose_modal'); } +export function ReplyMentionsModal() { + return import(/* webpackChunkName: "features/ui" */'../components/reply_mentions_modal'); +} + export function UnauthorizedModal() { return import(/* webpackChunkName: "features/ui" */'../components/unauthorized_modal'); } @@ -206,6 +198,26 @@ export function ComponentModal() { return import(/* webpackChunkName: "features/ui" */'../components/component_modal'); } +export function ReblogsModal() { + return import(/* webpackChunkName: "features/ui" */'../components/reblogs_modal'); +} + +export function FavouritesModal() { + return import(/* webpackChunkName: "features/ui" */'../components/favourites_modal'); +} + +export function ReactionsModal() { + return import(/* webpackChunkName: "features/ui" */'../components/reactions_modal'); +} + +export function MentionsModal() { + return import(/* webpackChunkName: "features/ui" */'../components/mentions_modal'); +} + +export function BirthdaysModal() { + return import(/* webpackChunkName: "features/ui" */'../components/birthdays_modal'); +} + export function ListEditor() { return import(/* webpackChunkName: "features/list_editor" */'../../list_editor'); } @@ -330,6 +342,10 @@ export function ProfileMediaPanel() { return import(/* webpackChunkName: "features/account_gallery" */'../components/profile_media_panel'); } +export function PinnedAccountsPanel() { + return import(/* webpackChunkName: "features/pinned_accounts" */'../components/pinned_accounts_panel'); +} + export function InstanceInfoPanel() { return import(/* webpackChunkName: "features/remote_timeline" */'../components/instance_info_panel'); } @@ -398,6 +414,10 @@ export function Aliases() { return import(/* webpackChunkName: "features/aliases" */'../../aliases'); } +export function Migration() { + return import(/* webpackChunkName: "features/migration" */'../../migration'); +} + export function ScheduleForm() { return import(/* webpackChunkName: "features/compose" */'../../compose/components/schedule_form'); } @@ -410,6 +430,10 @@ export function FollowRecommendations() { return import(/* webpackChunkName: "features/follow_recommendations" */'../../follow_recommendations'); } +export function Directory() { + return import(/* webpackChunkName: "features/directory" */'../../directory'); +} + export function RegisterInvite() { return import(/* webpackChunkName: "features/register_invite" */'../../register_invite'); } @@ -433,3 +457,7 @@ export function Developers() { export function CreateApp() { return import(/* webpackChunkName: "features/developers" */'../../developers/apps/create'); } + +export function SettingsStore() { + return import(/* webpackChunkName: "features/developers" */'../../developers/settings_store'); +} diff --git a/app/soapbox/features/ui/util/optional_motion.js b/app/soapbox/features/ui/util/optional_motion.js index b1e7355d2..c9a17f39e 100644 --- a/app/soapbox/features/ui/util/optional_motion.js +++ b/app/soapbox/features/ui/util/optional_motion.js @@ -1,10 +1,12 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import ReducedMotion from './reduced_motion'; +import React from 'react'; import Motion from 'react-motion/lib/Motion'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; +import ReducedMotion from './reduced_motion'; + const mapStateToProps = state => ({ reduceMotion: getSettings(state).get('reduceMotion'), }); diff --git a/app/soapbox/features/ui/util/pending_status_builder.js b/app/soapbox/features/ui/util/pending_status_builder.js index 191a99f1d..fcb41c14f 100644 --- a/app/soapbox/features/ui/util/pending_status_builder.js +++ b/app/soapbox/features/ui/util/pending_status_builder.js @@ -1,13 +1,31 @@ import { fromJS } from 'immutable'; +import { OrderedSet as ImmutableOrderedSet } from 'immutable'; + import { normalizeStatus } from 'soapbox/actions/importer/normalizer'; -import { makeGetAccount } from 'soapbox/selectors'; +import { makeGetAccount, makeGetStatus } from 'soapbox/selectors'; export const buildStatus = (state, pendingStatus, idempotencyKey) => { const getAccount = makeGetAccount(); + const getStatus = makeGetStatus(); const me = state.get('me'); const account = getAccount(state, me); + let mentions; + if (pendingStatus.get('in_reply_to_id')) { + const inReplyTo = getStatus(state, { id: pendingStatus.get('in_reply_to_id') }); + + if (inReplyTo.getIn(['account', 'id']) === me) { + mentions = ImmutableOrderedSet([account.get('acct')]).union(pendingStatus.get('to', [])); + } else { + mentions = pendingStatus.get('to', []); + } + + mentions = mentions.map(mention => ({ + username: mention.split('@')[0], + })); + } + const status = normalizeStatus({ account, application: null, @@ -22,11 +40,12 @@ export const buildStatus = (state, pendingStatus, idempotencyKey) => { in_reply_to_account_id: null, in_reply_to_id: pendingStatus.get('in_reply_to_id'), language: null, - media_attachments: [], // TODO: render pending thumbs - mentions: [], + media_attachments: pendingStatus.get('media_ids').map(id => ({ id })), + mentions, muted: false, pinned: false, poll: pendingStatus.get('poll', null), + quote: pendingStatus.get('quote_id', null), reblog: null, reblogged: false, reblogs_count: 0, diff --git a/app/soapbox/features/ui/util/react_router_helpers.js b/app/soapbox/features/ui/util/react_router_helpers.js index 4a636a738..d5543c421 100644 --- a/app/soapbox/features/ui/util/react_router_helpers.js +++ b/app/soapbox/features/ui/util/react_router_helpers.js @@ -1,16 +1,24 @@ -import React from 'react'; -import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { connect } from 'react-redux'; import { Redirect, Route } from 'react-router-dom'; -import ColumnsAreaContainer from '../containers/columns_area_container'; -import ColumnLoading from '../components/column_loading'; + +import { getSettings } from 'soapbox/actions/settings'; +import { isStaff, isAdmin } from 'soapbox/utils/accounts'; + import BundleColumnError from '../components/bundle_column_error'; +import ColumnForbidden from '../components/column_forbidden'; +import ColumnLoading from '../components/column_loading'; import BundleContainer from '../containers/bundle_container'; +import ColumnsAreaContainer from '../containers/columns_area_container'; const mapStateToProps = state => { + const me = state.get('me'); + return { - me: state.get('me'), + account: state.getIn(['accounts', me]), + settings: getSettings(state), }; }; @@ -22,8 +30,12 @@ class WrappedRoute extends React.Component { content: PropTypes.node, componentParams: PropTypes.object, layout: PropTypes.object, + account: ImmutablePropTypes.map, + settings: ImmutablePropTypes.map.isRequired, publicRoute: PropTypes.bool, - me: SoapboxPropTypes.me, + staffOnly: PropTypes.bool, + adminOnly: PropTypes.bool, + developerOnly: PropTypes.bool, }; static defaultProps = { @@ -72,6 +84,14 @@ class WrappedRoute extends React.Component { ); } + renderForbidden = () => { + return ( + + + + ); + } + renderError = (props) => { return ( @@ -80,16 +100,27 @@ class WrappedRoute extends React.Component { ); } - render() { - const { component: Component, content, publicRoute, me, ...rest } = this.props; + loginRedirect = () => { + const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types + return ; + } - if (!publicRoute && me === false) { - const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types - return ; - // return { - // window.location.href = `/auth/sign_in?redirect_uri=${actualUrl}`; - // return null; - // }}/> + render() { + const { component: Component, content, account, settings, publicRoute, developerOnly, staffOnly, adminOnly, ...rest } = this.props; + + const authorized = [ + account || publicRoute, + developerOnly ? settings.get('isDeveloper') : true, + staffOnly ? account && isStaff(account) : true, + adminOnly ? account && isAdmin(account) : true, + ].every(c => c); + + if (!authorized) { + if (!account) { + return this.loginRedirect(); + } else { + return this.renderForbidden(); + } } return ; diff --git a/app/soapbox/features/ui/util/reduced_motion.js b/app/soapbox/features/ui/util/reduced_motion.js index 95519042b..62d36f626 100644 --- a/app/soapbox/features/ui/util/reduced_motion.js +++ b/app/soapbox/features/ui/util/reduced_motion.js @@ -1,8 +1,8 @@ // Like react-motion's Motion, but reduces all animations to cross-fades // for the benefit of users with motion sickness. +import PropTypes from 'prop-types'; import React from 'react'; import Motion from 'react-motion/lib/Motion'; -import PropTypes from 'prop-types'; const stylesToKeep = ['opacity', 'backgroundOpacity']; diff --git a/app/soapbox/features/video/index.js b/app/soapbox/features/video/index.js index 9fc3831bb..90ce9a007 100644 --- a/app/soapbox/features/video/index.js +++ b/app/soapbox/features/video/index.js @@ -1,15 +1,17 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import classNames from 'classnames'; import { fromJS, is } from 'immutable'; import { throttle, debounce } from 'lodash'; -import classNames from 'classnames'; -import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen'; -import Icon from 'soapbox/components/icon'; -import Blurhash from 'soapbox/components/blurhash'; -import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { connect } from 'react-redux'; + import { getSettings } from 'soapbox/actions/settings'; +import Blurhash from 'soapbox/components/blurhash'; +import Icon from 'soapbox/components/icon'; + +import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio'; +import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen'; const messages = defineMessages({ play: { id: 'video.play', defaultMessage: 'Play' }, diff --git a/app/soapbox/globals.js b/app/soapbox/globals.js index 3b49e1fe6..08e773695 100644 --- a/app/soapbox/globals.js +++ b/app/soapbox/globals.js @@ -2,7 +2,7 @@ * globals: do things through the console. * This feature is for developers. */ -import { changeSetting } from 'soapbox/actions/settings'; +import { changeSettingImmediate } from 'soapbox/actions/settings'; export const createGlobals = store => { const Soapbox = { @@ -11,7 +11,7 @@ export const createGlobals = store => { if (![true, false].includes(bool)) { throw `Invalid option ${bool}. Must be true or false.`; } - store.dispatch(changeSetting(['isDeveloper'], bool)); + store.dispatch(changeSettingImmediate(['isDeveloper'], bool)); return bool; }, }; diff --git a/app/soapbox/locales/ar.json b/app/soapbox/locales/ar.json index dfa20c7d6..fb7dca136 100644 --- a/app/soapbox/locales/ar.json +++ b/app/soapbox/locales/ar.json @@ -8,6 +8,7 @@ "account.block_domain": "إخفاء كل شيئ قادم من اسم النطاق {domain}", "account.blocked": "محظور", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "هذا الحساب لا يتبع أحدًا بعد.", "account.follows_you": "يتابعك", "account.hide_reblogs": "إخفاء ترقيات @{name}", + "account.last_status": "Last active", "account.link_verified_on": "تم التحقق مِن مِلْكية هذا الرابط بتاريخ {date}", "account.locked_info": "تم تأمين خصوصية هذا الحساب عبر قفل. صاحب الحساب يُراجِع يدويا طلبات المتابَعة و الاشتراك بحسابه.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} انتقل إلى:", "account.mute": "أكتم @{name}", "account.muted": "مكتوم", + "account.never_active": "Never", "account.posts": "تبويقات", "account.posts_with_replies": "التبويقات و الردود", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "أغلق", "bundle_modal_error.message": "لقد وقع هناك خطأ أثناء عملية تحميل هذا العنصر.", "bundle_modal_error.retry": "إعادة المحاولة", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "الحسابات المحجوبة", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "الخيط العام المحلي", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "الرسائل المباشرة", + "column.directory": "Browse profiles", "column.domain_blocks": "النطاقات المخفية", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "طلبات المتابعة", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "الرئيسية", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "القوائم", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "الحسابات المكتومة", "column.notifications": "الإخطارات", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "الخيط العام الموحد", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "العودة", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "إخفاء الإعدادات", "column_header.show_settings": "عرض الإعدادات", "community.column_settings.media_only": "الوسائط فقط", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "مدة استطلاع الرأي", "compose_form.poll.option_placeholder": "الخيار {number}", "compose_form.poll.remove_option": "إزالة هذا الخيار", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "بوّق", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "احجبه وابلغ عنه", "confirmations.block.confirm": "حجب", "confirmations.block.message": "هل أنت متأكد أنك تريد حجب {name} ؟", "confirmations.delete.confirm": "حذف", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "هل أنت متأكد أنك تريد حذف هذا المنشور ؟", "confirmations.delete_list.confirm": "احذف", "confirmations.delete_list.message": "هل تود حقا حذف هذه القائمة ؟", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "ترخيص", "follow_request.reject": "رفض", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "العودة", "lightbox.view_context": "اعرض السياق", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "أضف إلى القائمة", "lists.account.remove": "احذف من القائمة", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "هل تود إخفاء الإخطارات القادمة من هذا المستخدم ؟", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "تحرير تبويق جديد", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "النطاقات المخفية", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "المفضلة", "navigation_bar.filters": "الكلمات المكتومة", "navigation_bar.follow_requests": "طلبات المتابعة", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "عن هذا الخادم", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "اختصارات لوحة المفاتيح", "navigation_bar.lists": "Lists", "navigation_bar.logout": "خروج", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "الحسابات المكتومة", "navigation_bar.pins": "التبويقات المثبتة", "navigation_bar.preferences": "التفضيلات", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "الأمان", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "تحديث", "poll.total_votes": "{count, plural, one {# صوت} other {# أصوات}}", "poll.vote": "صَوّت", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "إضافة استطلاع للرأي", "poll_button.remove_poll": "إزالة استطلاع الرأي", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "جارٍ التحميل…", "regeneration_indicator.sublabel": "جارٍ تجهيز تغذية صفحتك الرئيسية!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}ي", "relative_time.hours": "{number}سا", "relative_time.just_now": "الآن", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "إلغاء", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "التحويل إلى {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "ابحث", - "search_popout.search_format": "نمط البحث المتقدم", - "search_popout.tips.full_text": "النص البسيط يقوم بعرض المنشورات التي كتبتها أو قمت بإرسالها أو ترقيتها أو تمت الإشارة إليك فيها من طرف آخرين ، بالإضافة إلى مطابقة أسماء المستخدمين وأسماء العرض وعلامات التصنيف.", - "search_popout.tips.hashtag": "وسم", - "search_popout.tips.status": "حالة", - "search_popout.tips.user": "مستخدِم", "search_results.accounts": "أشخاص", "search_results.hashtags": "الوُسوم", "search_results.statuses": "التبويقات", diff --git a/app/soapbox/locales/ast.json b/app/soapbox/locales/ast.json index 4722504df..1300bdf5b 100644 --- a/app/soapbox/locales/ast.json +++ b/app/soapbox/locales/ast.json @@ -8,6 +8,7 @@ "account.block_domain": "Anubrir tolo de {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Esti usuariu entá nun sigue a naide.", "account.follows_you": "Síguete", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Silenciar a @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts y rempuestes", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Usuarios bloquiaos", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Llinia temporal llocal", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mensaxes direutos", + "column.directory": "Browse profiles", "column.domain_blocks": "Dominios anubríos", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Solicitúes de siguimientu", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Aniciu", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Llistes", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Usuarios silenciaos", "column.notifications": "Avisos", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Llinia temporal federada", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Atrás", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "¿De xuru que quies bloquiar a {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "¿De xuru que quies desaniciar esti estáu?", "confirmations.delete_list.confirm": "Desaniciar", "confirmations.delete_list.message": "¿De xuru que quies desaniciar dafechu esta llista?", "confirmations.domain_block.confirm": "Anubrir tol dominiu", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "¿De xuru que quies silenciar a {name}?", "confirmations.redraft.confirm": "Desaniciar y reeditar", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Refugar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} ye software de códigu abiertu. Pues collaborar o informar de fallos en {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Amestar a la llista", "lists.account.remove": "Desaniciar de la llista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dominios anubríos", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritos", "navigation_bar.filters": "Pallabres silenciaes", "navigation_bar.follow_requests": "Solicitúes de siguimientu", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Tocante a esta instancia", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atayos", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Zarrar sesión", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuarios silenciaos", "navigation_bar.pins": "Toots fixaos", "navigation_bar.preferences": "Preferencies", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguranza", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Cargando…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "agora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Encaboxar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Formatu de gueta avanzada", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estáu", - "search_popout.tips.user": "usuariu", "search_results.accounts": "Xente", "search_results.hashtags": "Etiquetes", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/bg.json b/app/soapbox/locales/bg.json index ecb50a076..b9e7ce2f0 100644 --- a/app/soapbox/locales/bg.json +++ b/app/soapbox/locales/bg.json @@ -8,6 +8,7 @@ "account.block_domain": "скрий всичко от {domain}", "account.blocked": "Блокирани", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Твой последовател", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Публикации", "account.posts_with_replies": "Posts with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Начало", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Списъци", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Известия", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Публичен канал", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Назад", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Раздумай", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} е софтуер с отворен код. Можеш да помогнеш или да докладваш за проблеми в GitLab: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Extended information", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Излизане", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Предпочитания", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Отказ", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Търсене", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/bn.json b/app/soapbox/locales/bn.json index 23e42b941..9ab0d0408 100644 --- a/app/soapbox/locales/bn.json +++ b/app/soapbox/locales/bn.json @@ -8,6 +8,7 @@ "account.block_domain": "{domain} থেকে সব সরিয়ে ফেলুন", "account.blocked": "বন্ধ করা হয়েছে", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "এই ব্যবহারকারী কাওকে এখনো অনুসরণ করেন না।", "account.follows_you": "আপনাকে অনুসরণ করে", "account.hide_reblogs": "@{name}র সমর্থনগুলি সরিয়ে ফেলুন", + "account.last_status": "Last active", "account.link_verified_on": "এই লিংকের মালিকানা চেক করা হয়েছে {date} তারিকে", "account.locked_info": "এই নিবন্ধনের গোপনীয়তার ক্ষেত্র তালা দেওয়া আছে। নিবন্ধনকারী অনুসরণ করার অনুমতি যাদেরকে দেবেন, শুধু তারাই অনুসরণ করতে পারবেন।", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} চলে গেছে এখানে:", "account.mute": "@{name} সব কার্যক্রম আপনার সময়রেখা থেকে সরিয়ে ফেলতে", "account.muted": "সরানো আছে", + "account.never_active": "Never", "account.posts": "টুট", "account.posts_with_replies": "টুট এবং মতামত", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "বন্ধ করুন", "bundle_modal_error.message": "এই অংশটি দেখাতে যেয়ে কোনো সমস্যা হয়েছে।", "bundle_modal_error.retry": "আবার চেষ্টা করুন", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "যাদের বন্ধ করে রাখা হয়েছে", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "স্থানীয় সময়সারি", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "সরাসরি লেখা", + "column.directory": "Browse profiles", "column.domain_blocks": "সরিয়ে ফেলা ওয়েবসাইট", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "অনুসরণের অনুমতি চেয়েছে যারা", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "বাড়ি", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "তালিকাগুলো", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "যাদের কার্যক্রম দেখা বন্ধ আছে", "column.notifications": "প্রজ্ঞাপনগুলো", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "যুক্ত সময়রেখা", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "পেছনে", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "সেটিংগুলো সরান", "column_header.show_settings": "সেটিং দেখান", "community.column_settings.media_only": "শুধুমাত্র ছবি বা ভিডিও", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "ভোটগ্রহনের সময়", "compose_form.poll.option_placeholder": "বিকল্প {number}", "compose_form.poll.remove_option": "এই বিকল্পটি মুছে ফেলুন", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "টুট", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "বন্ধ করুন এবং রিপোর্ট করুন", "confirmations.block.confirm": "বন্ধ করুন", "confirmations.block.message": "আপনি কি নিশ্চিত {name} কে বন্ধ করতে চান ?", "confirmations.delete.confirm": "মুছে ফেলুন", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "আপনি কি নিশ্চিত যে এই লেখাটি মুছে ফেলতে চান ?", "confirmations.delete_list.confirm": "মুছে ফেলুন", "confirmations.delete_list.message": "আপনি কি নিশ্চিত যে আপনি এই তালিকাটি স্থায়িভাবে মুছে ফেলতে চান ?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "অনুমতি দিন", "follow_request.reject": "প্রত্যাখ্যান করুন", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} একটি মুক্ত সফটওয়্যার। তৈরিতে সাহায্য করতে বা কোনো সমস্যা সম্পর্কে জানাতে আমাদের গিটহাবে যেতে পারেন {code_link} (v{code_version})।", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "পূর্ববর্তী", "lightbox.view_context": "প্রসঙ্গটি দেখতে", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "তালিকাতে যুক্ত করতে", "lists.account.remove": "তালিকা থেকে বাদ দিতে", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "এই ব্যবহারকারীর প্রজ্ঞাপন বন্ধ করবেন ?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "নতুন টুট লিখুন", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "বন্ধ করা ওয়েবসাইট", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "পছন্দের", "navigation_bar.filters": "বন্ধ করা শব্দ", "navigation_bar.follow_requests": "অনুসরণের অনুরোধগুলি", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "এই সার্ভার সম্পর্কে", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "হটকীগুলি", "navigation_bar.lists": "Lists", "navigation_bar.logout": "বাইরে যান", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "যেসব বেভহারকারীদের কার্যক্রম বন্ধ করা আছে", "navigation_bar.pins": "পিন দেওয়া টুট", "navigation_bar.preferences": "পছন্দসমূহ", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "নিরাপত্তা", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "বদলেছে কিনা দেখতে", "poll.total_votes": "{count, plural, one {# ভোট} other {# ভোট}}", "poll.vote": "ভোট", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "একটা নির্বাচন যোগ করতে", "poll_button.remove_poll": "নির্বাচন বাদ দিতে", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "আসছে…", "regeneration_indicator.sublabel": "আপনার বাড়ির-সময়রেখা প্রস্তূত করা হচ্ছে!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} দিন", "relative_time.hours": "{number} ঘন্টা", "relative_time.just_now": "এখন", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "বাতিল করতে", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "এটা আরো পাঠান {target} তে", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "খুঁজতে", - "search_popout.search_format": "বিস্তারিতভাবে খোঁজার পদ্ধতি", - "search_popout.tips.full_text": "সাধারণ লেখা দিয়ে খুঁজলে বের হবে সেরকম আপনার লেখা, পছন্দের লেখা, সমর্থন করা লেখা, আপনাকে উল্লেখকরা কোনো লেখা, যা খুঁজছেন সেরকম কোনো ব্যবহারকারীর নাম বা কোনো হ্যাশট্যাগগুলো।", - "search_popout.tips.hashtag": "হ্যাশট্যাগ", - "search_popout.tips.status": "লেখা", - "search_popout.tips.user": "ব্যবহারকারী", "search_results.accounts": "মানুষ", "search_results.hashtags": "হ্যাশট্যাগগুলি", "search_results.statuses": "টুট", diff --git a/app/soapbox/locales/br.json b/app/soapbox/locales/br.json index 91785dc40..42c9262bf 100644 --- a/app/soapbox/locales/br.json +++ b/app/soapbox/locales/br.json @@ -8,6 +8,7 @@ "account.block_domain": "Kuzh kement tra a {domain}", "account.blocked": "Stanket", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Ho heul", "account.hide_reblogs": "Kuzh toudoù skignet gant @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "Dilojet en·he deus {name} da:", "account.mute": "Kuzhat @{name}", "account.muted": "Kuzhet", + "account.never_active": "Never", "account.posts": "Toudoù", "account.posts_with_replies": "Toudoù ha respontoù", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Serriñ", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Klask endro", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Implijour·ezed·ion stanket", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Red-amzer lec'hel", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Kemennadoù prevez", + "column.directory": "Browse profiles", "column.domain_blocks": "Domani kuzhet", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/ca.json b/app/soapbox/locales/ca.json index b17c65409..a25a4d8be 100644 --- a/app/soapbox/locales/ca.json +++ b/app/soapbox/locales/ca.json @@ -8,6 +8,7 @@ "account.block_domain": "Amaga-ho tot de {domain}", "account.blocked": "Bloquejat", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Desactivat", "account.deactivated_description": "Aquest compte ha estat desactivat.", @@ -22,6 +23,7 @@ "account.follows.empty": "Ningú segueix aquest usuari encara.", "account.follows_you": "Et segueix", "account.hide_reblogs": "Amaga els impulsos de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La propietat d'aquest enllaç es va verificar el dia {date}", "account.locked_info": "L'estat de privacitat d'aquest compte està establert a privat. El propietari revisa manualment qui pot seguir-los.", "account.login": "Inici de sessió", @@ -31,6 +33,7 @@ "account.moved_to": "{name} s'ha mogut a:", "account.mute": "Silencia @{name}", "account.muted": "Silenciat", + "account.never_active": "Never", "account.posts": "Publicacions", "account.posts_with_replies": "Publicacions i respostes", "account.profile": "Perfil", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Desverifica @{name}", "admin.users.actions.verify_user": "Verifica @{name}", "admin.users.user_deactivated_message": "@{acct} s'ha desactivat", "admin.users.user_deleted_message": "@{acct} s'ha suprimit", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} s'ha desfet la verificació", "admin.users.user_verified_message": "@{acct} s'ha verificat", "admin_nav.awaiting_approval": "Esperant aprovació", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Crea una còpia de seguretat", "backups.empty_message": "No s'han trobat còpies de seguretat. {action}", "backups.empty_message.action": "Crear-ne una ara?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Tanca", "bundle_modal_error.message": "S'ha produït un error en carregar aquest component.", "bundle_modal_error.retry": "Torna-ho a provar", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Envia", "chat_box.input.placeholder": "Envia un missatge…", "chat_panels.main_window.empty": "Cap xat trobat. Per arrencar un xat, visita el perfil d'un usuari.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Elimina missatge", "chats.actions.more": "Més", "chats.actions.report": "Denunciar usuari", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Notificació amb so desactivada", "chats.audio_toggle_on": "Notificació amb so activada", "chats.dividers.today": "Avui", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Registre de moderació", "column.admin.reports": "Denuncies", "column.admin.reports.menu.moderation_log": "Registre de moderació", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Còpies de seguretat", "column.blocks": "Usuaris bloquejats", "column.bookmarks": "Marcadors", "column.chats": "Xats", "column.community": "Línia de temps local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Missatges directes", + "column.directory": "Browse profiles", "column.domain_blocks": "Dominis ocults", "column.edit_profile": "Editar perfil", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Paraules silenciades", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Tota la paraula", "column.filters.whole_word_hint": "Quan la paraula clau o frase és alfanumèrica només s'aplicarà si coincideix amb tota la paraula", "column.follow_requests": "Peticions de seguiment", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Grups", "column.home": "Inici", "column.import_data": "Importa dades", "column.info": "Informació del servidor", "column.lists": "Llistes", + "column.mentions": "Mentions", "column.mfa": "Autenticació multifactor", "column.mfa_cancel": "Cancel·la", "column.mfa_confirm_button": "Confirmar", @@ -195,8 +224,11 @@ "column.mfa_setup": "Continua a la configuració", "column.mutes": "Usuaris silenciats", "column.notifications": "Notificacions", + "column.pins": "Pinned posts", "column.preferences": "Preferències", + "column.profile_directory": "Profile directory", "column.public": "Línia de temps federada", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Línia de temps federada", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Seguretat", "column.soapbox_config": "Configuració de Soapbox", "column_back_button.label": "Enrere", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Amaga la configuració", "column_header.show_settings": "Mostra la configuració", "community.column_settings.media_only": "Només multimèdia", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durada de l'enquesta", "compose_form.poll.option_placeholder": "Opció {number}", "compose_form.poll.remove_option": "Elimina aquesta opció", - "compose_form.poll.type.hint": "Fes clic per activar o desactivar el tipus de votació. El botó d'opció (per defecte) és senzill. La casella de selecció és múltiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publica", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "Estàs a punt de marcar un missatge de @{acct} com a no sensible.", "confirmations.admin.mark_status_sensitive.confirm": "Marcar publicació com a sensible", "confirmations.admin.mark_status_sensitive.message": "Estàs a punt de marcar un missatge de @{acct} com a sensible.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquejar i informar", "confirmations.block.confirm": "Bloqueja", "confirmations.block.message": "Estàs segur que vols bloquejar a {name}?", "confirmations.delete.confirm": "Suprimeix", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Estàs segur que vols suprimir aquesta publicació?", "confirmations.delete_list.confirm": "Suprimeix", "confirmations.delete_list.message": "Estàs segur que vols suprimir permanentment aquesta llista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donar", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "Aquest compte és un bot", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Mostra el nom", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Capçalera", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF o JPG. Com a màxim 2 MB. Es reduirà a 400x400px", "edit_profile.hints.bot": "Aquest compte realitza principalment accions automatitzades i pot ser que no sigui controlat", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF o JPG. Com a màxim 2 MB. Es reduirà a 1500x500px", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Cal que aprovis els seguidors manualment", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autoritzar", "follow_request.reject": "Rebutjar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} és un programari de codi obert. Pots contribuir o informar de problemes a {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "Aquest grup no té membres.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Veure el context", "list.click_to_add": "Fes clic aquí per afegir persones", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Afegeix o suprimeix de les llistes", "lists.account.add": "Afegir a la llista", "lists.account.remove": "Treure de la llista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Amagar notificacions d'aquest usuari?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Redacta nou toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dominis ocults", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorits", "navigation_bar.filters": "Paraules silenciades", "navigation_bar.follow_requests": "Sol·licituds de seguiment", "navigation_bar.import_data": "Importa dades", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Sobre aquest servidor", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Dreceres de teclat", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Tancar sessió", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuaris silenciats", "navigation_bar.pins": "Publicacions fixades", "navigation_bar.preferences": "Preferències", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguretat", "navigation_bar.soapbox_config": "Configuració de Soapbox", "notification.chat_mention": "{name} t'ha enviat un missatge", @@ -627,14 +682,18 @@ "poll.refresh": "Actualitza", "poll.total_votes": "{count, plural, one {# vot} other {# vots}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Afegeix una enquesta", "poll_button.remove_poll": "Elimina l'enquesta", "preferences.fields.auto_play_gif_label": "Reprodueix automàticament els GIF animats", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Mostra el diàleg de confirmació abans de tornar a publicar", "preferences.fields.content_type_label": "Format de la publicació", "preferences.fields.delete_modal_label": "Mostra el diàleg de confirmació abans de suprimir una publicació", "preferences.fields.demetricator_label": "Utilitza Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Amaga les imatges marcades com a sensibles", "preferences.fields.display_media.hide_all": "Oculta sempre les imatges", "preferences.fields.display_media.show_all": "Mostra sempre les imatges", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Afegeix un compte existent", "profile_dropdown.logout": "Tanca la sessió @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Carregant…", "regeneration_indicator.sublabel": "S'està preparant la línia de temps Inici!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Nom d'usuari", "registration.lead": "Amb un compte a {instance} podreu seguir a la gent de qualsevol servidor del Fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Per què vols unir-te?", "registration.reason_hint": "Això ens ajudarà a revisar la teva inscripció", "registration.sign_up": "Registra't", "registration.tos": "Termes del servei", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "fa {number} dies", "relative_time.hours": "fa {number} hores", "relative_time.just_now": "ara", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "Estàs veient la línia de temps de {instance}.", "reply_indicator.cancel": "Cancel·lar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Bloquejar {target}", "report.block_hint": "També vols bloquejar aquest compte?", "report.forward": "Reenvia a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Cercar", - "search_popout.search_format": "Format de cerca avançada", - "search_popout.tips.full_text": "Text simple recupera publicacions que has escrit, les marcades com a favorites, les impulsades o en les que has estat esmentat, així com usuaris, noms d'usuari i etiquetes.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estat", - "search_popout.tips.user": "usuari", "search_results.accounts": "Gent", "search_results.hashtags": "Etiquetes", "search_results.statuses": "Publicacions", diff --git a/app/soapbox/locales/co.json b/app/soapbox/locales/co.json index a00609a63..493acdea9 100644 --- a/app/soapbox/locales/co.json +++ b/app/soapbox/locales/co.json @@ -8,6 +8,7 @@ "account.block_domain": "Piattà tuttu da {domain}", "account.blocked": "Bluccatu", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "St'utilizatore ùn seguita nisunu.", "account.follows_you": "Vi seguita", "account.hide_reblogs": "Piattà spartere da @{name}", + "account.last_status": "Last active", "account.link_verified_on": "A prupietà di stu ligame hè stata verificata u {date}", "account.locked_info": "U statutu di vita privata di u contu hè chjosu. U pruprietariu esamina manualmente e dumande d'abbunamentu.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} hè partutu nant'à:", "account.mute": "Piattà @{name}", "account.muted": "Piattatu", + "account.never_active": "Never", "account.posts": "Statuti", "account.posts_with_replies": "Statuti è risposte", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Chjudà", "bundle_modal_error.message": "C'hè statu un prublemu caricandu st'elementu.", "bundle_modal_error.retry": "Pruvà torna", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Utilizatori bluccati", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Linea pubblica lucale", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Missaghji diretti", + "column.directory": "Browse profiles", "column.domain_blocks": "Duminii piattati", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Dumande d'abbunamentu", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Accolta", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Liste", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Utilizatori piattati", "column.notifications": "Nutificazione", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Linea pubblica glubale", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Ritornu", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Piattà i parametri", "column_header.show_settings": "Mustrà i parametri", "community.column_settings.media_only": "Solu media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durata di u scandagliu", "compose_form.poll.option_placeholder": "Scelta {number}", "compose_form.poll.remove_option": "Toglie sta scelta", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bluccà è signalà", "confirmations.block.confirm": "Bluccà", "confirmations.block.message": "Site sicuru·a che vulete bluccà @{name}?", "confirmations.delete.confirm": "Toglie", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Site sicuru·a che vulete supprime stu statutu?", "confirmations.delete_list.confirm": "Toglie", "confirmations.delete_list.message": "Site sicuru·a che vulete supprime sta lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Auturizà", "follow_request.reject": "Righjittà", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitLab: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Pricidente", "lightbox.view_context": "Vede u cuntestu", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Aghjunghje à a lista", "lists.account.remove": "Toglie di a lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Piattà nutificazione da st'utilizatore?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Scrive un novu statutu", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Duminii piattati", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favuriti", "navigation_bar.filters": "Parolle silenzate", "navigation_bar.follow_requests": "Dumande d'abbunamentu", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "À prupositu di u servore", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Accorte cù a tastera", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Scunnettassi", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Utilizatori piattati", "navigation_bar.pins": "Statuti puntarulati", "navigation_bar.preferences": "Preferenze", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sicurità", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Attualizà", "poll.total_votes": "{count, plural, one {# votu} other {# voti}}", "poll.vote": "Vutà", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Aghjunghje", "poll_button.remove_poll": "Toglie u scandagliu", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Caricamentu…", "regeneration_indicator.sublabel": "Priparazione di a vostra pagina d'accolta!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}ghj", "relative_time.hours": "{number}o", "relative_time.just_now": "avà", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Annullà", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Trasferisce à {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Circà", - "search_popout.search_format": "Ricerca avanzata", - "search_popout.tips.full_text": "I testi simplici rimandanu i statuti ch'avete scritti, aghjunti à i vostri favuriti, spartuti o induve quelli site mintuvatu·a, è ancu i cugnomi, nomi pubblichi è hashtag chì currispondenu.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "statutu", - "search_popout.tips.user": "utilizatore", "search_results.accounts": "Ghjente", "search_results.hashtags": "Hashtag", "search_results.statuses": "Statuti", diff --git a/app/soapbox/locales/cs.json b/app/soapbox/locales/cs.json index 7e02ca28b..ef7ea02bc 100644 --- a/app/soapbox/locales/cs.json +++ b/app/soapbox/locales/cs.json @@ -8,6 +8,7 @@ "account.block_domain": "Skrýt vše z {domain}", "account.blocked": "Blokován/a", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deaktivován", "account.deactivated_description": "Tento účet byl deaktivován.", @@ -22,6 +23,7 @@ "account.follows.empty": "Tento uživatel ještě nikoho nesleduje.", "account.follows_you": "Sleduje vás", "account.hide_reblogs": "Skrýt boosty od uživatele @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Vlastnictví tohoto odkazu bylo zkontrolováno {date}", "account.locked_info": "Stav soukromí tohoto účtu je nastaven na zamčeno. Jeho vlastník ručně posuzuje, kdo ho může sledovat.", "account.login": "Přihlásit se", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se přesunul/a na:", "account.mute": "Skrýt uživatele @{name}", "account.muted": "Skryt/a", + "account.never_active": "Never", "account.posts": "Příspěvky", "account.posts_with_replies": "Příspěvky a odpovědi", "account.profile": "Profil", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Zavřít", "bundle_modal_error.message": "Při načítání tohoto komponentu se něco pokazilo.", "bundle_modal_error.retry": "Zkusit znovu", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Poslat", "chat_box.input.placeholder": "Poslat zprávu…", "chat_panels.main_window.empty": "Žádné chaty nenalezeny. Pro začnutí chatu, navštivte nečí profil.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Odstranit zprávu", "chats.actions.more": "Více", "chats.actions.report": "Nahlásit uživatele", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio upozornění vypnuté", "chats.audio_toggle_on": "Audio upozornění zapnoté", "chats.dividers.today": "Dnes", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokovaní uživatelé", "column.bookmarks": "Záložky", "column.chats": "Chaty", "column.community": "Místní zeď", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Přímé zprávy", + "column.directory": "Browse profiles", "column.domain_blocks": "Skryté domény", "column.edit_profile": "Editovat profil", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Filtrovaná slova", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Celé slovo", "column.filters.whole_word_hint": "Pokud je klíčové slovo či fráze pouze alfanumerické, bude aplikováno pouze pokud je kompletně shodné", "column.follow_requests": "Požadavky o sledování", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Skupiny", "column.home": "Domů", "column.import_data": "Importovat data", "column.info": "Server information", "column.lists": "Seznamy", + "column.mentions": "Mentions", "column.mfa": "Multi-Faktorová Authentifikace", "column.mfa_cancel": "Zrušit", "column.mfa_confirm_button": "Potvrdit", @@ -195,8 +224,11 @@ "column.mfa_setup": "Pokračovat v nastavování", "column.mutes": "Skrytí uživatelé", "column.notifications": "Oznámení", + "column.pins": "Pinned posts", "column.preferences": "Preference", + "column.profile_directory": "Profile directory", "column.public": "Federovaná zeď", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox nastavení", "column_back_button.label": "Zpět", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Skrýt nastavení", "column_header.show_settings": "Zobrazit nastavení", "community.column_settings.media_only": "Pouze média", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Délka ankety", "compose_form.poll.option_placeholder": "Volba {number}", "compose_form.poll.remove_option": "Odstranit tuto volbu", - "compose_form.poll.type.hint": "Klikněte pro změnu typu ankety. Kulaté tlačítko značí jednu volbu a hranaté značí více.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publikovat", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokovat a nahlásit", "confirmations.block.confirm": "Blokovat", "confirmations.block.message": "Jste si jistý/á, že chcete zablokovat uživatele {name}?", "confirmations.delete.confirm": "Smazat", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Jste si jistý/á, že chcete smazat tento příspěvek?", "confirmations.delete_list.confirm": "Smazat", "confirmations.delete_list.message": "Jste si jistý/á, že chcete tento seznam navždy smazat?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Darovat", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "Toto je účet robot", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Zobrazované jméno", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Hlavička", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF nebo JPG. Maximálně 2 MB. Bude zmenšen na 400x400px", "edit_profile.hints.bot": "Tento účet provádí automatizované úkony a není aktivně monitorován.", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF nebo JPG. Maximálně 2 MB. Bude zmenšen na 1500x500px", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Požaduje manuální schvalování sledujících.", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizovat", "follow_request.reject": "Odmítnout", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} je otevřený software. Na GitLabu k němu můžete přispět nebo nahlásit chyby: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "Tato skupina nemá členy.", @@ -505,6 +553,8 @@ "lightbox.previous": "Předchozí", "lightbox.view_context": "Zobrazit kontext", "list.click_to_add": "Přidat úživatele", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Přidat nebo odstranit ze seznamů", "lists.account.add": "Přidat do seznamu", "lists.account.remove": "Odebrat ze seznamu", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Skrýt oznámení od tohoto uživatele?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Vytvořit nový příspěvek", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Skryté domény", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Oblíbené", "navigation_bar.filters": "Skrytá slova", "navigation_bar.follow_requests": "Požadavky o sledování", "navigation_bar.import_data": "Importovat data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "O tomto serveru", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Klávesové zkratky", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Odhlásit", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Skrytí uživatelé", "navigation_bar.pins": "Připnuté příspěvky", "navigation_bar.preferences": "Předvolby", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Zabezpečení", "navigation_bar.soapbox_config": "Soapbox nastavení", "notification.chat_mention": "{name} Vám poslal/a zprávu", @@ -627,14 +682,18 @@ "poll.refresh": "Obnovit", "poll.total_votes": "{count, plural, one {# hlas} few {# hlasy} many {# hlasu} other {# hlasů}}", "poll.vote": "Hlasovat", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Přidat anketu", "poll_button.remove_poll": "Odstranit anketu", "preferences.fields.auto_play_gif_label": "Automaticky přehrávat GIFy", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Zobrazit potvrzovací dialog před boostnutím", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Zobrazit potvrzovací dialog před smazáním příspěvku", "preferences.fields.demetricator_label": "Použít Demetrikátor", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Načítám…", "regeneration_indicator.sublabel": "Váš domovský proud se připravuje!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Jméno", "registration.lead": "S účtem na {instance} budete moci sledovat další uživatele na fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Proč se chcete připojit?", "registration.reason_hint": "Toto nám pomůže posoudit Vaši přihlášku", "registration.sign_up": "Registrovat", "registration.tos": "Podmínky služby", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} d", "relative_time.hours": "{number} h", "relative_time.just_now": "teď", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Zrušit", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Zablokovat {target}", "report.block_hint": "Chcete zablokovat tento účet?", "report.forward": "Přeposlat na {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Hledat", - "search_popout.search_format": "Pokročilé hledání", - "search_popout.tips.full_text": "Navrátí příspěvek, který jste napsal/a, oblíbil/a si, boostnul/a, nebo v nich byl/a zmíněn/a, a také odpovídající přezdívky, zobrazovaná jména a hashtagy.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "příspěvek", - "search_popout.tips.user": "uživatel", "search_results.accounts": "Lidé", "search_results.hashtags": "Hashtagy", "search_results.statuses": "Příspěvky", diff --git a/app/soapbox/locales/cy.json b/app/soapbox/locales/cy.json index e35988597..eeb3d7ca2 100644 --- a/app/soapbox/locales/cy.json +++ b/app/soapbox/locales/cy.json @@ -8,6 +8,7 @@ "account.block_domain": "Cuddio popeth rhag {domain}", "account.blocked": "Blociwyd", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.follows_you": "Yn eich dilyn chi", "account.hide_reblogs": "Cuddio bwstiau o @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Gwiriwyd perchnogaeth y ddolen yma ar {date}", "account.locked_info": "Mae'r statws preifatrwydd cyfrif hwn wedi'i osod i gloi. Mae'r perchennog yn adolygu'r sawl sy'n gallu eu dilyn.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "Mae @{name} wedi symud i:", "account.mute": "Tawelu @{name}", "account.muted": "Distewyd", + "account.never_active": "Never", "account.posts": "Tŵtiau", "account.posts_with_replies": "Tŵtiau ac atebion", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Cau", "bundle_modal_error.message": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.", "bundle_modal_error.retry": "Ceiswich eto", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Defnyddwyr a flociwyd", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Ffrwd lleol", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Negeseuon preifat", + "column.directory": "Browse profiles", "column.domain_blocks": "Parthau cuddiedig", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Ceisiadau dilyn", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hafan", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Rhestrau", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Defnyddwyr a ddistewyd", "column.notifications": "Hysbysiadau", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Ffrwd y ffederasiwn", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Nôl", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Cuddio dewisiadau", "column_header.show_settings": "Dangos gosodiadau", "community.column_settings.media_only": "Cyfryngau yn unig", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Cyfnod pleidlais", "compose_form.poll.option_placeholder": "Dewisiad {number}", "compose_form.poll.remove_option": "Tynnu'r dewisiad", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tŵt", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Rhwystro ac Adrodd", "confirmations.block.confirm": "Blocio", "confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?", "confirmations.delete.confirm": "Dileu", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y tŵt hwn?", "confirmations.delete_list.confirm": "Dileu", "confirmations.delete_list.message": "Ydych chi'n sicr eich bod eisiau dileu y rhestr hwn am byth?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Caniatau", "follow_request.reject": "Gwrthod", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "Mae {code_name} yn feddalwedd côd agored. Mae modd cyfrannu neu adrodd materion ar GitLab ar {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Blaenorol", "lightbox.view_context": "Gweld cyd-destyn", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Ychwanegwch at restr", "lists.account.remove": "Dileu o'r rhestr", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Cuddio hysbysiadau rhag y defnyddiwr hwn?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Cyfansoddi tŵt newydd", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Parthau cuddiedig", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Ffefrynnau", "navigation_bar.filters": "Geiriau a dawelwyd", "navigation_bar.follow_requests": "Ceisiadau dilyn", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Ynghylch yr achos hwn", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Bysellau brys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Allgofnodi", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Defnyddwyr a dawelwyd", "navigation_bar.pins": "Tŵtiau wedi eu pinio", "navigation_bar.preferences": "Dewisiadau", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Diogelwch", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Adnewyddu", "poll.total_votes": "{count, plural, one {# bleidlais} other {# o bleidleisiau}}", "poll.vote": "Pleidleisio", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Ychwanegu pleidlais", "poll_button.remove_poll": "Tynnu pleidlais", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Llwytho…", "regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}dydd", "relative_time.hours": "{number}awr", "relative_time.just_now": "nawr", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Canslo", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Ymlaen i {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Chwilio", - "search_popout.search_format": "Fformat chwilio uwch", - "search_popout.tips.full_text": "Mae testun syml yn dychwelyd tŵtiau yr ydych wedi ysgrifennu, hoffi, wedi'u bŵstio, neu wedi'ch crybwyll ynddynt, ynghyd a chyfateb a enwau defnyddwyr, enwau arddangos ac hashnodau.", - "search_popout.tips.hashtag": "hashnod", - "search_popout.tips.status": "tŵt", - "search_popout.tips.user": "defnyddiwr", "search_results.accounts": "Pobl", "search_results.hashtags": "Hanshnodau", "search_results.statuses": "Tŵtiau", diff --git a/app/soapbox/locales/da.json b/app/soapbox/locales/da.json index b1d14b7ee..d463c189a 100644 --- a/app/soapbox/locales/da.json +++ b/app/soapbox/locales/da.json @@ -8,6 +8,7 @@ "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blokeret", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Denne bruger følger endnu ikke nogen.", "account.follows_you": "Følger dig", "account.hide_reblogs": "Skjul fremhævelserne fra @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ejerskabet af dette link blev tjekket den %{date}", "account.locked_info": "Denne kontos privatlivsstatus er sat til låst. Ejeren bedømmer manuelt, hvem der kan følge dem.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} er flyttet til:", "account.mute": "Dæmp @{name}", "account.muted": "Dæmpet", + "account.never_active": "Never", "account.posts": "Trut", "account.posts_with_replies": "Trut og svar", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Luk", "bundle_modal_error.message": "Noget gik galt under indlæsningen af dette komponent.", "bundle_modal_error.retry": "Prøv igen", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokerede brugere", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokal tidslinje", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direkte beskeder", + "column.directory": "Browse profiles", "column.domain_blocks": "Skjulte domæner", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Anmodning om at følge", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hjem", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lister", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Dæmpede brugere", "column.notifications": "Notifikationer", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Fælles tidslinje", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tilbage", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Skjul indstillinger", "column_header.show_settings": "Vis indstillinger", "community.column_settings.media_only": "Kun medie", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Afstemningens varighed", "compose_form.poll.option_placeholder": "Valgmulighed {number}", "compose_form.poll.remove_option": "Fjern denne valgmulighed", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Trut", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokér og anmeld", "confirmations.block.confirm": "Bloker", "confirmations.block.message": "Er du sikker på, du vil blokere {name}?", "confirmations.delete.confirm": "Slet", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Er du sikker på, du vil slette denne status?", "confirmations.delete_list.confirm": "Slet", "confirmations.delete_list.message": "Er du sikker på, du vil slette denne liste?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Godkend", "follow_request.reject": "Afvis", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} er et open source software. Du kan bidrage eller rapporterer fejl på GitLab {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Forrige", "lightbox.view_context": "Vis kontekst", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Tilføj til liste", "lists.account.remove": "Fjern fra liste", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Skjul notifikationer fra denne bruger?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Skriv nyt trut", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Skjulte domæner", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritter", "navigation_bar.filters": "Dæmpede ord", "navigation_bar.follow_requests": "Følgeanmodninger", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Om denne instans", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hurtigtast", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logud", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Dæmpede brugere", "navigation_bar.pins": "Fastgjorte trut", "navigation_bar.preferences": "Præferencer", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sikkerhed", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Opdatér", "poll.total_votes": "{count, plural, one {# stemme} other {# stemmer}}", "poll.vote": "Stem", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Tilføj en afstemning", "poll_button.remove_poll": "Fjern afstemning", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Indlæser…", "regeneration_indicator.sublabel": "Din startside er ved at blive forberedt!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}t", "relative_time.just_now": "nu", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Annuller", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Videresend til {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Søg", - "search_popout.search_format": "Avanceret søgeformat", - "search_popout.tips.full_text": "Simpel tekst returnerer statusser du har skrevet, favoriseret, boostet, eller er blevet nævnt i såvel som matchende brugernavne, profilnavne, og hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "bruger", "search_results.accounts": "Personer", "search_results.hashtags": "Hashtags", "search_results.statuses": "Trut", diff --git a/app/soapbox/locales/de.json b/app/soapbox/locales/de.json index faeb4b97e..d4bf70722 100644 --- a/app/soapbox/locales/de.json +++ b/app/soapbox/locales/de.json @@ -1,15 +1,16 @@ { "about.also_available": "Available in:", - "accordion.collapse": "Collapse", - "accordion.expand": "Expand", + "accordion.collapse": "Einklappen", + "accordion.expand": "Ausklappen", "account.add_or_remove_from_list": "Hinzufügen oder Entfernen von Listen", "account.badges.bot": "Bot", "account.block": "@{name} blockieren", "account.block_domain": "Alles von {domain} verstecken", "account.blocked": "Blockiert", - "account.chat": "Chat with @{name}", - "account.column_settings.title": "Acccount timeline settings", - "account.deactivated": "Deactivated", + "account.chat": "Mit @{name} chatten", + "account.column_settings.description": "These settings apply to all account timelines.", + "account.column_settings.title": "Einstellung für die Zeitleiste dieses Accounts", + "account.deactivated": "Deaktiviert", "account.deactivated_description": "Dieser Account wurde deaktiviert.", "account.direct": "Direktnachricht an @{name}", "account.domain_blocked": "Domain versteckt", @@ -22,6 +23,7 @@ "account.follows.empty": "Dieses Profil folgt noch niemandem.", "account.follows_you": "Folgt dir", "account.hide_reblogs": "Geteilte Beiträge von @{name} verbergen", + "account.last_status": "Last active", "account.link_verified_on": "Besitz dieses Links wurde geprüft am {date}", "account.locked_info": "Der Privatsphärenstatus dieses Kontos wurde auf privat gesetzt. Die Person bestimmt manuell, wer ihr folgen darf.", "account.login": "Anmelden", @@ -31,49 +33,50 @@ "account.moved_to": "{name} ist umgezogen auf:", "account.mute": "@{name} stummschalten", "account.muted": "Stummgeschaltet", + "account.never_active": "Never", "account.posts": "Beiträge", "account.posts_with_replies": "Beiträge und Antworten", "account.profile": "Profil", "account.register": "Registrieren", - "account.remote_follow": "Remote follow", + "account.remote_follow": "Von anderer Instanz folgen", "account.report": "@{name} melden", "account.requested": "Warte auf Bestätigung. Klicke zum Abbrechen", "account.requested_small": "Warte auf Bestätigung", "account.share": "Profil von @{name} teilen", "account.show_reblogs": "Von @{name} geteilte Beiträge anzeigen", - "account.subscribe": "Subscribe to notifications from @{name}", - "account.subscribed": "Subscribed", + "account.subscribe": "Benachrichtigungen von @{name} abonnieren", + "account.subscribed": "Abonniert", "account.unblock": "@{name} entblocken", "account.unblock_domain": "{domain} wieder anzeigen", "account.unendorse": "Nicht auf Profil hervorheben", "account.unfollow": "Entfolgen", "account.unmute": "@{name} nicht mehr stummschalten", - "account.unsubscribe": "Unsubscribe to notifications from @{name}", + "account.unsubscribe": "Benachrichtigungen von @{name} entabonnieren", "account_gallery.none": "Keine Medien vorhanden.", - "account_search.placeholder": "Search for an account", - "account_timeline.column_settings.show_pinned": "Show pinned posts", - "admin.awaiting_approval.approved_message": "{acct} was approved!", - "admin.awaiting_approval.empty_message": "There is nobody waiting for approval. When a new user signs up, you can review them here.", - "admin.awaiting_approval.rejected_message": "{acct} was rejected.", - "admin.dashboard.registration_mode.approval_hint": "Users can sign up, but their account only gets activated when an admin approves it.", - "admin.dashboard.registration_mode.approval_label": "Approval Required", + "account_search.placeholder": "Nach einem Account suchen", + "account_timeline.column_settings.show_pinned": "Angeheftete Beiträge anzeigen", + "admin.awaiting_approval.approved_message": "{acct} bestätigt.", + "admin.awaiting_approval.empty_message": "Keine neuen Nutzer zur Prüfung und Bestätigung vorhanden. Wenn sich ein neuer Nutzer anmeldet, kann er hier überprüft werden.", + "admin.awaiting_approval.rejected_message": "{acct} abgelehnt.", + "admin.dashboard.registration_mode.approval_hint": "Neue Nutzer können sich anmelden, müssen aber erst vom Adminstrator geprüft und aktiviert werden.", + "admin.dashboard.registration_mode.approval_label": "Bestätigung erforderlich", "admin.dashboard.registration_mode.closed_hint": "Neuanmeldungen sind zurzeit ausgesetzt. Einladungen sind weiterhin möglich.", "admin.dashboard.registration_mode.closed_label": "Geschlossen", - "admin.dashboard.registration_mode.open_hint": "Anyone can join.", + "admin.dashboard.registration_mode.open_hint": "Anmeldung offen für alle", "admin.dashboard.registration_mode.open_label": "Offen", "admin.dashboard.registration_mode_label": "Anmeldung", "admin.dashboard.settings_saved": "Einstellungen gespeichert!", "admin.dashcounters.domain_count_label": "peers", - "admin.dashcounters.mau_label": "monthly active users", + "admin.dashcounters.mau_label": "Monatlich aktive User", "admin.dashcounters.retention_label": "user retention", "admin.dashcounters.status_count_label": "Beiträge", "admin.dashcounters.user_count_label": "Nutzer", - "admin.dashwidgets.email_list_header": "Email list", + "admin.dashwidgets.email_list_header": "Emailliste", "admin.dashwidgets.software_header": "Software", - "admin.latest_accounts_panel.expand_message": "Click to see {count} more {count, plural, one {account} other {accounts}}", - "admin.latest_accounts_panel.title": "Latest Accounts", - "admin.moderation_log.empty_message": "You have not performed any moderation actions yet. When you do, a history will be shown here.", - "admin.reports.actions.close": "Schliessen", + "admin.latest_accounts_panel.expand_message": "{count} Weitere {count, plural, Einen {account} weiteren {accounts}} anzeigen", + "admin.latest_accounts_panel.title": "Neueste Accounts", + "admin.moderation_log.empty_message": "Bisher wurden keine Moderationstätigkeiten durchgeführt. Durchgeführte Modarationstätigkeiten werden hier angezeigt.", + "admin.reports.actions.close": "Schließen", "admin.reports.actions.view_status": "Beitrag ansehen", "admin.reports.empty_message": "Keine aktuellen Beschwerden. Wenn eine Beschwerde über einen Nutzer vorliegt, wird sie hier angezeigt.", "admin.reports.report_closed_message": "Beschwerde über @{name} geschlossen.", @@ -82,47 +85,62 @@ "admin.statuses.actions.mark_status_not_sensitive": "Markierung als heikel aufheben", "admin.statuses.actions.mark_status_sensitive": "Als heikel markieren", "admin.statuses.status_deleted_message": "Beitrag von @{acct} gelöscht", - "admin.statuses.status_marked_message_not_sensitive": "Post by @{acct} was marked not sensitive", - "admin.statuses.status_marked_message_sensitive": "Post by @{acct} was marked sensitive", - "admin.user_index.empty": "No users found.", - "admin.user_index.search_input_placeholder": "Who are you looking for?", + "admin.statuses.status_marked_message_not_sensitive": "Beitrag von @{acct} wurde als nicht heikel markiert.", + "admin.statuses.status_marked_message_sensitive": "Beitrag von @{acct} wurde als heikel markiert.", + "admin.user_index.empty": "Keine Nutzer gefunden.", + "admin.user_index.search_input_placeholder": "Nutzer suchen", "admin.users.actions.deactivate_user": "@{name} deaktivieren", "admin.users.actions.delete_user": "@{name} löschen", - "admin.users.actions.demote_to_moderator": "Demote @{name} to a moderator", - "admin.users.actions.demote_to_moderator_message": "@{acct} was demoted to a moderator", - "admin.users.actions.demote_to_user": "Demote @{name} to a regular user", - "admin.users.actions.demote_to_user_message": "@{acct} was demoted to a regular user", - "admin.users.actions.promote_to_admin": "Promote @{name} to an admin", - "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", - "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", - "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.demote_to_moderator": "@{name} zum Moderator herabstufen", + "admin.users.actions.demote_to_moderator_message": "@{acct} zum Moderator herabgestuft", + "admin.users.actions.demote_to_user": "@{name} zum einfachen Nutzer herabstufen", + "admin.users.actions.demote_to_user_message": "@{acct} zum einfachen Nutzer herabgestuft", + "admin.users.actions.promote_to_admin": "@{name} zum Adminstrator ernennen", + "admin.users.actions.promote_to_admin_message": "@{acct} ist nun Adminstrator.", + "admin.users.actions.promote_to_moderator": "@{name} zum Moderator ernennen", + "admin.users.actions.promote_to_moderator_message": "@{acct} ist nun Moderator", + "admin.users.actions.suggest_user": "@{name} vorschlagen", + "admin.users.actions.unsuggest_user": "Vorschlag von @{name} zurücknehmen", "admin.users.actions.unverify_user": "Verifizierung von @{name} aufheben", "admin.users.actions.verify_user": "Verifizierung von @{name} bestätigen", "admin.users.user_deactivated_message": "@{acct} wurde deaktiviert", "admin.users.user_deleted_message": "@{acct} wurde gelöscht", + "admin.users.user_suggested_message": "@{acct} vorgeschlagen", + "admin.users.user_unsuggested_message": "@{acct}: Vorschlag zurückgenommen", "admin.users.user_unverified_message": "Die Verifizierung von @{acct} wurde aufgehoben", "admin.users.user_verified_message": "@{acct} wurde verifiziert", "admin_nav.awaiting_approval": "Wartet auf Bestätigung", "admin_nav.dashboard": "Steuerung", "admin_nav.reports": "Beschwerden", - "alert.unexpected.clear_cookies": "clear cookies and browser data", - "alert.unexpected.help_text": "If the problem persists, please notify a site admin with a screenshot and information about your web browser. You may also {clear_cookies} (this will log you out).", + "alert.unexpected.clear_cookies": "Cookies und Browserdaten löschen", + "alert.unexpected.help_text": "Falls das Problem weiterhin besteht, benachrichtige einen Adminstrator mit einem Screenshot des Fehlers und dem verwendeten Browser. {clear_cookies} kann ebenfalls helfen. Dadurch wirst du automatisch abgemeldet.", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", - "alert.unexpected.return_home": "Return Home", - "alert.unexpected.title": "Hoppla!", - "aliases.account.add": "Create alias", - "aliases.account_label": "Old account:", - "aliases.aliases_list_delete": "Unlink alias", - "aliases.search": "Search your old account", - "aliases.success.add": "Account alias created successfully", - "aliases.success.remove": "Account alias removed successfully", - "auth.invalid_credentials": "Wrong username or password", - "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", + "alert.unexpected.return_home": "Zurück zur Startseite", + "alert.unexpected.title": "Hinweis:", + "aliases.account.add": "Alias erstellen", + "aliases.account_label": "Alter Account:", + "aliases.aliases_list_delete": "Link zum Alias entfernen", + "aliases.search": "Nach altem Account suchen", + "aliases.success.add": "Alias erfolgreich erstellt.", + "aliases.success.remove": "Alias erfolgreich entfernt", + "app_create.name_label": "Name der App", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Weitere App erstellen", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App erfolgreich erstellt", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "App erstellen", + "app_create.website_label": "Webseite", + "auth.invalid_credentials": "Falsches Passwort oder faslscher Nutzername", + "auth.logged_out": "Abgemeldet.", "backups.actions.create": "Backup erstellen", "backups.empty_message": "Kein Backup gefunden. {action}", "backups.empty_message.action": "Backup jetzt erstellen?", - "backups.pending": "Pending", + "backups.pending": "Anstehende Backups", "boost_modal.combo": "Drücke {combo}, um dieses Fenster zu überspringen", "bundle_column_error.body": "Etwas ist beim Laden schiefgelaufen.", "bundle_column_error.retry": "Erneut versuchen", @@ -130,105 +148,122 @@ "bundle_modal_error.close": "Schließen", "bundle_modal_error.message": "Etwas ist beim Laden schiefgelaufen.", "bundle_modal_error.retry": "Erneut versuchen", + "chat_box.actions.close": "Chat schließen", "chat_box.actions.send": "Senden", "chat_box.input.placeholder": "Nachricht senden…", - "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", + "chat_panels.main_window.empty": "Keine Chats vorhanden. Besuche ein Nutzerprofil, um einen Chat zu starten.", "chat_panels.main_window.title": "Chats", "chats.actions.delete": "Nachricht löschen", "chats.actions.more": "Mehr", "chats.actions.report": "Nutzer melden", + "chats.attachment": "Anhang", + "chats.attachment_image": "Bild", "chats.audio_toggle_off": "Benachrichtigungston aus", "chats.audio_toggle_on": "Benachrichtigungston an", "chats.dividers.today": "Heute", - "chats.search_placeholder": "Start a chat with…", + "chats.search_placeholder": "Chatten mit…", "column.admin.awaiting_approval": "Wartet auf Bestätigung", "column.admin.dashboard": "Steuerung", "column.admin.moderation_log": "Moderationsprotokoll", "column.admin.reports": "Beschwerden", "column.admin.reports.menu.moderation_log": "Moderationsprotokoll", - "column.aliases": "Account aliases", - "column.aliases.create_error": "Error creating alias", - "column.aliases.delete": "Delete", - "column.aliases.delete_error": "Error deleting alias", - "column.aliases.subheading_add_new": "Add New Alias", - "column.aliases.subheading_aliases": "Current aliases", + "column.admin.users": "Nutzer", + "column.aliases": "Account-Aliases", + "column.aliases.create_error": "Fehler beim Erstellen des Aliases", + "column.aliases.delete": "Löschen", + "column.aliases.delete_error": "Fehler beim Löschen des Aliases", + "column.aliases.subheading_add_new": "Neuen Alias hinzufügen", + "column.aliases.subheading_aliases": "Bestehende Aliases", + "column.app_create": "App erstellen", "column.backups": "Backups", "column.blocks": "Blockierte Profile", - "column.bookmarks": "Bookmarks", + "column.bookmarks": "Lesezeichen", "column.chats": "Chats", "column.community": "Lokale Zeitleiste", - "column.crypto_donate": "Donate Cryptocurrency", + "column.crypto_donate": "Mit Kryptowährungen spenden", + "column.developers": "Developers", "column.direct": "Direktnachrichten", + "column.directory": "Profile entdecken", "column.domain_blocks": "Versteckte Domains", "column.edit_profile": "Profil bearbeiten", - "column.export_data": "Export data", - "column.favourites": "Likes", - "column.federation_restrictions": "Federation Restrictions", + "column.export_data": "Daten exportieren", + "column.favourited_statuses": "Favorisierte Beiträge", + "column.favourites": "Favorisierungen", + "column.federation_restrictions": "Beschränkungen der Föderierung", "column.filters": "Stummgeschaltete Wörter", - "column.filters.add_new": "Add New Filter", - "column.filters.conversations": "Conversations", - "column.filters.create_error": "Error adding filter", - "column.filters.delete": "Delete", - "column.filters.delete_error": "Error deleting filter", - "column.filters.drop_header": "Drop instead of hide", - "column.filters.drop_hint": "Filtered posts will disappear irreversibly, even if filter is later removed", - "column.filters.expires": "Expire after", - "column.filters.expires_hint": "Expiration dates are not currently supported", + "column.filters.add_new": "Filter hinzufügen", + "column.filters.conversations": "Unterhaltungen", + "column.filters.create_error": "Fehler beim Hinzufügen des Filters", + "column.filters.delete": "Löschen", + "column.filters.delete_error": "Fehler beim Löschen des Filters", + "column.filters.drop_header": "Entfernen statt verstecken", + "column.filters.drop_hint": "Gefilterte Beiträge bleiben dauerhaft unsichtbar, auch wenn der Filter später entfernt wird.", + "column.filters.expires": "Gültig bis", + "column.filters.expires_hint": "Ablaufdaten werden zurzeit nicht unterstüzt.", "column.filters.home_timeline": "Home timeline", - "column.filters.keyword": "Keyword or phrase", - "column.filters.notifications": "Notifications", - "column.filters.public_timeline": "Public timeline", - "column.filters.subheading_add_new": "Add New Filter", - "column.filters.subheading_filters": "Current Filters", - "column.filters.whole_word_header": "Whole word", + "column.filters.keyword": "Stichwort oder Wortfolge", + "column.filters.notifications": "Benachrichtgungen", + "column.filters.public_timeline": "Öffentliche Zeitleiste", + "column.filters.subheading_add_new": "Filter hinzufügen", + "column.filters.subheading_filters": "Bestehnde Filter", + "column.filters.whole_word_header": "Ganzes Wort", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Folgeanfragen", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Gruppen", "column.home": "Startseite", - "column.import_data": "Import data", - "column.info": "Server information", + "column.import_data": "Daten importieren", + "column.info": "Serverinformation", "column.lists": "Listen", - "column.mfa": "Multi-Factor Authentication", - "column.mfa_cancel": "Cancel", - "column.mfa_confirm_button": "Confirm", - "column.mfa_disable_button": "Disable", - "column.mfa_setup": "Proceed to Setup", + "column.mentions": "Erwähnungen", + "column.mfa": "Multi-Faktor-Authentifizierung", + "column.mfa_cancel": "Abbrechen", + "column.mfa_confirm_button": "Bestätigen", + "column.mfa_disable_button": "Ausschalten", + "column.mfa_setup": "Weiter zu den Einstellungen", "column.mutes": "Stummgeschaltete Profile", "column.notifications": "Benachrichtigungen", + "column.pins": "Angeheftete Beiträge", "column.preferences": "Einstellungen", + "column.profile_directory": "Profilverzeichnis", "column.public": "Föderierte Zeitleiste", - "column.reblogs": "Reposts", + "column.reactions": "Reaktionen", + "column.reblogs": "Geteilte Beiträge", "column.remote": "Federated timeline", - "column.scheduled_statuses": "Scheduled Posts", - "column.search": "Search", - "column.security": "Security", + "column.scheduled_statuses": "Vorbereitete Beiträge", + "column.search": "Suche", + "column.security": "Sicherheitseinstellungen", "column.soapbox_config": "Soapbox Einstellungen", "column_back_button.label": "Zurück", + "column_forbidden.body": "Zugriff nicht erlaubt", + "column_forbidden.title": "Zugriffsbeschränkung", "column_header.hide_settings": "Einstellungen verbergen", "column_header.show_settings": "Einstellungen anzeigen", "community.column_settings.media_only": "Nur Medien", - "community.column_settings.title": "Local timeline settings", - "compose.character_counter.title": "Used {chars} out of {maxChars} characters", - "compose.invalid_schedule": "You must schedule a post at least 5 minutes out.", - "compose.submit_success": "Your post was sent", + "community.column_settings.title": "Einstellungen für die lokale Zeitleiste", + "compose.character_counter.title": "{chars} von {maxChars} Zeichen verwendet", + "compose.invalid_schedule": "Der gewählte Zeitpunkt für vorbereitete Beiträge muss mindesten 5 Minuten in der Zukunft liegen.", + "compose.submit_success": "Beitrag gesendet", "compose_form.direct_message_warning": "Dieser Beitrag wird nur für die erwähnten Nutzer sichtbar sein.", "compose_form.hashtag_warning": "Dieser Beitrag wird nicht durch Hashtags auffindbar sein, weil er ungelistet ist. Nur öffentliche Beiträge tauchen in Hashtag-Zeitleisten auf.", "compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Wer dir folgen will, kann das jederzeit tun und dann auch deine privaten Beiträge sehen.", "compose_form.lock_disclaimer.lock": "auf privat gestellt", - "compose_form.markdown.marked": "Post markdown enabled", - "compose_form.markdown.unmarked": "Post markdown disabled", - "compose_form.message": "Message", + "compose_form.markdown.marked": "Markdown für Beiträge eingeschaltet", + "compose_form.markdown.unmarked": "Markdown für Beiträge ausgeschaltet", + "compose_form.message": "Nachricht", "compose_form.placeholder": "Was gibt's Neues?", "compose_form.poll.add_option": "Eine Antwortmöglichkeit hinzufügen", "compose_form.poll.duration": "Umfragedauer", "compose_form.poll.option_placeholder": "Antwortmöglichkeit {number}", "compose_form.poll.remove_option": "Antwortmöglichkeit entfernen", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Mehrere Antworten erlauben", + "compose_form.poll.switch_to_single": "Nur eine Antwort erlauben", "compose_form.publish": "Senden", "compose_form.publish_loud": "{publish}", - "compose_form.schedule": "Schedule", - "compose_form.scheduled_statuses.click_here": "Click here", - "compose_form.scheduled_statuses.message": "You have scheduled posts. {click_here} to see them.", + "compose_form.schedule": "Beitrag bestätigen", + "compose_form.scheduled_statuses.click_here": "Hier klicken", + "compose_form.scheduled_statuses.message": "Anzeigen der vorbereiteten Beiträge", "compose_form.sensitive.hide": "Medien als heikel markieren", "compose_form.sensitive.marked": "Medien sind als heikel markiert", "compose_form.sensitive.unmarked": "Medien sind nicht als heikel markiert", @@ -238,19 +273,22 @@ "confirmation_modal.cancel": "Abbrechen", "confirmations.admin.deactivate_user.confirm": "@{name} deaktivieren", "confirmations.admin.deactivate_user.message": "Hiermit wird das Konto von @{acct} deaktiviert. Diese Entscheidung kann später zurückgenommen werden.", - "confirmations.admin.delete_local_user.checkbox": "I understand that I am about to delete a local user.", + "confirmations.admin.delete_local_user.checkbox": "Hiermit wird ein lokaler Nutzer unwiderruflich gelöscht.", "confirmations.admin.delete_status.confirm": "Beitrag löschen", "confirmations.admin.delete_status.message": "Hiermit wird ein Beitrag von @{acct} gelöscht. Der gelöschte Beitrag kann nicht wiederhergestellt werden..", "confirmations.admin.delete_user.confirm": "@{name} löschen", "confirmations.admin.delete_user.message": "Hiermit wird das Konto @{acct} unwiderruflich gelöscht. DAS KONTO KANN NICHT WIEDERHERGESTELLT WERDEN.", "confirmations.admin.mark_status_not_sensitive.confirm": "Markierung als heikel aufheben", - "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", - "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", + "confirmations.admin.mark_status_not_sensitive.message": "Hiermit wird der Beitrag von @{acct} als nicht heikel markiert.", + "confirmations.admin.mark_status_sensitive.confirm": "Beitrag als heikel markieren", "confirmations.admin.mark_status_sensitive.message": "Hiermit wird der Beitrag von @{acct} als heikel markiert.", + "confirmations.admin.reject_user.confirm": "@{name} ablehnen", + "confirmations.admin.reject_user.message": "Hiermit wird der Aufnahmeantrag von @{acct} abgelehnt. Diese Entscheidung kann nicht rückgängig gemacht werden.", "confirmations.block.block_and_report": "Blockieren und melden", "confirmations.block.confirm": "Blockieren", "confirmations.block.message": "Bist du dir sicher, dass du {name} blockieren möchtest?", "confirmations.delete.confirm": "Löschen", + "confirmations.delete.heading": "Beitrag löschen", "confirmations.delete.message": "Bist du dir sicher, dass du diesen Beitrag löschen möchtest?", "confirmations.delete_list.confirm": "Löschen", "confirmations.delete_list.message": "Bist du dir sicher, dass du diese Liste permanent löschen möchtest?", @@ -266,49 +304,57 @@ "confirmations.reply.message": "Wenn du jetzt antwortest, wird die gesamte Nachricht verworfen, die du gerade schreibst. Möchtest du wirklich fortfahren?", "confirmations.unfollow.confirm": "Entfolgen", "confirmations.unfollow.message": "Bist du dir sicher, dass du {name} entfolgen möchtest?", - "crypto_donate.explanation_box.message": "{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!", - "crypto_donate.explanation_box.title": "Sending cryptocurrency donations", - "crypto_donate_panel.actions.more": "Click to see {count} more {count, plural, one {wallet} other {wallets}}", - "crypto_donate_panel.heading": "Donate Cryptocurrency", - "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", - "datepicker.hint": "Scheduled to post at…", - "direct.search_placeholder": "Send a message to…", + "crypto_donate.explanation_box.message": "{siteTitle} akzeptiert Kryptowährungen. Du kannst an eine der angegebenen Adressen eine Spende senden. Danke für deine Unterstützung!", + "crypto_donate.explanation_box.title": "Spenden mit Kryptowährungen", + "crypto_donate_panel.actions.more": "{count} weitere {count, plural, one {Wallet} other {Wallets}} anzeigen", + "crypto_donate_panel.heading": "Kryptowährungen spenden", + "crypto_donate_panel.intro.message": "{siteTitle} akzeptiert Kryptowährungen, um dieses Angebot zu finanzieren. Danke für deine Unterstützung!", + "datepicker.hint": "Beitrag veröffentlichen am…", + "developers.navigation.app_create_label": "App erstellen", + "developers.navigation.intentional_error_label": "Trigger an error", + "direct.search_placeholder": "Nachricht senden an…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Spenden", - "donate_crypto": "Donate cryptocurrency", - "edit_federation.followers_only": "Hide posts except to followers", - "edit_federation.force_nsfw": "Force attachments to be marked sensitive", - "edit_federation.media_removal": "Strip media", + "donate_crypto": "Kryptowährungen spenden", + "edit_federation.followers_only": "Beitrag nur für Follower anzeigen", + "edit_federation.force_nsfw": "Markierung aller Anhänge als heikel erzwingen", + "edit_federation.media_removal": "Alle Medien entfernen", "edit_federation.reject": "Reject all activities", - "edit_federation.save": "Save", + "edit_federation.save": "Speichern", "edit_federation.success": "{host} federation was updated", - "edit_federation.unlisted": "Force posts unlisted", - "edit_profile.error": "Profile update failed", - "edit_profile.fields.accepts_email_list_label": "Subscribe to newsletter", + "edit_federation.unlisted": "Ungelistete Beiträge erzwingen", + "edit_profile.error": "Profil konnte nicht geändert werden", + "edit_profile.fields.accepts_email_list_label": "Newsletter abonnieren", "edit_profile.fields.avatar_label": "Profilbild", "edit_profile.fields.bio_label": "Kurzbeschreibung", - "edit_profile.fields.bio_placeholder": "Tell us about yourself.", + "edit_profile.fields.bio_placeholder": "Schreibe etwas über dich.", "edit_profile.fields.bot_label": "Dieses Konto wird für einen Bot genutzt", - "edit_profile.fields.display_name_label": "Display name", + "edit_profile.fields.discoverable_label": "Allow account discovery", + "edit_profile.fields.display_name_label": "Angezeigter Nutzername", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Profilbanner", - "edit_profile.fields.hide_network_label": "Hide network", + "edit_profile.fields.hide_network_label": "Follower und Nutzer, denen du folgst, nicht öffentlich anzeigen", "edit_profile.fields.locked_label": "Profil auf privat stellen", "edit_profile.fields.meta_fields.content_placeholder": "Content", "edit_profile.fields.meta_fields.label_placeholder": "Label", "edit_profile.fields.meta_fields_label": "Profile metadata", - "edit_profile.fields.stranger_notifications_label": "Block notifications from strangers", + "edit_profile.fields.stranger_notifications_label": "Benachrichtigungen von Fremden blockieren", "edit_profile.fields.verified_display_name": "Nach der Verifizierung kann der Nutzername nicht mehr geändert werden.", "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "Erlaubte Formate sind PNG, GIF oder JPG. Die Datei darf nicht größer als 2 MB sein. Das Bild wird automatisch auf 400x400px verkleinert.", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "Erlaubte Formate sind PNG, GIF oder JPG. Die Datei darf nicht größer als 2 MB sein. Das Bild wird automatisch auf 1500x500px verkleinert.", - "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", + "edit_profile.hints.hide_network": "Deine Follower und wem du folgst wird nicht in deinem Profil angezeit.", "edit_profile.hints.locked": "Follower müssen einzeln bestätigt werden.", "edit_profile.hints.meta_fields": "You can have up to {count, plural, one {# item} other {# items}} displayed as a table on your profile", - "edit_profile.hints.stranger_notifications": "Only show notifications from people you follow", + "edit_profile.hints.stranger_notifications": "Nur Benachrichtigungen von Nutzern anzeigen, denen du folgst.", "edit_profile.meta_fields.add": "Add new item", "edit_profile.save": "Speichern", - "edit_profile.success": "Profile saved!", + "edit_profile.success": "Profil gespeichert", "embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.", "embed.preview": "Vorschau:", "emoji_button.activity": "Aktivitäten", @@ -325,23 +371,23 @@ "emoji_button.search_results": "Suchergebnisse", "emoji_button.symbols": "Symbole", "emoji_button.travel": "Reisen und Orte", - "empty_column.account_blocked": "You are blocked by @{accountUsername}.", - "empty_column.account_favourited_statuses": "This user doesn't have any liked posts yet.", + "empty_column.account_blocked": "@{accountUsername} hat dich geblockt.", + "empty_column.account_favourited_statuses": "Dieser Nutzer hat noch keine Beiträge favorisiert.", "empty_column.account_timeline": "Keine Beiträge!", "empty_column.account_unavailable": "Konto nicht verfügbar", - "empty_column.aliases": "You haven't created any account alias yet.", + "empty_column.aliases": "Bisher wurde noch kein Alias angelegt", "empty_column.aliases.suggestions": "There are no account suggestions available for the provided term.", "empty_column.blocks": "Du hast keine Profile blockiert.", - "empty_column.bookmarks": "You don't have any bookmarks yet. When you add one, it will show up here.", - "empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe einen öffentlichen Beitrag, um den Ball ins Rollen zu bringen!", + "empty_column.bookmarks": "Es wurden noch keine Lesezeichen angelegt. Erstellte Lesezeichen erscheinen hier.", + "empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe selbst den ersten Beitrag!", "empty_column.direct": "Du hast noch keine Direktnachrichten erhalten. Wenn du eine sendest oder empfängst, wird sie hier zu sehen sein.", "empty_column.domain_blocks": "Bisher wurden noch keine Domains blockiert.", - "empty_column.favourited_statuses": "Du hast noch keine favorisierten Beiträge. Wenn du einen favorisierst, wird er hier erscheinen.", + "empty_column.favourited_statuses": "Du hast noch keine Beiträge favorisiert. Favorisierte Beiträge erscheinen hier.", "empty_column.favourites": "Diesen Beitrag hat noch niemand favorisiert. Sobald es jemand tut, wird das hier angezeigt.", "empty_column.filters": "Du hast keine Wörter stummgeschaltet.", "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.", - "empty_column.follow_requests": "Du hast noch keine Folge-Anfragen. Sobald du eine erhältst, wird sie hier angezeigt.", - "empty_column.group": "Diese Gruppe hat noch keine Beiträge. Sobald ein Gruppenmitglied einen Beitrag erstellt, wird er hier angezeigt werden.", + "empty_column.follow_requests": "Du hast noch keine Folgeanfragen. Sobald du eine erhältst, wird sie hier angezeigt.", + "empty_column.group": "Diese Gruppe hat noch keine Beiträge. Sobald ein Gruppenmitglied einen Beitrag erstellt, wird er hier angezeigt.", "empty_column.hashtag": "Unter diesem Hashtag gibt es noch nichts.", "empty_column.home": "Deine Startseite ist leer! Besuche {public} oder nutze die Suche, um andere Nutzer zu finden.", "empty_column.home.local_tab": "den Reiter {site_title}", @@ -351,27 +397,27 @@ "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um ins Gespräch zu kommen.", "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Servern, um die Zeitleiste aufzufüllen", "empty_column.remote": "There is nothing here! Manually follow users from {instance} to fill it up.", - "empty_column.scheduled_statuses": "You don't have any scheduled statuses yet. When you add one, it will show up here.", + "empty_column.scheduled_statuses": "Bisher wurden keine vorbereiteten Beiträge erstellt. Vorbereitete Beiträge werden hier angezeigt.", "empty_column.search.accounts": "There are no people results for \"{term}\"", "empty_column.search.hashtags": "There are no hashtags results for \"{term}\"", "empty_column.search.statuses": "There are no posts results for \"{term}\"", - "export_data.actions.export": "Export", - "export_data.actions.export_blocks": "Export blocks", - "export_data.actions.export_follows": "Export follows", - "export_data.actions.export_mutes": "Export mutes", - "export_data.blocks_label": "Blocks", - "export_data.follows_label": "Follows", - "export_data.hints.blocks": "Get a CSV file containing a list of blocked accounts", - "export_data.hints.follows": "Get a CSV file containing a list of followed accounts", - "export_data.hints.mutes": "Get a CSV file containing a list of muted accounts", - "export_data.mutes_label": "Mutes", - "export_data.success.blocks": "Blocks exported successfully", - "export_data.success.followers": "Followers exported successfully", - "export_data.success.mutes": "Mutes exported successfully", + "export_data.actions.export": "Exportieren", + "export_data.actions.export_blocks": "Liste geblockter Nutzer expotieren", + "export_data.actions.export_follows": "Liste der Nutzer, denen du folgst, exportieren", + "export_data.actions.export_mutes": "Liste stummgeschlateter Nutzer expotieren", + "export_data.blocks_label": "Geblockte Nutzer", + "export_data.follows_label": "Nutzer, denen du folgst", + "export_data.hints.blocks": "CSV-Datei mit geblockten Nutzern erstellen", + "export_data.hints.follows": "CSV-Datei mit Nutzern, denen du folgst, erstellen", + "export_data.hints.mutes": "CSV-Datei mit stummgeschalteten Nutzern erstellen", + "export_data.mutes_label": "Stummgeschaltete Nutzer", + "export_data.success.blocks": "Blockliste erfolgreich exportiert", + "export_data.success.followers": "Liste der Nutzer, denen du folgst, erfolgreich exportiert", + "export_data.success.mutes": "Liste stummgeschalteter Nutzer erfolgreich exportiert", "federation_restriction.federated_timeline_removal": "Fediverse timeline removal", - "federation_restriction.followers_only": "Hidden except to followers", - "federation_restriction.full_media_removal": "Full media removal", - "federation_restriction.media_nsfw": "Attachments marked NSFW", + "federation_restriction.followers_only": "Nur für Follower sichtbar", + "federation_restriction.full_media_removal": "Alle Medien entfernen", + "federation_restriction.media_nsfw": "Anhänge als NSFW markiert", "federation_restriction.partial_media_removal": "Partial media removal", "federation_restrictions.empty_message": "{siteTitle} has not restricted any instances.", "federation_restrictions.explanation_box.message": "Normally servers on the Fediverse can communicate freely. {siteTitle} has imposed restrictions on the following servers.", @@ -380,23 +426,25 @@ "fediverse_tab.explanation_box.dismiss": "Don't show again", "fediverse_tab.explanation_box.explanation": "{site_title} ist Teil des Fediverse, einem Sozialen Netzwerk, das aus tausenden unabhängigen Instanzen (aka \"Servern\") besteht. Die Beiträge, die du hier siehst, stammen überwiegend von anderen Servern. Du kannst auf alle Einträge reagieren oder jeden Server blockieren, der dir nicht gefällt. Die Bezeichnung hinter dem zweiten @-Symbol ist der Name des entsprechenden Servers. Um nur Beiträge von {site_title} zu sehen, wähle {local} aus.", "fediverse_tab.explanation_box.title": "Was ist das Fediverse?", - "filters.added": "Filter added.", + "filters.added": "Filter hinzugefügt.", "filters.context_header": "Filter contexts", "filters.context_hint": "One or multiple contexts where the filter should apply", "filters.filters_list_context_label": "Filter contexts:", - "filters.filters_list_delete": "Delete", + "filters.filters_list_delete": "Löschen", "filters.filters_list_details_label": "Filter settings:", "filters.filters_list_drop": "Drop", "filters.filters_list_hide": "Hide", - "filters.filters_list_phrase_label": "Keyword or phrase:", + "filters.filters_list_phrase_label": "Stichwort oder Wortfolge:", "filters.filters_list_whole-word": "Whole word", - "filters.removed": "Filter deleted.", + "filters.removed": "Filter gelöscht.", "follow_recommendations.done": "Done", - "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.", + "follow_recommendations.heading": "Folge Nutzern, deren Beiträge du sehen möchtest. Hier sind einige Vorschläge:", "follow_recommendations.lead": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!", "follow_request.authorize": "Bestätigen", "follow_request.reject": "Ablehnen", - "forms.copy": "Copy", + "forms.copy": "Kopieren", + "forms.hide_password": "Passwort nicht anzeigen", + "forms.show_password": "Passwort anzeigen", "getting_started.open_source_notice": "{code_name} ist quelloffene Software. Du kannst auf GitLab unter {code_link} (v{code_version}) mitarbeiten oder Probleme melden.", "group.detail.archived_group": "Archived group", "group.members.empty": "Diese Gruppe hat noch keine Mitglieder.", @@ -407,67 +455,67 @@ "groups.card.roles.member": "Mitglied dieser Gruppe", "groups.card.view": "Ansehen", "groups.create": "Gruppe erstellen", - "groups.detail.role_admin": "You're an admin", - "groups.edit": "Edit", + "groups.detail.role_admin": "Du bist ein Administrator", + "groups.edit": "Bearbeiten", "groups.form.coverImage": "Neues Titelbild hochladen (optional)", - "groups.form.coverImageChange": "Banner image selected", + "groups.form.coverImageChange": "Titelbild ausgewählt", "groups.form.create": "Gruppe erstellen", "groups.form.description": "Gruppenbeschreibung", - "groups.form.title": "Title", + "groups.form.title": "Gruppentitel", "groups.form.update": "Update group", - "groups.join": "Join group", - "groups.leave": "Leave group", - "groups.removed_accounts": "Removed Accounts", + "groups.join": "Gruppe beitreten", + "groups.leave": "Gruppe verlassen", + "groups.removed_accounts": "Entfernte Accounts", "groups.sidebar-panel.item.no_recent_activity": "No recent activity", - "groups.sidebar-panel.item.view": "new posts", - "groups.sidebar-panel.show_all": "Show all", - "groups.sidebar-panel.title": "Groups You're In", + "groups.sidebar-panel.item.view": "Neue Beiträge", + "groups.sidebar-panel.show_all": "Alle anzeigen", + "groups.sidebar-panel.title": "Gruppenmitgliedschaften", "groups.tab_admin": "Manage", "groups.tab_featured": "Featured", "groups.tab_member": "Mitglied", "hashtag.column_header.tag_mode.all": "und {additional}", "hashtag.column_header.tag_mode.any": "oder {additional}", "hashtag.column_header.tag_mode.none": "ohne {additional}", - "header.about.label": "About", - "header.back_to.label": "Back to {siteTitle}", + "header.about.label": "Über", + "header.back_to.label": "Zurück zu {siteTitle}", "header.home.label": "Home", - "header.login.label": "Log in", - "home.column_settings.show_direct": "Show direct messages", + "header.login.label": "Anmelden", + "home.column_settings.show_direct": "Direktnachricht anzeigen", "home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen", "home.column_settings.show_replies": "Antworten anzeigen", "home.column_settings.title": "Home settings", "home_column.lists": "Listen", - "home_column_header.all": "All", + "home_column_header.all": "Alle", "home_column_header.fediverse": "Fediverse", - "home_column_header.home": "Startseite", + "home_column_header.home": "Start", "icon_button.icons": "Icons", - "icon_button.label": "Select icon", - "icon_button.not_found": "No icons!! (╯°□°)╯︵ ┻━┻", - "import_data.actions.import": "Import", - "import_data.actions.import_blocks": "Import blocks", - "import_data.actions.import_follows": "Import follows", - "import_data.actions.import_mutes": "Import mutes", - "import_data.blocks_label": "Blocks", - "import_data.follows_label": "Follows", - "import_data.hints.blocks": "CSV file containing a list of blocked accounts", - "import_data.hints.follows": "CSV file containing a list of followed accounts", - "import_data.hints.mutes": "CSV file containing a list of muted accounts", - "import_data.mutes_label": "Mutes", - "import_data.success.blocks": "Blocks imported successfully", + "icon_button.label": "Icons auswählen", + "icon_button.not_found": "Keine Icons!! (╯°□°)╯︵ ┻━┻", + "import_data.actions.import": "Importieren", + "import_data.actions.import_blocks": "Blockliste importieren", + "import_data.actions.import_follows": "Nutzer, denen du folgst, importieren", + "import_data.actions.import_mutes": "Liste mit stummgeschalteten Nutzern importieren", + "import_data.blocks_label": "Geblockt", + "import_data.follows_label": "Nutzer, denen du folgst", + "import_data.hints.blocks": "CSV-Datei mit geblockten Nutzern", + "import_data.hints.follows": "CSV-Datei mit Nutzer, denen du folgst", + "import_data.hints.mutes": "CSV-Datei mit stummgeschalteten Nutzern", + "import_data.mutes_label": "Stummgeschaltet", + "import_data.success.blocks": "Blockliste erfolgreich importiert", "import_data.success.followers": "Followers imported successfully", - "import_data.success.mutes": "Mutes imported successfully", + "import_data.success.mutes": "Liste mit stummgeschalteten Nutzern erfolgreich importiert", "intervals.full.days": "{number, plural, one {# Tag} other {# Tage}}", "intervals.full.hours": "{number, plural, one {# Stunde} other {# Stunden}}", "intervals.full.minutes": "{number, plural, one {# Minute} other {# Minuten}}", - "introduction.federation.action": "Next", + "introduction.federation.action": "Weiter", "introduction.federation.home.headline": "Home", "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", "introduction.interactions.action": "Finish tutorial!", "introduction.interactions.favourite.headline": "Favorite", "introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.", - "introduction.interactions.reblog.headline": "Repost", + "introduction.interactions.reblog.headline": "Teilen", "introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.", - "introduction.interactions.reply.headline": "Reply", + "introduction.interactions.reply.headline": "Antworten", "introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.", "introduction.welcome.action": "Let's go!", "introduction.welcome.headline": "First steps", @@ -493,7 +541,7 @@ "keyboard_shortcuts.profile": "Profil des Autors öffnen", "keyboard_shortcuts.react": "to react", "keyboard_shortcuts.reply": "antworten", - "keyboard_shortcuts.requests": "Liste der Folge-Anfragen öffnen", + "keyboard_shortcuts.requests": "Liste der Folgeanfragen öffnen", "keyboard_shortcuts.search": "Suche fokussieren", "keyboard_shortcuts.toggle_hidden": "Text hinter einer Inhaltswarnung verstecken/anzeigen", "keyboard_shortcuts.toggle_sensitivity": "Medien hinter einer Inhaltswarnung verstecken/anzeigen", @@ -505,6 +553,8 @@ "lightbox.previous": "Zurück", "lightbox.view_context": "Beitrag sehen", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Nutzer hinzufügen oder entfernen", "lists.account.add": "Zur Liste hinzufügen", "lists.account.remove": "Von der Liste entfernen", @@ -543,56 +593,61 @@ "mfa.setup_otp_title": "OTP Disabled", "mfa.setup_recoverycodes": "Recovery codes", "mfa.setup_warning": "Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.", - "missing_description_modal.cancel": "Cancel", - "missing_description_modal.continue": "Post", + "missing_description_modal.cancel": "Abbrechen", + "missing_description_modal.continue": "Senden", "missing_description_modal.text": "You have not entered a description for all attachments. Continue anyway?", "missing_indicator.label": "Nicht gefunden", - "missing_indicator.sublabel": "Die Ressource konnte nicht gefunden werden", + "missing_indicator.sublabel": "Der Eintrag konnte nicht gefunden werden", "morefollows.followers_label": "…and {count} more {count, plural, one {follower} other {followers}} on remote sites.", "morefollows.following_label": "…and {count} more {count, plural, one {follow} other {follows}} on remote sites.", "mute_modal.hide_notifications": "Benachrichtigungen von diesem Account verbergen?", "navigation.chats": "Chats", - "navigation.dashboard": "Dashboard", - "navigation.direct_messages": "Messages", - "navigation.home": "Home", - "navigation.invites": "Invites", - "navigation.notifications": "Notifications", - "navigation.search": "Search", + "navigation.dashboard": "Steuerung", + "navigation.developers": "Developers", + "navigation.direct_messages": "Nachrichten", + "navigation.home": "Start", + "navigation.invites": "Einladungen", + "navigation.notifications": "Benachrichtigungen", + "navigation.search": "Suche", "navigation_bar.account_aliases": "Account aliases", "navigation_bar.admin_settings": "Admin settings", "navigation_bar.blocks": "Blockierte Profile", - "navigation_bar.bookmarks": "Bookmarks", + "navigation_bar.bookmarks": "Lesezeichen", "navigation_bar.compose": "Neuen Beitrag verfassen", - "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_direct": "Direktnachrichten", + "navigation_bar.compose_reply": "Auf Beitrag antworten", "navigation_bar.domain_blocks": "Versteckte Domains", - "navigation_bar.export_data": "Export data", + "navigation_bar.export_data": "Daten exportieren", "navigation_bar.favourites": "Favoriten", - "navigation_bar.filters": "Stummgeschaltene Wörter", + "navigation_bar.filters": "Stummgeschaltete Wörter", "navigation_bar.follow_requests": "Folgeanfragen", - "navigation_bar.import_data": "Import data", + "navigation_bar.import_data": "Daten importieren", + "navigation_bar.in_reply_to": "Antwort auf", "navigation_bar.info": "Über diesen Server", + "navigation_bar.invites": "Einladungen", "navigation_bar.keyboard_shortcuts": "Tastenkombinationen", - "navigation_bar.lists": "Lists", + "navigation_bar.lists": "Listen", "navigation_bar.logout": "Abmelden", - "navigation_bar.messages": "Messages", + "navigation_bar.messages": "Nachrichten", "navigation_bar.mutes": "Stummgeschaltete Profile", "navigation_bar.pins": "Angeheftete Beiträge", "navigation_bar.preferences": "Einstellungen", + "navigation_bar.profile_directory": "Profilverzeichnis", "navigation_bar.security": "Sicherheit", "navigation_bar.soapbox_config": "Soapbox config", - "notification.chat_mention": "{name} sent you a message", + "notification.chat_mention": "{name} hat dir eine Nachricht gesendet", "notification.favourite": "{name} hat deinen Beitrag favorisiert", "notification.follow": "{name} folgt dir", "notification.follow_request": "{name} möchte dir folgen", "notification.mention": "{name} hat dich erwähnt", - "notification.move": "{name} moved to {targetName}", + "notification.move": "{name} ist nach {targetName} umgezogen", "notification.pleroma:emoji_reaction": "{name} hat auf deinen Beitrag reagiert", "notification.poll": "Eine Umfrage, in der du abgestimmt hast, ist vorbei", "notification.reblog": "{name} hat deinen Beitrag geteilt", "notifications.clear": "Benachrichtigungen löschen", "notifications.clear_confirmation": "Bist du dir sicher, dass du alle Benachrichtigungen löschen möchtest?", "notifications.column_settings.alert": "Desktop-Benachrichtigungen", - "notifications.column_settings.emoji_react": "Emoji reacts:", + "notifications.column_settings.emoji_react": "Emoji-Reaktionen:", "notifications.column_settings.favourite": "Favorisierungen:", "notifications.column_settings.filter_bar.advanced": "Zeige alle Kategorien an", "notifications.column_settings.filter_bar.category": "Schnellfilterleiste", @@ -611,7 +666,7 @@ "notifications.column_settings.title": "Notification settings", "notifications.filter.all": "Alle", "notifications.filter.boosts": "Geteilte Beiträge", - "notifications.filter.emoji_reacts": "Emoji reacts", + "notifications.filter.emoji_reacts": "Emoji-Reaktionen", "notifications.filter.favourites": "Favorisierungen", "notifications.filter.follows": "Folgt", "notifications.filter.mentions": "Erwähnungen", @@ -620,21 +675,25 @@ "notifications.group": "{count} Benachrichtigungen", "notifications.queue_label": "{count, plural, one {Eine neue Benachrichtigung} other {# neue Benachrichtigungen}}. Hier klicken, um sie anzuzeigen.", "password_reset.confirmation": "Check your email for confirmation.", - "password_reset.fields.username_placeholder": "Email or username", - "password_reset.reset": "Reset password", + "password_reset.fields.username_placeholder": "Email oder Nutzername", + "password_reset.reset": "Passwort zurücksetzen", "pinned_statuses.none": "Keine angehefteten Beiträge.", "poll.closed": "Geschlossen", "poll.refresh": "Aktualisieren", "poll.total_votes": "{count, plural, one {# Stimme} other {# Stimmen}}", "poll.vote": "Abstimmen", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Eine Umfrage erstellen", "poll_button.remove_poll": "Umfrage entfernen", "preferences.fields.auto_play_gif_label": "Animierte GIFs automatisch abspielen", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Laden…", "regeneration_indicator.sublabel": "Deine Startseite wird gerade vorbereitet!", "register_invite.lead": "Complete the form below to create an account.", @@ -687,11 +747,13 @@ "registration.fields.username_hint": "Only letters, numbers, and underscores are allowed.", "registration.fields.username_placeholder": "Nutzername", "registration.lead": "Mit einem Konto auf {instance} kannst du Nutzern im gesamten Fediverse folgen.", - "registration.newsletter": "Subscribe to newsletter.", + "registration.newsletter": "Newsletter abonnieren.", + "registration.password_mismatch": "Die eingegebenen Passwörter stimmen nicht überein", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Registrieren", "registration.tos": "Nutzungsbedingungen", + "registration.username_unavailable": "Der gewählte Nutzername ist bereits vorhanden.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "jetzt", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Abbrechen", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "und {count, plural, one {einen weiteren Nutzer} other {# weitere Nutzer}}", + "reply_mentions.reply": "Antwort an {accounts}{more}", + "reply_mentions.reply_empty": "Antwort auf einen Beitrag", "report.block": "{target} blockieren.", "report.block_hint": "Soll dieses Konto zusammen mit der Meldung auch gleich blockiert werden?", "report.forward": "An {target} weiterleiten", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Suche", - "search_popout.search_format": "Fortgeschrittenes Suchformat", - "search_popout.tips.full_text": "Einfache Texteingabe gibt Beiträge, die du geschrieben, favorisiert und geteilt hast, zurück. Außerdem auch Beiträge, in denen du erwähnt wurdest, aber auch passende Nutzernamen, Anzeigenamen oder Hashtags.", - "search_popout.tips.hashtag": "Hashtag", - "search_popout.tips.status": "Beitrag", - "search_popout.tips.user": "Nutzer", "search_results.accounts": "Personen", "search_results.hashtags": "Hashtags", "search_results.statuses": "Beiträge", @@ -732,7 +808,7 @@ "security.codes.fail": "Failed to fetch backup codes", "security.confirm.fail": "Incorrect code or password. Try again.", "security.delete_account.fail": "Account deletion failed.", - "security.delete_account.success": "Account successfully deleted.", + "security.delete_account.success": "Das Konto wurde erfolgreich gelöscht.", "security.disable.fail": "Incorrect password. Try again.", "security.disable_mfa": "Disable", "security.fields.email.label": "Emailaddresse", @@ -740,7 +816,7 @@ "security.fields.old_password.label": "Bisheriges Passwort", "security.fields.password.label": "Passwort", "security.fields.password_confirmation.label": "Neues Passwort (wiederholen)", - "security.headers.delete": "Delete Account", + "security.headers.delete": "Konto löschen", "security.headers.tokens": "Sessions", "security.headers.update_email": "Email ändern", "security.headers.update_password": "Passwort ändern", @@ -750,7 +826,7 @@ "security.mfa_setup_hint": "Configure multi-factor authentication with OTP", "security.qr.fail": "Failed to fetch setup key", "security.submit": "Änderungen speichern", - "security.submit.delete": "Delete Account", + "security.submit.delete": "Konto löschen", "security.text.delete": "To delete your account, enter your password then click Delete Account. This is a permanent action that cannot be undone. Your account will be destroyed from this server, and a deletion request will be sent to other servers. It's not guaranteed that all servers will purge your account.", "security.tokens.revoke": "Widerrufen", "security.update_email.fail": "Änderung der Emailadresse fehlgeschlagen.", @@ -791,21 +867,21 @@ "soapbox_config.promo_panel.meta_fields.url_placeholder": "URL", "soapbox_config.raw_json_hint": "Edit the settings data directly. Changes made directly to the JSON file will override the form fields above. Click Save to apply your changes.", "soapbox_config.raw_json_label": "Advanced: Edit raw JSON data", - "soapbox_config.save": "Save", + "soapbox_config.save": "Speichern", "soapbox_config.saved": "Soapbox config saved!", "soapbox_config.verified_can_edit_name_label": "Allow verified users to edit their own display name.", "status.admin_account": "Öffne Moderationsoberfläche für @{name}", "status.admin_status": "Öffne Beitrag in der Moderationsoberfläche", - "status.block": "Blockiere @{name}", - "status.bookmark": "Bookmark", - "status.bookmarked": "Bookmark added.", - "status.cancel_reblog_private": "Nicht mehr teilen", + "status.block": "@{name} blockieren", + "status.bookmark": "Lesezeichen", + "status.bookmarked": "Lesezeichen angelegt.", + "status.cancel_reblog_private": "Teilen zurücknehmen", "status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden", - "status.chat": "Chat with @{name}", + "status.chat": "Chatte mit @{name}", "status.copy": "Kopiere Link zum Beitrag", "status.delete": "Löschen", - "status.detailed_status": "Detaillierte Ansicht der Konversation", - "status.direct": "Direktnachricht @{name}", + "status.detailed_status": "Detaillierte Ansicht der Unterhaltung", + "status.direct": "Direktnachricht an @{name}", "status.embed": "Einbetten", "status.favourite": "Favorisieren", "status.filtered": "Gefiltert", @@ -814,7 +890,7 @@ "status.mention": "@{name} erwähnen", "status.more": "Mehr", "status.mute": "@{name} stummschalten", - "status.mute_conversation": "Konversation stummschalten", + "status.mute_conversation": "Unterhaltung stummschalten", "status.open": "Diesen Beitrag öffnen", "status.pin": "Im Profil anheften", "status.pinned": "Angehefteter Beitrag", @@ -825,7 +901,7 @@ "status.reactions.like": "Like", "status.reactions.open_mouth": "Wow", "status.reactions.weary": "Weary", - "status.reactions_expand": "Select emoji", + "status.reactions_expand": "Emoji auswählen", "status.read_more": "Mehr lesen", "status.reblog": "Teilen", "status.reblog_private": "Mit der ursprünglichen Zielgruppe teilen", @@ -843,23 +919,23 @@ "status.show_less_all": "Alle Inhaltswarnungen zuklappen", "status.show_more": "Mehr anzeigen", "status.show_more_all": "Alle Inhaltswarnungen aufklappen", - "status.show_thread": "Zeige Konversation", - "status.title": "Post", - "status.title_direct": "Direct message", - "status.unbookmark": "Remove bookmark", - "status.unbookmarked": "Bookmark removed.", - "status.unmute_conversation": "Stummschaltung von Konversation aufheben", + "status.show_thread": "Gesamte Unterhaltung anzeigen", + "status.title": "Beiträge", + "status.title_direct": "Direktnachricht", + "status.unbookmark": "Lesezeichen entfernen", + "status.unbookmarked": "Lesezeichen entfernt.", + "status.unmute_conversation": "Stummschaltung der Unterhaltung aufheben", "status.unpin": "Vom Profil lösen", "status_list.queue_label": "{count, plural, one {Ein neuer Beitrag} other {# neue Beiträge}}. Hier klicken, um {count, plural, one {ihn} other {sie}} anzuzeigen.", - "statuses.tombstone": "One or more posts is unavailable.", + "statuses.tombstone": "Beitrag oder Beiträge können nicht angezeigt werden.", "suggestions.dismiss": "Empfehlung ausblenden", "tabs_bar.all": "All", "tabs_bar.apps": "Apps", "tabs_bar.chats": "Chats", - "tabs_bar.dashboard": "Dashboard", + "tabs_bar.dashboard": "Steuerung", "tabs_bar.fediverse": "Fediverse", - "tabs_bar.header": "Account Info", - "tabs_bar.home": "Startseite", + "tabs_bar.header": "Kontoinformtion", + "tabs_bar.home": "Start", "tabs_bar.news": "News", "tabs_bar.notifications": "Benachrichtigungen", "tabs_bar.post": "Neuer Beitrag", @@ -882,7 +958,7 @@ "upload_error.limit": "Dateiupload-Limit erreicht.", "upload_error.poll": "Dateiuploads sind in Kombination mit Umfragen nicht erlaubt.", "upload_form.description": "Für Menschen mit Sehbehinderung beschreiben", - "upload_form.preview": "Preview", + "upload_form.preview": "Vorschau", "upload_form.undo": "Löschen", "upload_progress.label": "Wird hochgeladen …", "video.close": "Video schließen", @@ -895,5 +971,6 @@ "video.pause": "Pausieren", "video.play": "Abspielen", "video.unmute": "Ton einschalten", - "who_to_follow.title": "Who To Follow" + "who_to_follow.title": "Vorschläge" } + diff --git a/app/soapbox/locales/defaultMessages.json b/app/soapbox/locales/defaultMessages.json index eeeb1e138..5a0b58946 100644 --- a/app/soapbox/locales/defaultMessages.json +++ b/app/soapbox/locales/defaultMessages.json @@ -1,4 +1,17 @@ [ + { + "descriptors": [ + { + "defaultMessage": "You are about to reject @{acct} registration request. This action cannot be undone.", + "id": "confirmations.admin.reject_user.message" + }, + { + "defaultMessage": "Reject @{name}", + "id": "confirmations.admin.reject_user.confirm" + } + ], + "path": "app/soapbox/actions/admin.json" + }, { "descriptors": [ { @@ -157,6 +170,14 @@ "defaultMessage": "Delete post", "id": "confirmations.admin.delete_status.confirm" }, + { + "defaultMessage": "You are about to reject @{acct} registration request. This action cannot be undone.", + "id": "confirmations.admin.reject_user.message" + }, + { + "defaultMessage": "Reject @{name}", + "id": "confirmations.admin.reject_user.confirm" + }, { "defaultMessage": "Post by @{acct} was deleted", "id": "admin.statuses.status_deleted_message" @@ -228,15 +249,6 @@ ], "path": "app/soapbox/components/account.json" }, - { - "descriptors": [ - { - "defaultMessage": "Search for an account", - "id": "autosuggest_account_input.default_placeholder" - } - ], - "path": "app/soapbox/components/autosuggest_account_input.json" - }, { "descriptors": [ { @@ -399,6 +411,10 @@ "defaultMessage": "Delete", "id": "confirmations.delete.confirm" }, + { + "defaultMessage": "Delete post", + "id": "confirmations.delete.heading" + }, { "defaultMessage": "Are you sure you want to delete this post?", "id": "confirmations.delete.message" @@ -419,21 +435,20 @@ ], "path": "app/soapbox/components/more_follows.json" }, - { - "descriptors": [ - { - "defaultMessage": "Loading...", - "id": "loading_indicator.label" - } - ], - "path": "app/soapbox/components/placeholder/placeholder_layout.json" - }, { "descriptors": [ { "defaultMessage": "Closed", "id": "poll.closed" }, + { + "defaultMessage": "You voted for this answer", + "id": "poll.voted" + }, + { + "defaultMessage": "{votes, plural, one {# vote} other {# votes}}", + "id": "poll.votes" + }, { "defaultMessage": "Vote", "id": "poll.vote" @@ -455,6 +470,10 @@ "defaultMessage": "Home", "id": "tabs_bar.home" }, + { + "defaultMessage": "Search", + "id": "navigation.search" + }, { "defaultMessage": "Notifications", "id": "tabs_bar.notifications" @@ -467,10 +486,6 @@ "defaultMessage": "Messages", "id": "navigation.direct_messages" }, - { - "defaultMessage": "Search", - "id": "navigation.search" - }, { "defaultMessage": "Dashboard", "id": "tabs_bar.dashboard" @@ -479,6 +494,10 @@ "defaultMessage": "Invites", "id": "navigation.invites" }, + { + "defaultMessage": "Developers", + "id": "navigation.developers" + }, { "defaultMessage": "All", "id": "tabs_bar.all" @@ -544,6 +563,19 @@ ], "path": "app/soapbox/components/relative_timestamp.json" }, + { + "descriptors": [ + { + "defaultMessage": "Show password", + "id": "forms.show_password" + }, + { + "defaultMessage": "Hide password", + "id": "forms.hide_password" + } + ], + "path": "app/soapbox/components/showable_password.json" + }, { "descriptors": [ { @@ -558,6 +590,10 @@ "defaultMessage": "Profile", "id": "account.profile" }, + { + "defaultMessage": "Invites", + "id": "navigation_bar.invites" + }, { "defaultMessage": "Preferences", "id": "navigation_bar.preferences" @@ -614,6 +650,10 @@ "defaultMessage": "Bookmarks", "id": "column.bookmarks" }, + { + "defaultMessage": "Profile directory", + "id": "column.profile_directory" + }, { "defaultMessage": "Account Info", "id": "tabs_bar.header" @@ -638,6 +678,10 @@ "defaultMessage": "Server information", "id": "column.info" }, + { + "defaultMessage": "Developers", + "id": "navigation.developers" + }, { "defaultMessage": "Add an existing account", "id": "profile_dropdown.add_account" @@ -856,6 +900,23 @@ ], "path": "app/soapbox/components/status_list.json" }, + { + "descriptors": [ + { + "defaultMessage": "Replying to {accounts}{more}", + "id": "reply_mentions.reply" + }, + { + "defaultMessage": "Replying to post", + "id": "reply_mentions.reply_empty" + }, + { + "defaultMessage": "and {count} more", + "id": "reply_mentions.more" + } + ], + "path": "app/soapbox/components/status_reply_mentions.json" + }, { "descriptors": [ { @@ -869,10 +930,6 @@ { "defaultMessage": "{name} reposted", "id": "status.reblogged_by" - }, - { - "defaultMessage": "Show thread", - "id": "status.show_thread" } ], "path": "app/soapbox/components/status.json" @@ -896,6 +953,10 @@ "defaultMessage": "Home", "id": "navigation.home" }, + { + "defaultMessage": "Search", + "id": "navigation.search" + }, { "defaultMessage": "Notifications", "id": "navigation.notifications" @@ -908,10 +969,6 @@ "defaultMessage": "Messages", "id": "navigation.direct_messages" }, - { - "defaultMessage": "Search", - "id": "navigation.search" - }, { "defaultMessage": "Dashboard", "id": "navigation.dashboard" @@ -1027,9 +1084,13 @@ "id": "lightbox.close" }, { - "defaultMessage": "Acccount timeline settings", + "defaultMessage": "Account timeline settings", "id": "account.column_settings.title" }, + { + "defaultMessage": "These settings apply to all account timelines.", + "id": "account.column_settings.description" + }, { "defaultMessage": "Show pinned posts", "id": "account_timeline.column_settings.show_pinned" @@ -1092,6 +1153,14 @@ "defaultMessage": "@{acct} was demoted to a regular user", "id": "admin.users.actions.demote_to_user_message" }, + { + "defaultMessage": "@{acct} was suggested", + "id": "admin.users.user_suggested_message" + }, + { + "defaultMessage": "@{acct} was unsuggested", + "id": "admin.users.user_unsuggested_message" + }, { "defaultMessage": "Are you sure you want to unfollow {name}?", "id": "confirmations.unfollow.message" @@ -1101,7 +1170,7 @@ "id": "confirmations.block.message" }, { - "defaultMessage": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "defaultMessage": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "id": "confirmations.domain_block.message" } ], @@ -1282,6 +1351,14 @@ "defaultMessage": "Unsubscribe to notifications from @{name}", "id": "account.unsubscribe" }, + { + "defaultMessage": "Suggest @{name}", + "id": "admin.users.actions.suggest_user" + }, + { + "defaultMessage": "Unsuggest @{name}", + "id": "admin.users.actions.unsuggest_user" + }, { "defaultMessage": "Follows you", "id": "account.follows_you" @@ -1521,6 +1598,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Users", + "id": "column.admin.users" + }, { "defaultMessage": "No users found.", "id": "admin.user_index.empty" @@ -1742,6 +1823,14 @@ "defaultMessage": "Your account will be manually approved by an admin. Please be patient while we review your details.", "id": "confirmations.register.needs_approval" }, + { + "defaultMessage": "Username is already taken.", + "id": "registration.username_unavailable" + }, + { + "defaultMessage": "Passwords don't match.", + "id": "registration.password_mismatch" + }, { "defaultMessage": "Why do you want to join?", "id": "registration.reason" @@ -1834,6 +1923,15 @@ ], "path": "app/soapbox/features/chats/components/chat_box.json" }, + { + "descriptors": [ + { + "defaultMessage": "No chats found. To start a chat, visit a user's profile", + "id": "chat_panels.main_window.empty" + } + ], + "path": "app/soapbox/features/chats/components/chat_list.json" + }, { "descriptors": [ { @@ -1864,14 +1962,32 @@ { "defaultMessage": "Chats", "id": "chat_panels.main_window.title" - }, - { - "defaultMessage": "No chats found. To start a chat, visit a user's profile.", - "id": "chat_panels.main_window.empty" } ], "path": "app/soapbox/features/chats/components/chat_panes.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close chat", + "id": "chat_box.actions.close" + } + ], + "path": "app/soapbox/features/chats/components/chat_window.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Image", + "id": "chats.attachment_image" + }, + { + "defaultMessage": "Attachment", + "id": "chats.attachment" + } + ], + "path": "app/soapbox/features/chats/components/chat.json" + }, { "descriptors": [ { @@ -1881,10 +1997,6 @@ { "defaultMessage": "Start a chat with…", "id": "chats.search_placeholder" - }, - { - "defaultMessage": "No chats found. To start a chat, visit a user's profile.", - "id": "chat_panels.main_window.empty" } ], "path": "app/soapbox/features/chats/index.json" @@ -2099,6 +2211,19 @@ ], "path": "app/soapbox/features/compose/components/emoji_picker_dropdown.json" }, + { + "descriptors": [ + { + "defaultMessage": "Select list", + "id": "list.select" + }, + { + "defaultMessage": "Select list…", + "id": "list.label" + } + ], + "path": "app/soapbox/features/compose/components/list_dropdown.json" + }, { "descriptors": [ { @@ -2143,6 +2268,14 @@ "defaultMessage": "Poll duration", "id": "compose_form.poll.duration" }, + { + "defaultMessage": "Change poll to allow multiple choices", + "id": "compose_form.poll.switch_to_multiple" + }, + { + "defaultMessage": "Change poll to allow for a single choice", + "id": "compose_form.poll.switch_to_single" + }, { "defaultMessage": "{number, plural, one {# minute} other {# minutes}}", "id": "intervals.full.minutes" @@ -2154,10 +2287,6 @@ { "defaultMessage": "{number, plural, one {# day} other {# days}}", "id": "intervals.full.days" - }, - { - "defaultMessage": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", - "id": "compose_form.poll.type.hint" } ], "path": "app/soapbox/features/compose/components/poll_form.json" @@ -2212,6 +2341,19 @@ ], "path": "app/soapbox/features/compose/components/reply_indicator.json" }, + { + "descriptors": [ + { + "defaultMessage": "Replying to {accounts}{more}", + "id": "reply_mentions.reply" + }, + { + "defaultMessage": "and {count} more", + "id": "reply_mentions.more" + } + ], + "path": "app/soapbox/features/compose/components/reply_mentions.json" + }, { "descriptors": [ { @@ -2266,24 +2408,8 @@ "id": "search.placeholder" }, { - "defaultMessage": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "id": "search_popout.tips.full_text" - }, - { - "defaultMessage": "Advanced search format", - "id": "search_popout.search_format" - }, - { - "defaultMessage": "hashtag", - "id": "search_popout.tips.hashtag" - }, - { - "defaultMessage": "user", - "id": "search_popout.tips.user" - }, - { - "defaultMessage": "post", - "id": "search_popout.tips.status" + "defaultMessage": "Search for “{query}”", + "id": "search.action" } ], "path": "app/soapbox/features/compose/components/search.json" @@ -2460,6 +2586,80 @@ ], "path": "app/soapbox/features/crypto_donate/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Create app", + "id": "column.app_create" + }, + { + "defaultMessage": "e.g. 'Soapbox'", + "id": "app_create.name_placeholder" + }, + { + "defaultMessage": "e.g. 'read write follow'", + "id": "app_create.scopes_placeholder" + }, + { + "defaultMessage": "App created successfully", + "id": "app_create.results.explanation_title" + }, + { + "defaultMessage": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "id": "app_create.results.explanation_text" + }, + { + "defaultMessage": "App", + "id": "app_create.results.app_label" + }, + { + "defaultMessage": "OAuth token", + "id": "app_create.results.token_label" + }, + { + "defaultMessage": "Create another", + "id": "app_create.restart" + }, + { + "defaultMessage": "App name", + "id": "app_create.name_label" + }, + { + "defaultMessage": "Website", + "id": "app_create.website_label" + }, + { + "defaultMessage": "Redirect URIs", + "id": "app_create.redirect_uri_label" + }, + { + "defaultMessage": "Scopes", + "id": "app_create.scopes_label" + }, + { + "defaultMessage": "Create app", + "id": "app_create.submit" + } + ], + "path": "app/soapbox/features/developers/apps/create.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Developers", + "id": "column.developers" + }, + { + "defaultMessage": "Create an app", + "id": "developers.navigation.app_create_label" + }, + { + "defaultMessage": "Trigger an error", + "id": "developers.navigation.intentional_error_label" + } + ], + "path": "app/soapbox/features/developers/index.json" + }, { "descriptors": [ { @@ -2477,6 +2677,56 @@ ], "path": "app/soapbox/features/direct_timeline/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Follows you", + "id": "account.follows_you" + }, + { + "defaultMessage": "Toots", + "id": "account.posts" + }, + { + "defaultMessage": "Followers", + "id": "account.followers" + }, + { + "defaultMessage": "Never", + "id": "account.never_active" + }, + { + "defaultMessage": "Last active", + "id": "account.last_status" + } + ], + "path": "app/soapbox/features/directory/components/account_card.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Browse profiles", + "id": "column.directory" + }, + { + "defaultMessage": "Recently active", + "id": "directory.recently_active" + }, + { + "defaultMessage": "New arrivals", + "id": "directory.new_arrivals" + }, + { + "defaultMessage": "From {domain} only", + "id": "directory.local" + }, + { + "defaultMessage": "From known fediverse", + "id": "directory.federated" + } + ], + "path": "app/soapbox/features/directory/index.json" + }, { "descriptors": [ { @@ -2584,6 +2834,14 @@ "defaultMessage": "Only show notifications from people you follow", "id": "edit_profile.hints.stranger_notifications" }, + { + "defaultMessage": "Allow account discovery", + "id": "edit_profile.fields.discoverable_label" + }, + { + "defaultMessage": "Display account in profile directory and allow indexing by external services", + "id": "edit_profile.hints.discoverable" + }, { "defaultMessage": "Subscribe to newsletter", "id": "edit_profile.fields.accepts_email_list_label" @@ -2679,6 +2937,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Liked posts", + "id": "column.favourited_statuses" + }, { "defaultMessage": "Profile unavailable", "id": "empty_column.account_unavailable" @@ -2925,23 +3187,6 @@ ], "path": "app/soapbox/features/follow_recommendations/components/follow_recommendations_list.json" }, - { - "descriptors": [ - { - "defaultMessage": "Follow people you'd like to see posts from! Here are some suggestions.", - "id": "follow_recommendations.heading" - }, - { - "defaultMessage": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!", - "id": "follow_recommendations.lead" - }, - { - "defaultMessage": "Done", - "id": "follow_recommendations.done" - } - ], - "path": "app/soapbox/features/follow_recommendations/index.json" - }, { "descriptors": [ { @@ -2970,6 +3215,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Followers", + "id": "column.followers" + }, { "defaultMessage": "Profile unavailable", "id": "empty_column.account_unavailable" @@ -2983,6 +3232,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Following", + "id": "column.following" + }, { "defaultMessage": "Profile unavailable", "id": "empty_column.account_unavailable" @@ -3606,6 +3859,15 @@ ], "path": "app/soapbox/features/lists/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Mentions", + "id": "column.mentions" + } + ], + "path": "app/soapbox/features/mentions/index.json" + }, { "descriptors": [ { @@ -3828,6 +4090,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Pinned posts", + "id": "column.pins" + }, { "defaultMessage": "No pins to show.", "id": "pinned_statuses.none" @@ -3853,6 +4119,22 @@ "defaultMessage": "Always show media", "id": "preferences.fields.display_media.show_all" }, + { + "defaultMessage": "Home settings", + "id": "home.column_settings.title" + }, + { + "defaultMessage": "Show reposts", + "id": "home.column_settings.show_reblogs" + }, + { + "defaultMessage": "Show replies", + "id": "home.column_settings.show_replies" + }, + { + "defaultMessage": "Show direct messages", + "id": "home.column_settings.show_direct" + }, { "defaultMessage": "Language", "id": "preferences.fields.language_label" @@ -3937,6 +4219,10 @@ "defaultMessage": "Automatically load new posts when scrolled to the top of the page", "id": "preferences.fields.autoload_timelines_label" }, + { + "defaultMessage": "Automatically load more items when scrolled to the bottom of the page", + "id": "preferences.fields.autoload_more_label" + }, { "defaultMessage": "Always underline links in posts", "id": "preferences.fields.underline_links_label" @@ -3964,6 +4250,10 @@ { "defaultMessage": "Decrease social media anxiety by hiding all numbers from the site.", "id": "preferences.hints.demetricator" + }, + { + "defaultMessage": "Developer tools", + "id": "preferences.fields.developer_label" } ], "path": "app/soapbox/features/preferences/index.json" @@ -4049,6 +4339,14 @@ }, { "descriptors": [ + { + "defaultMessage": "Reactions", + "id": "column.reactions" + }, + { + "defaultMessage": "All", + "id": "reactions.all" + }, { "defaultMessage": "No one has reacted to this post yet. When someone does, they will show up here.", "id": "status.reactions.empty" @@ -4099,6 +4397,19 @@ ], "path": "app/soapbox/features/remote_timeline/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Remove from mentions", + "id": "reply_mentions.account.remove" + }, + { + "defaultMessage": "Add to mentions", + "id": "reply_mentions.account.add" + } + ], + "path": "app/soapbox/features/reply_mentions/account.json" + }, { "descriptors": [ { @@ -4380,6 +4691,35 @@ ], "path": "app/soapbox/features/server_info/index.json" }, + { + "descriptors": [ + { + "defaultMessage": "Account aliases", + "id": "column.aliases" + }, + { + "defaultMessage": "Add New Alias", + "id": "column.aliases.subheading_add_new" + }, + { + "defaultMessage": "Error creating alias", + "id": "column.aliases.create_error" + }, + { + "defaultMessage": "Error deleting alias", + "id": "column.aliases.delete_error" + }, + { + "defaultMessage": "Current aliases", + "id": "column.aliases.subheading_aliases" + }, + { + "defaultMessage": "Delete", + "id": "column.aliases.delete" + } + ], + "path": "app/soapbox/features/share/index.json" + }, { "descriptors": [ { @@ -4707,6 +5047,19 @@ ], "path": "app/soapbox/features/status/components/action_bar.json" }, + { + "descriptors": [ + { + "defaultMessage": "Replying to {accounts}{more}", + "id": "reply_mentions.reply" + }, + { + "defaultMessage": "and {count} more", + "id": "reply_mentions.more" + } + ], + "path": "app/soapbox/features/status/components/detailed_status.json" + }, { "descriptors": [ { @@ -4859,6 +5212,15 @@ ], "path": "app/soapbox/features/ui/components/action_button.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + } + ], + "path": "app/soapbox/features/ui/components/actions_modal.json" + }, { "descriptors": [ { @@ -4913,11 +5275,24 @@ { "descriptors": [ { - "defaultMessage": "Close", - "id": "lightbox.close" + "defaultMessage": "Forbidden", + "id": "column_forbidden.title" + }, + { + "defaultMessage": "You do not have permission to access this page.", + "id": "column_forbidden.body" } ], - "path": "app/soapbox/features/ui/components/component_modal.json" + "path": "app/soapbox/features/ui/components/column_forbidden.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Toot", + "id": "compose_form.publish" + } + ], + "path": "app/soapbox/features/ui/components/columns_area.json" }, { "descriptors": [ @@ -4937,6 +5312,10 @@ "defaultMessage": "Direct message", "id": "navigation_bar.compose_direct" }, + { + "defaultMessage": "Reply to post", + "id": "navigation_bar.compose_reply" + }, { "defaultMessage": "Compose new post", "id": "navigation_bar.compose" @@ -5003,6 +5382,23 @@ ], "path": "app/soapbox/features/ui/components/embed_modal.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "No one has liked this post yet. When someone does, they will show up here.", + "id": "empty_column.favourites" + }, + { + "defaultMessage": "likes", + "id": "column.favourites" + } + ], + "path": "app/soapbox/features/ui/components/favourites_modal.json" + }, { "descriptors": [ { @@ -5181,6 +5577,10 @@ }, { "descriptors": [ + { + "defaultMessage": "Profile directory", + "id": "navigation_bar.profile_directory" + }, { "defaultMessage": "Blocks", "id": "navigation_bar.blocks" @@ -5261,6 +5661,19 @@ ], "path": "app/soapbox/features/ui/components/media_modal.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "Mentions", + "id": "column.mentions" + } + ], + "path": "app/soapbox/features/ui/components/mentions_modal.json" + }, { "descriptors": [ { @@ -5376,6 +5789,155 @@ ], "path": "app/soapbox/features/ui/components/profile_stats.json" }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "All", + "id": "reactions.all" + }, + { + "defaultMessage": "No one has reacted to this post yet. When someone does, they will show up here.", + "id": "status.reactions.empty" + }, + { + "defaultMessage": "Reactions", + "id": "column.reactions" + } + ], + "path": "app/soapbox/features/ui/components/reactions_modal.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "No one has reposted this post yet. When someone does, they will show up here.", + "id": "status.reblogs.empty" + }, + { + "defaultMessage": "Reposts", + "id": "column.reblogs" + } + ], + "path": "app/soapbox/features/ui/components/reblogs_modal.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "Follow @{acct} from remote account", + "id": "unauthorized_modal.title" + }, + { + "defaultMessage": "Sign up", + "id": "account.register" + }, + { + "defaultMessage": "Log in", + "id": "account.login" + } + ], + "path": "app/soapbox/features/ui/components/remote_follow_modal.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "Enter your username@domain you want to act from", + "id": "remote_interaction.account_placeholder" + }, + { + "defaultMessage": "Couldn't find given user", + "id": "remote_interaction.user_not_found_error" + }, + { + "defaultMessage": "Follow {user} remotely", + "id": "remote_interaction.follow_title" + }, + { + "defaultMessage": "Proceed to follow", + "id": "remote_interaction.follow" + }, + { + "defaultMessage": "Reply to a post remotely", + "id": "remote_interaction.reply_title" + }, + { + "defaultMessage": "Proceed to reply", + "id": "remote_interaction.reply" + }, + { + "defaultMessage": "Reblog a post remotely", + "id": "remote_interaction.reblog_title" + }, + { + "defaultMessage": "Proceed to repost", + "id": "remote_interaction.reblog" + }, + { + "defaultMessage": "Like a post remotely", + "id": "remote_interaction.favourite_title" + }, + { + "defaultMessage": "Proceed to like", + "id": "remote_interaction.favourite" + }, + { + "defaultMessage": "Vote in a poll remotely", + "id": "remote_interaction.poll_vote_title" + }, + { + "defaultMessage": "Proceed to vote", + "id": "remote_interaction.poll_vote" + }, + { + "defaultMessage": "or", + "id": "remote_interaction.divider" + }, + { + "defaultMessage": "Sign up for {site_title}", + "id": "unauthorized_modal.title" + }, + { + "defaultMessage": "Sign up", + "id": "account.register" + }, + { + "defaultMessage": "Log in", + "id": "account.login" + } + ], + "path": "app/soapbox/features/ui/components/remote_interaction_modal.json" + }, + { + "descriptors": [ + { + "defaultMessage": "Close", + "id": "lightbox.close" + }, + { + "defaultMessage": "Delete", + "id": "confirmations.delete.confirm" + }, + { + "defaultMessage": "In reply to", + "id": "navigation_bar.in_reply_to" + } + ], + "path": "app/soapbox/features/ui/components/reply_mentions_modal.json" + }, { "descriptors": [ { @@ -5461,6 +6023,18 @@ "defaultMessage": "Home", "id": "tabs_bar.home" }, + { + "defaultMessage": "Notifications", + "id": "tabs_bar.notifications" + }, + { + "defaultMessage": "Chats", + "id": "tabs_bar.chats" + }, + { + "defaultMessage": "Dashboard", + "id": "tabs_bar.dashboard" + }, { "defaultMessage": "Log In", "id": "account.login" @@ -5501,24 +6075,76 @@ "id": "lightbox.close" }, { - "defaultMessage": "Sign up for {site_title}", - "id": "unauthorized_modal.title" + "defaultMessage": "Enter your username@domain you want to act from", + "id": "remote_interaction.account_placeholder" }, { - "defaultMessage": "You need to be logged in to do that.", - "id": "unauthorized_modal.text" + "defaultMessage": "Couldn't find given user", + "id": "remote_interaction.user_not_found_error" + }, + { + "defaultMessage": "Follow {user} remotely", + "id": "remote_interaction.follow_title" + }, + { + "defaultMessage": "Proceed to follow", + "id": "remote_interaction.follow" + }, + { + "defaultMessage": "Reply to a post remotely", + "id": "remote_interaction.reply_title" + }, + { + "defaultMessage": "Proceed to reply", + "id": "remote_interaction.reply" + }, + { + "defaultMessage": "Reblog a post remotely", + "id": "remote_interaction.reblog_title" + }, + { + "defaultMessage": "Proceed to repost", + "id": "remote_interaction.reblog" + }, + { + "defaultMessage": "Like a post remotely", + "id": "remote_interaction.favourite_title" + }, + { + "defaultMessage": "Proceed to like", + "id": "remote_interaction.favourite" + }, + { + "defaultMessage": "Vote in a poll remotely", + "id": "remote_interaction.poll_vote_title" + }, + { + "defaultMessage": "Proceed to vote", + "id": "remote_interaction.poll_vote" + }, + { + "defaultMessage": "or", + "id": "remote_interaction.divider" + }, + { + "defaultMessage": "Sign up for {site_title}", + "id": "unauthorized_modal.title" }, { "defaultMessage": "Sign up", "id": "account.register" }, - { - "defaultMessage": "Already have an account? {login}.", - "id": "unauthorized_modal.footer" - }, { "defaultMessage": "Log in", "id": "account.login" + }, + { + "defaultMessage": "You need to be logged in to do that.", + "id": "unauthorized_modal.text" + }, + { + "defaultMessage": "Already have an account? {login}.", + "id": "unauthorized_modal.footer" } ], "path": "app/soapbox/features/ui/components/unauthorized_modal.json" diff --git a/app/soapbox/locales/el.json b/app/soapbox/locales/el.json index fb85808f9..78e91b042 100644 --- a/app/soapbox/locales/el.json +++ b/app/soapbox/locales/el.json @@ -8,6 +8,7 @@ "account.block_domain": "Απόκρυψε τα πάντα από το {domain}", "account.blocked": "Αποκλεισμένος/η", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Αυτός ο χρήστης δεν ακολουθεί κανέναν ακόμα.", "account.follows_you": "Σε ακολουθεί", "account.hide_reblogs": "Απόκρυψη προωθήσεων από @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Η ιδιοκτησία αυτού του συνδέσμου ελέχθηκε την {date}", "account.locked_info": "Η κατάσταση απορρήτου αυτού του λογαριασμού είναι κλειδωμένη. Ο ιδιοκτήτης επιβεβαιώνει χειροκίνητα ποιος μπορεί να τον ακολουθήσει.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} μεταφέρθηκε στο:", "account.mute": "Σώπασε @{name}", "account.muted": "Αποσιωπημένος/η", + "account.never_active": "Never", "account.posts": "Τουτ", "account.posts_with_replies": "Τουτ και απαντήσεις", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Κλείσιμο", "bundle_modal_error.message": "Κάτι πήγε στραβά κατά τη φόρτωση του στοιχείου.", "bundle_modal_error.retry": "Δοκίμασε ξανά", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Αποκλεισμένοι χρήστες", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Τοπική ροή", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Προσωπικά μηνύματα", + "column.directory": "Browse profiles", "column.domain_blocks": "Κρυμμένοι τομείς", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Αιτήματα ακολούθησης", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Αρχική", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Λίστες", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Αποσιωπημένοι χρήστες", "column.notifications": "Ειδοποιήσεις", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Ομοσπονδιακή ροή", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Πίσω", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Απόκρυψη ρυθμίσεων", "column_header.show_settings": "Εμφάνιση ρυθμίσεων", "community.column_settings.media_only": "Μόνο πολυμέσα", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Διάρκεια δημοσκόπησης", "compose_form.poll.option_placeholder": "Επιλογή {number}", "compose_form.poll.remove_option": "Αφαίρεση επιλογής", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Τουτ", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Αποκλεισμός & Καταγγελία", "confirmations.block.confirm": "Απόκλεισε", "confirmations.block.message": "Σίγουρα θες να αποκλείσεις {name};", "confirmations.delete.confirm": "Διέγραψε", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Σίγουρα θες να διαγράψεις αυτή τη δημοσίευση;", "confirmations.delete_list.confirm": "Διέγραψε", "confirmations.delete_list.message": "Σίγουρα θες να διαγράψεις οριστικά αυτή τη λίστα;", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Ενέκρινε", "follow_request.reject": "Απέρριψε", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "Το {code_name} είναι ελεύθερο λογισμικό. Μπορείς να συνεισφέρεις ή να αναφέρεις ζητήματα στο GitLab στο {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Προηγούμενο", "lightbox.view_context": "Εμφάνιση πλαισίου", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Πρόσθεσε στη λίστα", "lists.account.remove": "Βγάλε από τη λίστα", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Απόκρυψη ειδοποιήσεων αυτού του χρήστη;", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Γράψε νέο τουτ", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Κρυμμένοι τομείς", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Αγαπημένα", "navigation_bar.filters": "Αποσιωπημένες λέξεις", "navigation_bar.follow_requests": "Αιτήματα ακολούθησης", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Πληροφορίες κόμβου", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Συντομεύσεις", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Αποσύνδεση", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Αποσιωπημένοι χρήστες", "navigation_bar.pins": "Καρφιτσωμένα τουτ", "navigation_bar.preferences": "Προτιμήσεις", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Ασφάλεια", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Ανανέωση", "poll.total_votes": "{count, plural, one {# ψήφος} other {# ψήφοι}}", "poll.vote": "Ψήφισε", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Προσθήκη δημοσκόπησης", "poll_button.remove_poll": "Αφαίρεση δημοσκόπησης", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Φορτώνει…", "regeneration_indicator.sublabel": "Η αρχική σου ροή ετοιμάζεται!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}η", "relative_time.hours": "{number}ω", "relative_time.just_now": "τώρα", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Άκυρο", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Προώθηση προς {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Αναζήτηση", - "search_popout.search_format": "Προχωρημένη αναζήτηση", - "search_popout.tips.full_text": "Απλό κείμενο που επιστρέφει καταστάσεις που έχεις γράψει, σημειώσει ως αγαπημένες, προωθήσει ή έχεις αναφερθεί σε αυτές, καθώς και όσα ονόματα χρηστών και ταμπέλες ταιριάζουν.", - "search_popout.tips.hashtag": "ταμπέλα", - "search_popout.tips.status": "κατάσταση", - "search_popout.tips.user": "χρήστης", "search_results.accounts": "Άνθρωποι", "search_results.hashtags": "Ταμπέλες", "search_results.statuses": "Τουτ", diff --git a/app/soapbox/locales/en-Shaw.json b/app/soapbox/locales/en-Shaw.json new file mode 100644 index 000000000..ae0b73eb2 --- /dev/null +++ b/app/soapbox/locales/en-Shaw.json @@ -0,0 +1,975 @@ +{ + "about.also_available": "𐑩𐑝𐑱𐑤𐑩𐑚𐑩𐑤 𐑦𐑯:", + "accordion.collapse": "𐑒𐑩𐑤𐑨𐑐𐑕", + "accordion.expand": "𐑦𐑒𐑕𐑐𐑨𐑯𐑛", + "account.add_or_remove_from_list": "𐑨𐑛 𐑹 𐑮𐑦𐑥𐑵𐑝 𐑮𐑦𐑥𐑵𐑝 𐑤𐑦𐑕𐑑𐑕", + "account.badges.bot": "𐑚𐑪𐑑", + "account.block": "𐑚𐑤𐑪𐑒 @{name}", + "account.block_domain": "𐑣𐑲𐑛 𐑧𐑝𐑮𐑦𐑔𐑦𐑙 𐑓𐑮𐑪𐑥 {domain}", + "account.blocked": "𐑚𐑤𐑪𐑒𐑑", + "account.chat": "𐑗𐑨𐑑 𐑢𐑦𐑞 @{name}", + "account.column_settings.description": "𐑞𐑰𐑟 𐑕𐑧𐑑𐑦𐑙𐑟 𐑩𐑐𐑤𐑲 𐑑 𐑷𐑤 𐑩𐑒𐑬𐑯𐑑 𐑑𐑲𐑥𐑤𐑲𐑯𐑟.", + "account.column_settings.title": "𐑩𐑒𐑬𐑯𐑑 𐑑𐑲𐑥𐑤𐑲𐑯 𐑕𐑧𐑑𐑦𐑙𐑟", + "account.deactivated": "𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑𐑩𐑛", + "account.deactivated_description": "𐑞𐑦𐑕 𐑩𐑒𐑬𐑯𐑑 𐑣𐑨𐑟 𐑚𐑰𐑯 𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑𐑩𐑛.", + "account.direct": "𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡 @{name}", + "account.domain_blocked": "𐑛𐑴𐑥𐑱𐑯 𐑣𐑦𐑛𐑩𐑯", + "account.edit_profile": "𐑧𐑛𐑦𐑑 𐑐𐑮𐑴𐑓𐑲𐑤", + "account.endorse": "𐑓𐑰𐑗𐑼 𐑪𐑯 𐑐𐑮𐑴𐑓𐑲𐑤", + "account.follow": "𐑓𐑪𐑤𐑴", + "account.followers": "𐑓𐑪𐑤𐑴𐑼𐑟", + "account.followers.empty": "𐑯𐑴 𐑢𐑳𐑯 𐑓𐑪𐑤𐑴𐑟 𐑞𐑦𐑕 𐑿𐑟𐑼 𐑘𐑧𐑑.", + "account.follows": "𐑓𐑪𐑤𐑴𐑟", + "account.follows.empty": "𐑞𐑦𐑕 𐑿𐑟𐑼 𐑛𐑳𐑟𐑩𐑯𐑑 𐑓𐑪𐑤𐑴 𐑧𐑯𐑦𐑢𐑳𐑯 𐑘𐑧𐑑.", + "account.follows_you": "𐑓𐑪𐑤𐑴𐑟 𐑿", + "account.hide_reblogs": "𐑣𐑲𐑛 𐑮𐑰𐑐𐑴𐑕𐑑𐑕 𐑓𐑮𐑪𐑥 @{name}", + "account.last_status": "𐑤𐑭𐑕𐑑 𐑨𐑒𐑑𐑦𐑝", + "account.link_verified_on": "𐑴𐑯𐑼𐑖𐑦𐑐 𐑝 𐑞𐑦𐑕 𐑤𐑦𐑙𐑒 𐑢𐑪𐑟 𐑗𐑧𐑒𐑑 𐑪𐑯 {date}", + "account.locked_info": "𐑞𐑦𐑕 𐑩𐑒𐑬𐑯𐑑 𐑐𐑮𐑦𐑝𐑩𐑕𐑦 𐑕𐑑𐑱𐑑𐑩𐑕 𐑦𐑟 𐑕𐑧𐑑 𐑑 𐑤𐑪𐑒𐑑. 𐑞 𐑴𐑯𐑼 𐑥𐑨𐑯𐑘𐑫𐑩𐑤𐑦 𐑮𐑦𐑝𐑿𐑟 𐑣𐑵 𐑒𐑨𐑯 𐑓𐑪𐑤𐑴 𐑞𐑧𐑥.", + "account.login": "𐑤𐑪𐑜 𐑦𐑯", + "account.media": "𐑥𐑰𐑛𐑾", + "account.member_since": "𐑡𐑶𐑯𐑛 {date}", + "account.mention": "𐑥𐑧𐑯𐑖𐑩𐑯", + "account.moved_to": "{name} 𐑣𐑨𐑟 𐑥𐑵𐑝𐑛 𐑑:", + "account.mute": "𐑥𐑿𐑑 @{name}", + "account.muted": "𐑥𐑿𐑑𐑩𐑛", + "account.never_active": "𐑯𐑧𐑝𐑼", + "account.posts": "𐑐𐑴𐑕𐑑𐑕", + "account.posts_with_replies": "𐑐𐑴𐑕𐑑𐑕 𐑯 𐑮𐑦𐑐𐑤𐑲𐑟", + "account.profile": "𐑐𐑮𐑴𐑓𐑲𐑤", + "account.register": "𐑕𐑲𐑯 𐑳𐑐", + "account.remote_follow": "𐑮𐑦𐑥𐑴𐑑 𐑓𐑪𐑤𐑴", + "account.report": "𐑮𐑦𐑐𐑹𐑑 @{name}", + "account.requested": "𐑩𐑢𐑱𐑑𐑦𐑙 𐑩𐑐𐑮𐑵𐑝𐑩𐑤. 𐑒𐑤𐑦𐑒 𐑑 𐑒𐑨𐑯𐑕𐑩𐑤 𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑", + "account.requested_small": "𐑩𐑢𐑱𐑑𐑦𐑙 𐑩𐑐𐑮𐑵𐑝𐑩𐑤", + "account.share": "𐑖𐑺 @{name}'s 𐑐𐑮𐑴𐑓𐑲𐑤", + "account.show_reblogs": "𐑖𐑴 𐑮𐑰𐑐𐑴𐑕𐑑𐑕 𐑓𐑮𐑪𐑥 @{name}", + "account.subscribe": "𐑕𐑩𐑚𐑕𐑒𐑮𐑲𐑚 𐑑 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑓𐑮𐑪𐑥 @{name}", + "account.subscribed": "𐑕𐑩𐑚𐑕𐑒𐑮𐑲𐑚𐑛", + "account.unblock": "𐑳𐑯𐑚𐑤𐑪𐑒 @{name}", + "account.unblock_domain": "𐑳𐑯𐑣𐑲𐑛 {domain}", + "account.unendorse": "𐑛𐑴𐑯𐑑 𐑓𐑰𐑗𐑼 𐑪𐑯 𐑐𐑮𐑴𐑓𐑲𐑤", + "account.unfollow": "𐑳𐑯𐑓𐑪𐑤𐑴", + "account.unmute": "𐑳𐑯𐑥𐑿𐑑 @{name}", + "account.unsubscribe": "𐑳𐑯𐑕𐑩𐑚𐑕𐑒𐑮𐑲𐑚 𐑑 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑓𐑮𐑪𐑥 @{name}", + "account_gallery.none": "𐑯𐑴 𐑥𐑰𐑛𐑾 𐑑 𐑖𐑴.", + "account_search.placeholder": "𐑕𐑻𐑗 𐑓 𐑩𐑯 𐑩𐑒𐑬𐑯𐑑", + "account_timeline.column_settings.show_pinned": "𐑖𐑴 𐑐𐑦𐑯𐑛 𐑐𐑴𐑕𐑑𐑕", + "admin.awaiting_approval.approved_message": "{acct} 𐑢𐑪𐑟 𐑩𐑐𐑮𐑵𐑝𐑛!", + "admin.awaiting_approval.empty_message": "𐑞𐑺 𐑦𐑟 𐑯𐑴𐑚𐑪𐑛𐑦 𐑢𐑱𐑑𐑦𐑙 𐑓 𐑩𐑐𐑮𐑵𐑝𐑩𐑤. 𐑢𐑧𐑯 𐑩 𐑯𐑿 𐑿𐑟𐑼 𐑕𐑲𐑯𐑟 𐑳𐑐, 𐑿 𐑒𐑨𐑯 𐑮𐑦𐑝𐑿 𐑞𐑧𐑥 𐑣𐑽.", + "admin.awaiting_approval.rejected_message": "{acct} 𐑢𐑪𐑟 𐑮𐑦𐑡𐑧𐑒𐑑𐑩𐑛.", + "admin.dashboard.registration_mode.approval_hint": "𐑿𐑟𐑼𐑟 𐑒𐑨𐑯 𐑕𐑲𐑯 𐑳𐑐, 𐑚𐑳𐑑 𐑞𐑺 𐑩𐑒𐑬𐑯𐑑 𐑴𐑯𐑤𐑦 𐑜𐑧𐑑𐑕 𐑨𐑒𐑑𐑦𐑝𐑱𐑑𐑩𐑛 𐑢𐑧𐑯 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯 𐑩𐑐𐑮𐑵𐑝𐑟 𐑦𐑑.", + "admin.dashboard.registration_mode.approval_label": "𐑩𐑐𐑮𐑵𐑝𐑩𐑤 𐑮𐑦𐑒𐑢𐑲𐑼𐑛", + "admin.dashboard.registration_mode.closed_hint": "𐑯𐑴𐑚𐑪𐑛𐑦 𐑒𐑨𐑯 𐑕𐑲𐑯 𐑳𐑐. 𐑿 𐑒𐑨𐑯 𐑕𐑑𐑦𐑤 𐑦𐑯𐑝𐑲𐑑 𐑐𐑰𐑐𐑩𐑤.", + "admin.dashboard.registration_mode.closed_label": "𐑒𐑤𐑴𐑟𐑛", + "admin.dashboard.registration_mode.open_hint": "𐑧𐑯𐑦𐑢𐑳𐑯 𐑒𐑨𐑯 𐑡𐑶𐑯.", + "admin.dashboard.registration_mode.open_label": "𐑴𐑐𐑩𐑯", + "admin.dashboard.registration_mode_label": "𐑮𐑧𐑡𐑦𐑕𐑑𐑮𐑱𐑖𐑩𐑯𐑟", + "admin.dashboard.settings_saved": "𐑕𐑧𐑑𐑦𐑙𐑟 𐑕𐑱𐑝𐑛!", + "admin.dashcounters.domain_count_label": "𐑐𐑽𐑟", + "admin.dashcounters.mau_label": "𐑥𐑳𐑯𐑔𐑤𐑦 𐑨𐑒𐑑𐑦𐑝 𐑿𐑟𐑼𐑟", + "admin.dashcounters.retention_label": "𐑿𐑟𐑼 𐑮𐑦𐑑𐑧𐑯𐑖𐑩𐑯", + "admin.dashcounters.status_count_label": "𐑐𐑴𐑕𐑑𐑕", + "admin.dashcounters.user_count_label": "𐑑𐑴𐑑𐑩𐑤 𐑿𐑟𐑼𐑟", + "admin.dashwidgets.email_list_header": "𐑰𐑥𐑱𐑤 𐑤𐑦𐑕𐑑", + "admin.dashwidgets.software_header": "𐑕𐑪𐑓𐑑𐑢𐑺", + "admin.latest_accounts_panel.expand_message": "𐑒𐑤𐑦𐑒 𐑑 𐑕𐑰 {count} 𐑥𐑹 {count, plural, one {account} other {accounts}}", + "admin.latest_accounts_panel.title": "𐑤𐑱𐑑𐑩𐑕𐑑 𐑩𐑒𐑬𐑯𐑑𐑕", + "admin.moderation_log.empty_message": "𐑿 𐑣𐑨𐑝 𐑯𐑪𐑑 𐑐𐑼𐑓𐑹𐑥𐑛 𐑧𐑯𐑦 𐑥𐑪𐑛𐑼𐑱𐑖𐑩𐑯 𐑨𐑒𐑖𐑩𐑯𐑟 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 do, 𐑩 𐑣𐑦𐑕𐑑𐑼𐑦 𐑢𐑦𐑤 𐑚𐑰 𐑖𐑴𐑯 𐑣𐑽.", + "admin.reports.actions.close": "𐑒𐑤𐑴𐑟", + "admin.reports.actions.view_status": "𐑝𐑿 𐑐𐑴𐑕𐑑", + "admin.reports.empty_message": "𐑞𐑺 𐑸 𐑯𐑴 𐑴𐑐𐑩𐑯 𐑮𐑦𐑐𐑹𐑑𐑕. 𐑦𐑓 𐑩 𐑿𐑟𐑼 𐑜𐑧𐑑𐑕 𐑮𐑦𐑐𐑹𐑑𐑩𐑛, 𐑞𐑱 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "admin.reports.report_closed_message": "𐑮𐑦𐑐𐑹𐑑 𐑪𐑯 @{name} 𐑢𐑪𐑟 𐑒𐑤𐑴𐑟𐑛", + "admin.reports.report_title": "𐑮𐑦𐑐𐑹𐑑 𐑪𐑯 {acct}", + "admin.statuses.actions.delete_status": "𐑛𐑦𐑤𐑰𐑑 𐑐𐑴𐑕𐑑", + "admin.statuses.actions.mark_status_not_sensitive": "𐑥𐑸𐑒 𐑐𐑴𐑕𐑑 𐑯𐑪𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "admin.statuses.actions.mark_status_sensitive": "𐑥𐑸𐑒 𐑐𐑴𐑕𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "admin.statuses.status_deleted_message": "𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct} 𐑢𐑪𐑟 𐑛𐑦𐑤𐑰𐑑𐑩𐑛", + "admin.statuses.status_marked_message_not_sensitive": "𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct} 𐑢𐑪𐑟 𐑥𐑸𐑒𐑑 𐑯𐑪𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "admin.statuses.status_marked_message_sensitive": "𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct} 𐑢𐑪𐑟 𐑥𐑸𐑒𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "admin.user_index.empty": "𐑯𐑴 𐑿𐑟𐑼𐑟 𐑓𐑬𐑯𐑛.", + "admin.user_index.search_input_placeholder": "𐑣𐑵 𐑸 𐑿 𐑤𐑫𐑒𐑦𐑙 for?", + "admin.users.actions.deactivate_user": "𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑 @{name}", + "admin.users.actions.delete_user": "𐑛𐑦𐑤𐑰𐑑 @{name}", + "admin.users.actions.demote_to_moderator": "𐑛𐑦𐑥𐑴𐑑 @{name} 𐑑 𐑩 𐑥𐑪𐑛𐑼𐑱𐑑𐑼", + "admin.users.actions.demote_to_moderator_message": "@{acct} 𐑢𐑪𐑟 𐑛𐑦𐑥𐑴𐑑𐑩𐑛 𐑑 𐑩 𐑥𐑪𐑛𐑼𐑱𐑑𐑼", + "admin.users.actions.demote_to_user": "𐑛𐑦𐑥𐑴𐑑 @{name} 𐑑 𐑩 𐑮𐑧𐑜𐑘𐑩𐑤𐑼 𐑿𐑟𐑼", + "admin.users.actions.demote_to_user_message": "@{acct} 𐑢𐑪𐑟 𐑛𐑦𐑥𐑴𐑑𐑩𐑛 𐑑 𐑩 𐑮𐑧𐑜𐑘𐑩𐑤𐑼 𐑿𐑟𐑼", + "admin.users.actions.promote_to_admin": "𐑐𐑮𐑩𐑥𐑴𐑑 @{name} 𐑑 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯", + "admin.users.actions.promote_to_admin_message": "@{acct} 𐑢𐑪𐑟 𐑐𐑮𐑩𐑥𐑴𐑑𐑩𐑛 𐑑 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯", + "admin.users.actions.promote_to_moderator": "𐑐𐑮𐑩𐑥𐑴𐑑 @{name} 𐑑 𐑩 𐑥𐑪𐑛𐑼𐑱𐑑𐑼", + "admin.users.actions.promote_to_moderator_message": "@{acct} 𐑢𐑪𐑟 𐑐𐑮𐑩𐑥𐑴𐑑𐑩𐑛 𐑑 𐑩 𐑥𐑪𐑛𐑼𐑱𐑑𐑼", + "admin.users.actions.suggest_user": "𐑕𐑩𐑡𐑧𐑕𐑑 @{name}", + "admin.users.actions.unsuggest_user": "𐑳𐑯𐑕𐑩𐑡𐑧𐑕𐑑 @{name}", + "admin.users.actions.unverify_user": "𐑳𐑯𐑝𐑧𐑮𐑦𐑓𐑲 @{name}", + "admin.users.actions.verify_user": "𐑝𐑧𐑮𐑦𐑓𐑲 @{name}", + "admin.users.user_deactivated_message": "@{acct} 𐑢𐑪𐑟 𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑𐑩𐑛", + "admin.users.user_deleted_message": "@{acct} 𐑢𐑪𐑟 𐑛𐑦𐑤𐑰𐑑𐑩𐑛", + "admin.users.user_suggested_message": "@{acct} 𐑢𐑪𐑟 𐑕𐑩𐑡𐑧𐑕𐑑𐑩𐑛", + "admin.users.user_unsuggested_message": "@{acct} 𐑢𐑪𐑟 𐑳𐑯𐑕𐑩𐑡𐑧𐑕𐑑𐑩𐑛", + "admin.users.user_unverified_message": "@{acct} 𐑢𐑪𐑟 𐑳𐑯𐑝𐑧𐑮𐑦𐑓𐑲𐑛", + "admin.users.user_verified_message": "@{acct} 𐑢𐑪𐑟 𐑝𐑧𐑮𐑦𐑓𐑲𐑛", + "admin_nav.awaiting_approval": "𐑩𐑢𐑱𐑑𐑦𐑙 𐑩𐑐𐑮𐑵𐑝𐑩𐑤", + "admin_nav.dashboard": "𐑛𐑨𐑖𐑚𐑹𐑛", + "admin_nav.reports": "𐑮𐑦𐑐𐑹𐑑𐑕", + "alert.unexpected.clear_cookies": "𐑒𐑤𐑽 𐑒𐑫𐑒𐑦𐑟 𐑯 𐑚𐑮𐑬𐑟𐑼 𐑛𐑱𐑑𐑩", + "alert.unexpected.help_text": "𐑦𐑓 𐑞 𐑐𐑮𐑪𐑚𐑤𐑩𐑥 𐑐𐑼𐑕𐑦𐑕𐑑𐑕, 𐑐𐑤𐑰𐑟 𐑯𐑴𐑑𐑦𐑓𐑲 𐑩 𐑕𐑲𐑑 𐑨𐑛𐑥𐑦𐑯 𐑢𐑦𐑞 𐑩 𐑕𐑒𐑮𐑰𐑯𐑖𐑪𐑑 𐑯 𐑦𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑩𐑚𐑬𐑑 𐑘𐑹 𐑢𐑧𐑚 𐑚𐑮𐑬𐑟𐑼. 𐑿 𐑥𐑱 𐑷𐑤𐑕𐑴 {clear_cookies} (𐑞𐑦𐑕 𐑢𐑦𐑤 𐑤𐑪𐑜 𐑿 𐑬𐑑).", + "alert.unexpected.message": "𐑩𐑯 𐑳𐑯𐑦𐑒𐑕𐑐𐑧𐑒𐑑𐑩𐑛 𐑧𐑮𐑼 occurred.", + "alert.unexpected.return_home": "𐑮𐑦𐑑𐑻𐑯 𐑣𐑴𐑥", + "alert.unexpected.title": "𐑵𐑐𐑕!", + "aliases.account.add": "𐑒𐑮𐑦𐑱𐑑 𐑱𐑤𐑾𐑕", + "aliases.account_label": "𐑴𐑤𐑛 𐑩𐑒𐑬𐑯𐑑:", + "aliases.aliases_list_delete": "𐑳𐑯𐑤𐑦𐑙𐑒 𐑱𐑤𐑾𐑕", + "aliases.search": "𐑕𐑻𐑗 𐑘𐑹 𐑴𐑤𐑛 𐑩𐑒𐑬𐑯𐑑", + "aliases.success.add": "𐑩𐑒𐑬𐑯𐑑 𐑱𐑤𐑾𐑕 𐑒𐑮𐑦𐑱𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "aliases.success.remove": "𐑩𐑒𐑬𐑯𐑑 𐑱𐑤𐑾𐑕 𐑮𐑦𐑥𐑵𐑝𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "app_create.name_label": "𐑨𐑐 𐑯𐑱𐑥", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "𐑮𐑰𐑛𐑦𐑮𐑧𐑒𐑑 URIs", + "app_create.restart": "𐑒𐑮𐑦𐑱𐑑 𐑩𐑯𐑳𐑞𐑼", + "app_create.results.app_label": "𐑨𐑐", + "app_create.results.explanation_text": "𐑿 𐑒𐑮𐑦𐑱𐑑𐑩𐑛 𐑩 𐑯𐑿 𐑨𐑐 𐑯 𐑑𐑴𐑒𐑩𐑯! 𐑐𐑤𐑰𐑟 𐑒𐑪𐑐𐑦 𐑞 𐑒𐑮𐑦𐑛𐑧𐑯𐑖𐑩𐑤𐑟 𐑕𐑳𐑥𐑢𐑺; 𐑿 𐑢𐑦𐑤 𐑯𐑪𐑑 𐑕𐑰 𐑞𐑧𐑥 𐑩𐑜𐑱𐑯 𐑭𐑓𐑑𐑼 𐑯𐑨𐑝𐑦𐑜𐑱𐑑𐑦𐑙 𐑩𐑢𐑱 𐑓𐑮𐑪𐑥 𐑞𐑦𐑕 𐑐𐑱𐑡.", + "app_create.results.explanation_title": "𐑨𐑐 𐑒𐑮𐑦𐑱𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "app_create.results.token_label": "OAuth 𐑑𐑴𐑒𐑩𐑯", + "app_create.scopes_label": "𐑕𐑒𐑴𐑐𐑕", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "𐑒𐑮𐑦𐑱𐑑 𐑨𐑐", + "app_create.website_label": "𐑢𐑧𐑚𐑕𐑲𐑑", + "auth.invalid_credentials": "𐑮𐑪𐑙 𐑿𐑟𐑼𐑯𐑱𐑥 𐑹 𐑐𐑭𐑕𐑢𐑻𐑛", + "auth.logged_out": "𐑤𐑪𐑜𐑛 𐑬𐑑.", + "backups.actions.create": "𐑒𐑮𐑦𐑱𐑑 𐑚𐑨𐑒𐑳𐑐", + "backups.empty_message": "𐑯𐑴 𐑚𐑨𐑒𐑳𐑐𐑕 𐑓𐑬𐑯𐑛. {action}", + "backups.empty_message.action": "𐑒𐑮𐑦𐑱𐑑 𐑢𐑳𐑯 𐑯𐑬?", + "backups.pending": "𐑐𐑧𐑯𐑛𐑦𐑙", + "boost_modal.combo": "𐑿 𐑒𐑨𐑯 𐑐𐑮𐑧𐑕 {combo} 𐑑 𐑕𐑒𐑦𐑐 𐑞𐑦𐑕 𐑯𐑧𐑒𐑕𐑑 𐑑𐑲𐑥", + "bundle_column_error.body": "𐑕𐑳𐑥𐑔𐑦𐑙 𐑢𐑧𐑯𐑑 𐑮𐑪𐑙 𐑢𐑲𐑤 𐑤𐑴𐑛𐑦𐑙 𐑞𐑦𐑕 𐑒𐑩𐑥𐑐𐑴𐑯𐑩𐑯𐑑.", + "bundle_column_error.retry": "𐑑𐑮𐑲 𐑩𐑜𐑱𐑯", + "bundle_column_error.title": "𐑯𐑧𐑑𐑢𐑻𐑒 𐑧𐑮𐑼", + "bundle_modal_error.close": "𐑒𐑤𐑴𐑟", + "bundle_modal_error.message": "𐑕𐑳𐑥𐑔𐑦𐑙 𐑢𐑧𐑯𐑑 𐑮𐑪𐑙 𐑢𐑲𐑤 𐑤𐑴𐑛𐑦𐑙 𐑞𐑦𐑕 𐑒𐑩𐑥𐑐𐑴𐑯𐑩𐑯𐑑.", + "bundle_modal_error.retry": "𐑑𐑮𐑲 𐑩𐑜𐑱𐑯", + "chat_box.actions.close": "𐑒𐑤𐑴𐑟 𐑗𐑨𐑑", + "chat_box.actions.send": "𐑕𐑧𐑯𐑛", + "chat_box.input.placeholder": "𐑕𐑧𐑯𐑛 𐑩 𐑥𐑧𐑕𐑦𐑡…", + "chat_panels.main_window.empty": "𐑯𐑴 𐑗𐑨𐑑𐑕 𐑓𐑬𐑯𐑛. 𐑑 𐑕𐑑𐑸𐑑 𐑩 𐑗𐑨𐑑, 𐑝𐑦𐑟𐑦𐑑 𐑩 𐑿𐑟𐑼𐑟 𐑐𐑮𐑴𐑓𐑲𐑤.", + "chat_panels.main_window.title": "𐑗𐑨𐑑𐑕", + "chats.actions.delete": "𐑛𐑦𐑤𐑰𐑑 𐑥𐑧𐑕𐑦𐑡", + "chats.actions.more": "𐑥𐑹", + "chats.actions.report": "𐑮𐑦𐑐𐑹𐑑 𐑿𐑟𐑼", + "chats.attachment": "𐑩𐑑𐑨𐑗𐑥𐑩𐑯𐑑", + "chats.attachment_image": "𐑦𐑥𐑦𐑡", + "chats.audio_toggle_off": "𐑷𐑛𐑦𐑴 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯 𐑪𐑓", + "chats.audio_toggle_on": "𐑷𐑛𐑦𐑴 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯 on", + "chats.dividers.today": "𐑑𐑩𐑛𐑱", + "chats.search_placeholder": "𐑕𐑑𐑸𐑑 𐑩 𐑗𐑨𐑑 𐑢𐑦𐑞…", + "column.admin.awaiting_approval": "𐑩𐑢𐑱𐑑𐑦𐑙 𐑩𐑐𐑮𐑵𐑝𐑩𐑤", + "column.admin.dashboard": "𐑛𐑨𐑖𐑚𐑹𐑛", + "column.admin.moderation_log": "𐑥𐑪𐑛𐑼𐑱𐑖𐑩𐑯 𐑤𐑪𐑜", + "column.admin.reports": "𐑮𐑦𐑐𐑹𐑑𐑕", + "column.admin.reports.menu.moderation_log": "𐑥𐑪𐑛𐑼𐑱𐑖𐑩𐑯 𐑤𐑪𐑜", + "column.admin.users": "𐑿𐑟𐑼𐑟", + "column.aliases": "𐑩𐑒𐑬𐑯𐑑 𐑱𐑤𐑾𐑕𐑩𐑟", + "column.aliases.create_error": "𐑧𐑮𐑼 𐑒𐑮𐑦𐑱𐑑𐑦𐑙 𐑱𐑤𐑾𐑕", + "column.aliases.delete": "𐑛𐑦𐑤𐑰𐑑", + "column.aliases.delete_error": "𐑧𐑮𐑼 𐑛𐑦𐑤𐑰𐑑𐑦𐑙 𐑱𐑤𐑾𐑕", + "column.aliases.subheading_add_new": "𐑨𐑛 𐑯𐑿 𐑱𐑤𐑾𐑕", + "column.aliases.subheading_aliases": "𐑒𐑳𐑮𐑩𐑯𐑑 𐑱𐑤𐑾𐑕𐑩𐑟", + "column.app_create": "𐑒𐑮𐑦𐑱𐑑 𐑨𐑐", + "column.backups": "𐑚𐑨𐑒𐑳𐑐𐑕", + "column.blocks": "𐑚𐑤𐑪𐑒𐑑 𐑿𐑟𐑼𐑟", + "column.bookmarks": "𐑚𐑫𐑒𐑥𐑸𐑒𐑕", + "column.chats": "𐑗𐑨𐑑𐑕", + "column.community": "𐑤𐑴𐑒𐑩𐑤 𐑑𐑲𐑥𐑤𐑲𐑯", + "column.crypto_donate": "𐑛𐑴𐑯𐑱𐑑 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦", + "column.developers": "𐑛𐑦𐑝𐑧𐑤𐑩𐑐𐑼𐑟", + "column.direct": "𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡𐑩𐑟", + "column.directory": "𐑚𐑮𐑬𐑟 𐑐𐑮𐑴𐑓𐑲𐑤s", + "column.domain_blocks": "𐑣𐑦𐑛𐑩𐑯 𐑛𐑴𐑥𐑱𐑯𐑟", + "column.edit_profile": "𐑧𐑛𐑦𐑑 𐑐𐑮𐑴𐑓𐑲𐑤", + "column.export_data": "𐑦𐑒𐑕𐑐𐑹𐑑 𐑛𐑱𐑑𐑩", + "column.favourited_statuses": "𐑤𐑲𐑒𐑑 𐑐𐑴𐑕𐑑𐑕", + "column.favourites": "𐑤𐑲𐑒𐑕", + "column.federation_restrictions": "𐑓𐑧𐑛𐑼𐑱𐑖𐑩𐑯 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟", + "column.filters": "𐑥𐑿𐑑𐑩𐑛 𐑢𐑻𐑛𐑟", + "column.filters.add_new": "𐑨𐑛 𐑯𐑿 𐑓𐑦𐑤𐑑𐑼", + "column.filters.conversations": "𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯𐑟", + "column.filters.create_error": "𐑧𐑮𐑼 𐑨𐑛𐑦𐑙 𐑓𐑦𐑤𐑑𐑼", + "column.filters.delete": "𐑛𐑦𐑤𐑰𐑑", + "column.filters.delete_error": "𐑧𐑮𐑼 𐑛𐑦𐑤𐑰𐑑𐑦𐑙 𐑓𐑦𐑤𐑑𐑼", + "column.filters.drop_header": "𐑛𐑮𐑪𐑐 𐑦𐑯𐑕𐑑𐑧𐑛 𐑝 𐑣𐑲𐑛", + "column.filters.drop_hint": "𐑓𐑦𐑤𐑑𐑼𐑛 𐑐𐑴𐑕𐑑𐑕 𐑢𐑦𐑤 𐑛𐑦𐑕𐑩𐑐𐑽 𐑦𐑮𐑦𐑝𐑻𐑕𐑩𐑚𐑤𐑦, 𐑰𐑝𐑩𐑯 𐑦𐑓 𐑓𐑦𐑤𐑑𐑼 𐑦𐑟 𐑤𐑱𐑑𐑼 𐑮𐑦𐑥𐑵𐑝𐑛", + "column.filters.expires": "𐑦𐑒𐑕𐑐𐑲𐑼 𐑭𐑓𐑑𐑼", + "column.filters.expires_hint": "𐑧𐑒𐑕𐑐𐑦𐑮𐑱𐑖𐑩𐑯 𐑛𐑱𐑑𐑕 𐑸 𐑯𐑪𐑑 𐑒𐑳𐑮𐑩𐑯𐑑𐑤𐑦 𐑕𐑩𐑐𐑹𐑑𐑩𐑛", + "column.filters.home_timeline": "𐑣𐑴𐑥 𐑑𐑲𐑥𐑤𐑲𐑯", + "column.filters.keyword": "𐑒𐑰𐑢𐑻𐑛 𐑹 𐑓𐑮𐑱𐑟", + "column.filters.notifications": "𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "column.filters.public_timeline": "𐑐𐑳𐑚𐑤𐑦𐑒 𐑑𐑲𐑥𐑤𐑲𐑯", + "column.filters.subheading_add_new": "𐑨𐑛 𐑯𐑿 𐑓𐑦𐑤𐑑𐑼", + "column.filters.subheading_filters": "𐑒𐑳𐑮𐑩𐑯𐑑 𐑓𐑦𐑤𐑑𐑼𐑟", + "column.filters.whole_word_header": "𐑣𐑴𐑤 𐑢𐑻𐑛", + "column.filters.whole_word_hint": "𐑢𐑧𐑯 𐑞 𐑒𐑰𐑢𐑻𐑛 𐑹 𐑓𐑮𐑱𐑟 𐑦𐑟 𐑨𐑤𐑓𐑩𐑯𐑿𐑥𐑧𐑮𐑦𐑒 𐑴𐑯𐑤𐑦, 𐑦𐑑 𐑢𐑦𐑤 𐑴𐑯𐑤𐑦 𐑚𐑰 𐑩𐑐𐑤𐑲𐑛 𐑦𐑓 𐑦𐑑 𐑥𐑨𐑗𐑩𐑟 𐑞 𐑣𐑴𐑤 𐑢𐑻𐑛", + "column.follow_requests": "𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑕", + "column.followers": "𐑓𐑪𐑤𐑴𐑼𐑟", + "column.following": "𐑓𐑪𐑤𐑴𐑦𐑙", + "column.groups": "𐑜𐑮𐑵𐑐𐑕", + "column.home": "𐑣𐑴𐑥", + "column.import_data": "𐑦𐑥𐑐𐑹𐑑 𐑛𐑱𐑑𐑩", + "column.info": "𐑕𐑻𐑝𐑼 𐑦𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯", + "column.lists": "𐑤𐑦𐑕𐑑𐑕", + "column.mentions": "𐑥𐑧𐑯𐑖𐑩𐑯𐑟", + "column.mfa": "𐑥𐑳𐑤𐑑𐑦-𐑓𐑨𐑒𐑑𐑼 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯", + "column.mfa_cancel": "𐑒𐑨𐑯𐑕𐑩𐑤", + "column.mfa_confirm_button": "𐑒𐑩𐑯𐑓𐑻𐑥", + "column.mfa_disable_button": "𐑛𐑦𐑕𐑱𐑚𐑩𐑤", + "column.mfa_setup": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑕𐑧𐑑𐑳𐑐", + "column.mutes": "𐑥𐑿𐑑𐑩𐑛 𐑿𐑟𐑼𐑟", + "column.notifications": "𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "column.pins": "𐑐𐑦𐑯𐑛 𐑐𐑴𐑕𐑑𐑕", + "column.preferences": "𐑐𐑮𐑧𐑓𐑼𐑩𐑯𐑕𐑩𐑟", + "column.profile_directory": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑛𐑦𐑮𐑧𐑒𐑑𐑼𐑦", + "column.public": "𐑓𐑧𐑛𐑼𐑱𐑑𐑩𐑛 𐑑𐑲𐑥𐑤𐑲𐑯", + "column.reactions": "𐑮𐑦𐑨𐑒𐑖𐑩𐑯𐑟", + "column.reblogs": "𐑮𐑰𐑐𐑴𐑕𐑑𐑕", + "column.remote": "𐑓𐑧𐑛𐑼𐑱𐑑𐑩𐑛 𐑑𐑲𐑥𐑤𐑲𐑯", + "column.scheduled_statuses": "𐑖𐑧𐑡𐑵𐑤𐑛 𐑐𐑴𐑕𐑑𐑕", + "column.search": "𐑕𐑻𐑗", + "column.security": "𐑕𐑦𐑒𐑘𐑫𐑼𐑦𐑑𐑦", + "column.soapbox_config": "·𐑕𐑴𐑐𐑚𐑪𐑒𐑕 𐑒𐑩𐑯𐑓𐑦𐑜", + "column_back_button.label": "𐑚𐑨𐑒", + "column_forbidden.body": "𐑿 𐑛𐑵 𐑯𐑪𐑑 𐑣𐑨𐑝 𐑐𐑼𐑥𐑦𐑖𐑩𐑯 𐑑 𐑨𐑒𐑕𐑧𐑕 𐑞𐑦𐑕 𐑐𐑱𐑡.", + "column_forbidden.title": "𐑓𐑼𐑚𐑦𐑛𐑩𐑯", + "column_header.hide_settings": "𐑣𐑲𐑛 𐑕𐑧𐑑𐑦𐑙𐑟", + "column_header.show_settings": "𐑖𐑴 𐑕𐑧𐑑𐑦𐑙𐑟", + "community.column_settings.media_only": "𐑥𐑰𐑛𐑾 𐑴𐑯𐑤𐑦", + "community.column_settings.title": "𐑤𐑴𐑒𐑩𐑤 𐑑𐑲𐑥𐑤𐑲𐑯 𐑕𐑧𐑑𐑦𐑙𐑟", + "compose.character_counter.title": "𐑿𐑟𐑛 {chars} 𐑬𐑑 𐑝 {maxChars} 𐑒𐑨𐑮𐑩𐑒𐑑𐑼𐑟", + "compose.invalid_schedule": "𐑿 𐑥𐑳𐑕𐑑 𐑖𐑧𐑡𐑵𐑤 𐑩 𐑐𐑴𐑕𐑑 𐑨𐑑 𐑤𐑰𐑕𐑑 5 𐑥𐑦𐑯𐑦𐑑𐑕 𐑬𐑑.", + "compose.submit_success": "𐑘𐑹 𐑐𐑴𐑕𐑑 𐑢𐑪𐑟 𐑕𐑧𐑯𐑑", + "compose_form.direct_message_warning": "𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑢𐑦𐑤 𐑴𐑯𐑤𐑦 𐑚𐑰 𐑕𐑧𐑯𐑑 𐑑 𐑞 𐑥𐑧𐑯𐑖𐑩𐑯𐑛 𐑿𐑟𐑼𐑟.", + "compose_form.hashtag_warning": "𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑢𐑴𐑯𐑑 𐑚𐑰 𐑤𐑦𐑕𐑑𐑩𐑛 𐑳𐑯𐑛𐑼 𐑧𐑯𐑦 𐑣𐑨𐑖𐑑𐑨𐑜 𐑨𐑟 𐑦𐑑 𐑦𐑟 𐑳𐑯𐑤𐑦𐑕𐑑𐑩𐑛. 𐑴𐑯𐑤𐑦 𐑐𐑳𐑚𐑤𐑦𐑒 𐑐𐑴𐑕𐑑𐑕 𐑒𐑨𐑯 𐑚𐑰 𐑕𐑻𐑗𐑑 𐑚𐑲 𐑣𐑨𐑖𐑑𐑨𐑜.", + "compose_form.lock_disclaimer": "𐑘𐑹 𐑩𐑒𐑬𐑯𐑑 𐑦𐑟 𐑯𐑪𐑑 {locked}. 𐑧𐑯𐑦𐑢𐑳𐑯 𐑒𐑨𐑯 𐑓𐑪𐑤𐑴 𐑿 𐑑 𐑝𐑿 𐑘𐑹 𐑓𐑪𐑤𐑴𐑼-𐑴𐑯𐑤𐑦 𐑐𐑴𐑕𐑑𐑕.", + "compose_form.lock_disclaimer.lock": "𐑤𐑪𐑒𐑑", + "compose_form.markdown.marked": "𐑐𐑴𐑕𐑑 𐑥𐑸𐑒𐑛𐑬𐑯 𐑦𐑯𐑱𐑚𐑩𐑤𐑛", + "compose_form.markdown.unmarked": "𐑐𐑴𐑕𐑑 𐑥𐑸𐑒𐑛𐑬𐑯 𐑛𐑦𐑕𐑱𐑚𐑩𐑤𐑛", + "compose_form.message": "𐑥𐑧𐑕𐑦𐑡", + "compose_form.placeholder": "𐑢𐑪𐑑𐑕 𐑪𐑯 𐑘𐑹 𐑥𐑲𐑯𐑛?", + "compose_form.poll.add_option": "𐑨𐑛 𐑩 𐑗𐑶𐑕", + "compose_form.poll.duration": "𐑐𐑴𐑤 𐑛𐑘𐑫𐑼𐑱𐑖𐑩𐑯", + "compose_form.poll.option_placeholder": "𐑗𐑶𐑕 {number}", + "compose_form.poll.remove_option": "𐑮𐑦𐑥𐑵𐑝 𐑞𐑦𐑕 𐑗𐑶𐑕", + "compose_form.poll.switch_to_multiple": "𐑗𐑱𐑯𐑡 𐑐𐑴𐑤 𐑑 𐑩𐑤𐑬 𐑥𐑳𐑤𐑑𐑦𐑐𐑩𐑤 𐑗𐑶𐑕𐑩𐑟", + "compose_form.poll.switch_to_single": "𐑗𐑱𐑯𐑡 𐑐𐑴𐑤 𐑑 𐑩𐑤𐑬 𐑓 𐑩 𐑕𐑦𐑙𐑜𐑩𐑤 𐑗𐑶𐑕", + "compose_form.publish": "𐑐𐑳𐑚𐑤𐑦𐑖", + "compose_form.publish_loud": "{publish}!", + "compose_form.schedule": "𐑖𐑧𐑡𐑵𐑤", + "compose_form.scheduled_statuses.click_here": "𐑒𐑤𐑦𐑒 𐑣𐑽", + "compose_form.scheduled_statuses.message": "𐑿 𐑣𐑨𐑝 𐑖𐑧𐑡𐑵𐑤𐑛 𐑐𐑴𐑕𐑑𐑕. {click_here} 𐑑 𐑕𐑰 𐑞𐑧𐑥.", + "compose_form.sensitive.hide": "𐑥𐑸𐑒 𐑥𐑰𐑛𐑾 𐑨𐑟 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "compose_form.sensitive.marked": "𐑥𐑰𐑛𐑾 𐑦𐑟 𐑥𐑸𐑒𐑑 𐑨𐑟 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "compose_form.sensitive.unmarked": "𐑥𐑰𐑛𐑾 𐑦𐑟 𐑯𐑪𐑑 𐑥𐑸𐑒𐑑 𐑨𐑟 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "compose_form.spoiler.marked": "𐑑𐑧𐑒𐑕𐑑 𐑦𐑟 𐑣𐑦𐑛𐑩𐑯 behind 𐑢𐑹𐑯𐑦𐑙", + "compose_form.spoiler.unmarked": "𐑑𐑧𐑒𐑕𐑑 𐑦𐑟 𐑯𐑪𐑑 𐑣𐑦𐑛𐑩𐑯", + "compose_form.spoiler_placeholder": "𐑮𐑲𐑑 𐑘𐑹 𐑢𐑹𐑯𐑦𐑙 𐑣𐑽", + "confirmation_modal.cancel": "𐑒𐑨𐑯𐑕𐑩𐑤", + "confirmations.admin.deactivate_user.confirm": "𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑 @{name}", + "confirmations.admin.deactivate_user.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑 @{acct}. 𐑛𐑰𐑨𐑒𐑑𐑦𐑝𐑱𐑑𐑦𐑙 𐑩 𐑿𐑟𐑼 𐑦𐑟 𐑩 𐑮𐑦𐑝𐑻𐑕𐑩𐑚𐑩𐑤 𐑨𐑒𐑖𐑩𐑯.", + "confirmations.admin.delete_local_user.checkbox": "𐑲 𐑳𐑯𐑛𐑼𐑕𐑑𐑨𐑯𐑛 𐑞𐑨𐑑 𐑲 𐑨𐑥 𐑩𐑚𐑬𐑑 𐑑 𐑛𐑦𐑤𐑰𐑑 𐑩 𐑤𐑴𐑒𐑩𐑤 𐑿𐑟𐑼.", + "confirmations.admin.delete_status.confirm": "𐑛𐑦𐑤𐑰𐑑 𐑐𐑴𐑕𐑑", + "confirmations.admin.delete_status.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑛𐑦𐑤𐑰𐑑 𐑩 𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct}. 𐑞𐑦𐑕 𐑨𐑒𐑖𐑩𐑯 𐑒𐑨𐑯𐑪𐑑 𐑚𐑰 𐑳𐑯𐑛𐑳𐑯.", + "confirmations.admin.delete_user.confirm": "𐑛𐑦𐑤𐑰𐑑 @{name}", + "confirmations.admin.delete_user.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑛𐑦𐑤𐑰𐑑 @{acct}. ¡𐑞𐑦𐑕 𐑦𐑟 𐑩 𐑛𐑦𐑕𐑑𐑮𐑳𐑒𐑑𐑦𐑝 𐑨𐑒𐑖𐑩𐑯 𐑞𐑨𐑑 𐑒𐑨𐑯𐑪𐑑 𐑚𐑰 𐑳𐑯𐑛𐑳𐑯!", + "confirmations.admin.mark_status_not_sensitive.confirm": "𐑥𐑸𐑒 𐑐𐑴𐑕𐑑 𐑯𐑪𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "confirmations.admin.mark_status_not_sensitive.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑥𐑸𐑒 𐑩 𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct} 𐑯𐑪𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝.", + "confirmations.admin.mark_status_sensitive.confirm": "𐑥𐑸𐑒 𐑐𐑴𐑕𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "confirmations.admin.mark_status_sensitive.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑥𐑸𐑒 𐑩 𐑐𐑴𐑕𐑑 𐑚𐑲 @{acct} 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝.", + "confirmations.admin.reject_user.confirm": "𐑮𐑦𐑡𐑧𐑒𐑑 @{name}", + "confirmations.admin.reject_user.message": "𐑿 𐑸 𐑩𐑚𐑬𐑑 𐑑 𐑮𐑦𐑡𐑧𐑒𐑑 @{acct} 𐑮𐑧𐑡𐑦𐑕𐑑𐑮𐑱𐑖𐑩𐑯 𐑮𐑦𐑒𐑢𐑧𐑕𐑑. 𐑞𐑦𐑕 𐑨𐑒𐑖𐑩𐑯 𐑒𐑨𐑯𐑪𐑑 𐑚𐑰 𐑳𐑯𐑛𐑳𐑯.", + "confirmations.block.block_and_report": "𐑚𐑤𐑪𐑒 𐑯 𐑮𐑦𐑐𐑹𐑑", + "confirmations.block.confirm": "𐑚𐑤𐑪𐑒", + "confirmations.block.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑚𐑤𐑪𐑒 {name}?", + "confirmations.delete.confirm": "𐑛𐑦𐑤𐑰𐑑", + "confirmations.delete.heading": "𐑛𐑦𐑤𐑰𐑑 𐑐𐑴𐑕𐑑", + "confirmations.delete.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑛𐑦𐑤𐑰𐑑 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑?", + "confirmations.delete_list.confirm": "𐑛𐑦𐑤𐑰𐑑", + "confirmations.delete_list.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑐𐑻𐑥𐑩𐑯𐑩𐑯𐑑𐑤𐑦 𐑛𐑦𐑤𐑰𐑑 𐑞𐑦𐑕 list?", + "confirmations.domain_block.confirm": "𐑣𐑲𐑛 𐑦𐑯𐑑𐑲𐑼 𐑛𐑴𐑥𐑱𐑯", + "confirmations.domain_block.message": "𐑸 𐑿 𐑮𐑾𐑤𐑦, 𐑮𐑾𐑤𐑦 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑚𐑤𐑪𐑒 𐑞 𐑦𐑯𐑑𐑲𐑼 {domain}? 𐑦𐑯 𐑥𐑴𐑕𐑑 𐑒𐑱𐑕𐑩𐑟 𐑩 𐑓𐑿 𐑑𐑸𐑜𐑩𐑑𐑩𐑛 𐑚𐑤𐑪𐑒𐑕 𐑹 𐑥𐑿𐑑𐑕 𐑸 𐑕𐑩𐑓𐑦𐑖𐑩𐑯𐑑 𐑯 𐑐𐑮𐑧𐑓𐑼𐑩𐑚𐑩𐑤. 𐑿 𐑢𐑦𐑤 𐑯𐑪𐑑 𐑕𐑰 𐑒𐑪𐑯𐑑𐑧𐑯𐑑 𐑓𐑮𐑪𐑥 𐑞𐑨𐑑 𐑛𐑴𐑥𐑱𐑯 𐑦𐑯 𐑧𐑯𐑦 𐑐𐑳𐑚𐑤𐑦𐑒 𐑑𐑲𐑥𐑤𐑲𐑯𐑟 𐑹 𐑘𐑹 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟.", + "confirmations.mute.confirm": "𐑥𐑿𐑑", + "confirmations.mute.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑥𐑿𐑑 {name}?", + "confirmations.redraft.confirm": "𐑛𐑦𐑤𐑰𐑑 𐑯 𐑮𐑰𐑛𐑮𐑭𐑓𐑑", + "confirmations.redraft.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑛𐑦𐑤𐑰𐑑 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑯 𐑮𐑰𐑛𐑮𐑭𐑓𐑑 𐑦𐑑? 𐑓𐑱𐑝𐑼𐑦𐑑𐑕 𐑯 𐑮𐑰𐑐𐑴𐑕𐑑𐑕 𐑢𐑦𐑤 𐑚𐑰 𐑤𐑪𐑕𐑑, 𐑯 𐑮𐑦𐑐𐑤𐑲𐑟 𐑑 𐑞 𐑼𐑦𐑡𐑦𐑯𐑩𐑤 𐑐𐑴𐑕𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑹𐑓𐑩𐑯𐑛.", + "confirmations.register.needs_approval": "𐑘𐑹 𐑩𐑒𐑬𐑯𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑥𐑨𐑯𐑘𐑫𐑩𐑤𐑦 𐑩𐑐𐑮𐑵𐑝𐑛 𐑚𐑲 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯. 𐑐𐑤𐑰𐑟 𐑚𐑰 𐑐𐑱𐑖𐑩𐑯𐑑 𐑢𐑲𐑤 𐑢𐑰 𐑮𐑦𐑝𐑿 𐑘𐑹 𐑛𐑰𐑑𐑱𐑤𐑟.", + "confirmations.register.needs_confirmation": "𐑐𐑤𐑰𐑟 𐑗𐑧𐑒 𐑘𐑹 𐑦𐑯𐑚𐑪𐑒𐑕 𐑨𐑑 {email} 𐑓 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑦𐑯𐑕𐑑𐑮𐑳𐑒𐑖𐑩𐑯𐑟. 𐑿 𐑢𐑦𐑤 𐑯𐑰𐑛 𐑑 𐑝𐑧𐑮𐑦𐑓𐑲 𐑘𐑹 𐑰𐑥𐑱𐑤 𐑩𐑛𐑮𐑧𐑕 𐑑 𐑒𐑩𐑯𐑑𐑦𐑯𐑿.", + "confirmations.reply.confirm": "𐑮𐑦𐑐𐑤𐑲", + "confirmations.reply.message": "𐑮𐑦𐑐𐑤𐑲𐑦𐑙 𐑯𐑬 𐑢𐑦𐑤 𐑴𐑝𐑼𐑲𐑑 𐑞 𐑥𐑧𐑕𐑦𐑡 𐑿 𐑸 𐑒𐑳𐑮𐑩𐑯𐑑𐑤𐑦 𐑒𐑩𐑥𐑐𐑴𐑟𐑦𐑙. 𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑐𐑮𐑩𐑕𐑰𐑛?", + "confirmations.unfollow.confirm": "𐑳𐑯𐑓𐑪𐑤𐑴", + "confirmations.unfollow.message": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑳𐑯𐑓𐑪𐑤𐑴 {name}?", + "crypto_donate.explanation_box.message": "{siteTitle} 𐑩𐑒𐑕𐑧𐑐𐑑𐑕 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦 𐑛𐑴𐑯𐑱𐑖𐑩𐑯𐑟. 𐑿 𐑥𐑱 𐑕𐑧𐑯𐑛 𐑩 𐑛𐑴𐑯𐑱𐑖𐑩𐑯 𐑑 𐑧𐑯𐑦 𐑝 𐑞 𐑩𐑛𐑮𐑧𐑕𐑩𐑟 𐑚𐑦𐑤𐑴. 𐑔𐑨𐑙𐑒 𐑿 𐑓 𐑘𐑹 𐑕𐑩𐑐𐑹𐑑!", + "crypto_donate.explanation_box.title": "𐑕𐑧𐑯𐑛𐑦𐑙 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦 𐑛𐑴𐑯𐑱𐑖𐑩𐑯𐑟", + "crypto_donate_panel.actions.more": "𐑒𐑤𐑦𐑒 𐑑 𐑕𐑰 {count} 𐑥𐑹 {count, plural, one {wallet} other {wallets}}", + "crypto_donate_panel.heading": "𐑛𐑴𐑯𐑱𐑑 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦", + "crypto_donate_panel.intro.message": "{siteTitle} 𐑩𐑒𐑕𐑧𐑐𐑑𐑕 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦 𐑛𐑴𐑯𐑱𐑖𐑩𐑯𐑟 𐑑 fund our 𐑕𐑻𐑝𐑦𐑕. 𐑔𐑨𐑙𐑒 𐑿 𐑓 𐑘𐑹 𐑕𐑩𐑐𐑹𐑑!", + "datepicker.hint": "𐑖𐑧𐑡𐑵𐑤𐑛 𐑑 𐑐𐑴𐑕𐑑 𐑨𐑑…", + "developers.navigation.app_create_label": "𐑒𐑮𐑦𐑱𐑑 𐑩𐑯 𐑨𐑐", + "developers.navigation.intentional_error_label": "𐑑𐑮𐑦𐑜𐑼 𐑩𐑯 𐑧𐑮𐑼", + "direct.search_placeholder": "𐑕𐑧𐑯𐑛 𐑩 𐑥𐑧𐑕𐑦𐑡 to…", + "directory.federated": "𐑓𐑮𐑪𐑥 𐑯𐑴𐑯 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕", + "directory.local": "𐑓𐑮𐑪𐑥 {domain} 𐑴𐑯𐑤𐑦", + "directory.new_arrivals": "𐑯𐑿 𐑼𐑲𐑝𐑩𐑤𐑟", + "directory.recently_active": "𐑮𐑰𐑕𐑩𐑯𐑑𐑤𐑦 𐑨𐑒𐑑𐑦𐑝", + "donate": "𐑛𐑴𐑯𐑱𐑑", + "donate_crypto": "𐑛𐑴𐑯𐑱𐑑 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦", + "edit_federation.followers_only": "𐑣𐑲𐑛 𐑐𐑴𐑕𐑑𐑕 𐑦𐑒𐑕𐑧𐑐𐑑 𐑑 𐑓𐑪𐑤𐑴𐑼𐑟", + "edit_federation.force_nsfw": "𐑓𐑹𐑕 𐑩𐑑𐑨𐑗𐑥𐑩𐑯𐑑𐑕 𐑑 𐑚𐑰 𐑥𐑸𐑒𐑑 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "edit_federation.media_removal": "𐑕𐑑𐑮𐑦𐑐 𐑥𐑰𐑛𐑾", + "edit_federation.reject": "𐑮𐑦𐑡𐑧𐑒𐑑 𐑷𐑤 𐑨𐑒𐑑𐑦𐑝𐑦𐑑𐑦𐑟", + "edit_federation.save": "𐑕𐑱𐑝", + "edit_federation.success": "{host} 𐑓𐑧𐑛𐑼𐑱𐑖𐑩𐑯 𐑢𐑪𐑟 𐑳𐑐𐑛𐑱𐑑𐑩𐑛", + "edit_federation.unlisted": "𐑓𐑹𐑕 𐑐𐑴𐑕𐑑𐑕 𐑳𐑯𐑤𐑦𐑕𐑑𐑩𐑛", + "edit_profile.error": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑳𐑐𐑛𐑱𐑑 𐑓𐑱𐑤𐑛", + "edit_profile.fields.accepts_email_list_label": "𐑕𐑩𐑚𐑕𐑒𐑮𐑲𐑚 𐑑 𐑯𐑿𐑟𐑤𐑧𐑑𐑼", + "edit_profile.fields.avatar_label": "𐑨𐑝𐑩𐑑𐑸", + "edit_profile.fields.bio_label": "𐑚𐑲𐑴", + "edit_profile.fields.bio_placeholder": "𐑑𐑧𐑤 𐑳𐑕 𐑩𐑚𐑬𐑑 𐑘𐑹𐑕𐑧𐑤𐑓.", + "edit_profile.fields.bot_label": "𐑞𐑦𐑕 𐑦𐑟 𐑩 𐑚𐑪𐑑 𐑩𐑒𐑬𐑯𐑑", + "edit_profile.fields.discoverable_label": "𐑩𐑤𐑬 𐑩𐑒𐑬𐑯𐑑 𐑛𐑦𐑕𐑒𐑳𐑝𐑼𐑦", + "edit_profile.fields.display_name_label": "𐑛𐑦𐑕𐑐𐑤𐑱 𐑯𐑱𐑥", + "edit_profile.fields.display_name_placeholder": "𐑯𐑱𐑥", + "edit_profile.fields.header_label": "𐑣𐑧𐑛𐑼", + "edit_profile.fields.hide_network_label": "𐑣𐑲𐑛 𐑯𐑧𐑑𐑢𐑻𐑒", + "edit_profile.fields.locked_label": "𐑤𐑪𐑒 𐑩𐑒𐑬𐑯𐑑", + "edit_profile.fields.meta_fields.content_placeholder": "𐑒𐑪𐑯𐑑𐑧𐑯𐑑", + "edit_profile.fields.meta_fields.label_placeholder": "𐑤𐑱𐑚𐑩𐑤", + "edit_profile.fields.meta_fields_label": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑥𐑧𐑑𐑩𐑛𐑱𐑑𐑩", + "edit_profile.fields.stranger_notifications_label": "𐑚𐑤𐑪𐑒 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑓𐑮𐑪𐑥 strangers", + "edit_profile.fields.verified_display_name": "𐑝𐑧𐑮𐑦𐑓𐑲𐑛 𐑿𐑟𐑼𐑟 𐑥𐑱 𐑯𐑪𐑑 𐑳𐑐𐑛𐑱𐑑 𐑞𐑺 𐑛𐑦𐑕𐑐𐑤𐑱 𐑯𐑱𐑥", + "edit_profile.hints.accepts_email_list": "𐑪𐑐𐑑-𐑦𐑯 𐑑 𐑯𐑿𐑟 𐑯 𐑥𐑸𐑒𐑩𐑑𐑦𐑙 𐑳𐑐𐑛𐑱𐑑𐑕.", + "edit_profile.hints.avatar": "PNG, GIF 𐑹 JPG. 𐑢𐑦𐑤 𐑚𐑰 downscaled 𐑑 {size}", + "edit_profile.hints.bot": "𐑞𐑦𐑕 𐑩𐑒𐑬𐑯𐑑 𐑥𐑱𐑯𐑤𐑦 𐑐𐑼𐑓𐑹𐑥𐑟 𐑷𐑑𐑩𐑥𐑱𐑑𐑩𐑛 𐑨𐑒𐑖𐑩𐑯𐑟 𐑯 𐑥𐑲𐑑 𐑯𐑪𐑑 𐑚𐑰 𐑥𐑪𐑯𐑦𐑑𐑼𐑛", + "edit_profile.hints.discoverable": "𐑛𐑦𐑕𐑐𐑤𐑱 𐑩𐑒𐑬𐑯𐑑 𐑦𐑯 𐑐𐑮𐑴𐑓𐑲𐑤 𐑛𐑦𐑮𐑧𐑒𐑑𐑼𐑦 𐑯 𐑩𐑤𐑬 𐑦𐑯𐑛𐑧𐑒𐑕𐑦𐑙 𐑚𐑲 𐑦𐑒𐑕𐑑𐑻𐑯𐑩𐑤 𐑕𐑻𐑝𐑦𐑕𐑩𐑟", + "edit_profile.hints.header": "PNG, GIF 𐑹 JPG. 𐑢𐑦𐑤 𐑚𐑰 downscaled 𐑑 {size}", + "edit_profile.hints.hide_network": "𐑣𐑵 𐑿 𐑓𐑪𐑤𐑴 𐑯 𐑣𐑵 𐑓𐑪𐑤𐑴𐑟 𐑿 𐑢𐑦𐑤 𐑯𐑪𐑑 𐑚𐑰 𐑖𐑴𐑯 𐑪𐑯 𐑘𐑹 𐑐𐑮𐑴𐑓𐑲𐑤", + "edit_profile.hints.locked": "𐑮𐑦𐑒𐑢𐑲𐑼𐑟 𐑿 𐑑 𐑥𐑨𐑯𐑘𐑫𐑩𐑤𐑦 𐑩𐑐𐑮𐑵𐑝 𐑓𐑪𐑤𐑴𐑼𐑟", + "edit_profile.hints.meta_fields": "𐑿 𐑒𐑨𐑯 𐑣𐑨𐑝 𐑳𐑐 𐑑 {count, plural, one {# item} other {# items}} 𐑛𐑦𐑕𐑐𐑤𐑱𐑛 𐑨𐑟 𐑩 𐑑𐑱𐑚𐑩𐑤 𐑪𐑯 𐑘𐑹 𐑐𐑮𐑴𐑓𐑲𐑤", + "edit_profile.hints.stranger_notifications": "𐑴𐑯𐑤𐑦 𐑖𐑴 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑓𐑮𐑪𐑥 𐑐𐑰𐑐𐑩𐑤 𐑿 𐑓𐑪𐑤𐑴", + "edit_profile.meta_fields.add": "𐑨𐑛 𐑯𐑿 𐑲𐑑𐑩𐑥", + "edit_profile.save": "𐑕𐑱𐑝", + "edit_profile.success": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑕𐑱𐑝𐑛!", + "embed.instructions": " 𐑦𐑥𐑚𐑧𐑛 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑪𐑯 𐑘𐑹 𐑢𐑧𐑚𐑕𐑲𐑑 𐑚𐑲 𐑒𐑪𐑐𐑦𐑦𐑙 𐑞 𐑒𐑴𐑛 𐑚𐑦𐑤𐑴.", + "embed.preview": "𐑣𐑽 𐑦𐑟 𐑢𐑪𐑑 𐑦𐑑 𐑢𐑦𐑤 𐑤𐑫𐑒 𐑤𐑲𐑒:", + "emoji_button.activity": "𐑨𐑒𐑑𐑦𐑝𐑦𐑑𐑦", + "emoji_button.custom": "𐑒𐑳𐑕𐑑𐑩𐑥", + "emoji_button.flags": "𐑓𐑤𐑨𐑜𐑟", + "emoji_button.food": "𐑓𐑵𐑛 𐑯 𐑛𐑮𐑦𐑙𐑒", + "emoji_button.label": "𐑦𐑯𐑕𐑻𐑑 𐑦𐑥𐑴𐑡𐑦", + "emoji_button.nature": "𐑯𐑱𐑗𐑼", + "emoji_button.not_found": "𐑯𐑴 𐑦𐑥𐑴𐑡𐑦𐑟!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "𐑪𐑚𐑡𐑧𐑒𐑑𐑕", + "emoji_button.people": "𐑐𐑰𐑐𐑩𐑤", + "emoji_button.recent": "𐑓𐑮𐑰𐑒𐑢𐑩𐑯𐑑𐑤𐑦 𐑿𐑟𐑛", + "emoji_button.search": "𐑕𐑻𐑗...", + "emoji_button.search_results": "𐑕𐑻𐑗 𐑮𐑦𐑟𐑳𐑤𐑑𐑕", + "emoji_button.symbols": "𐑕𐑦𐑥𐑚𐑩𐑤𐑟", + "emoji_button.travel": "𐑑𐑮𐑨𐑝𐑩𐑤 𐑯 𐑐𐑤𐑱𐑕𐑩𐑟", + "empty_column.account_blocked": "𐑿 𐑸 𐑚𐑤𐑪𐑒𐑑 𐑚𐑲 @{accountUsername}.", + "empty_column.account_favourited_statuses": "𐑞𐑦𐑕 𐑿𐑟𐑼 𐑛𐑳𐑟𐑩𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑤𐑲𐑒𐑑 𐑐𐑴𐑕𐑑𐑕 𐑘𐑧𐑑.", + "empty_column.account_timeline": "𐑯𐑴 𐑐𐑴𐑕𐑑𐑕 𐑣𐑽!", + "empty_column.account_unavailable": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑳𐑯𐑩𐑝𐑱𐑤𐑩𐑚𐑩𐑤", + "empty_column.aliases": "𐑿 𐑣𐑨𐑝𐑩𐑯𐑑 𐑒𐑮𐑦𐑱𐑑𐑩𐑛 𐑧𐑯𐑦 𐑩𐑒𐑬𐑯𐑑 𐑱𐑤𐑾𐑕 𐑘𐑧𐑑.", + "empty_column.aliases.suggestions": "𐑞𐑺 𐑸 𐑯𐑴 𐑩𐑒𐑬𐑯𐑑 𐑕𐑩𐑡𐑧𐑕𐑗𐑩𐑯𐑟 available 𐑓 𐑞 𐑐𐑮𐑩𐑝𐑲𐑛𐑩𐑛 term.", + "empty_column.blocks": "𐑿 𐑣𐑨𐑝𐑩𐑯𐑑 𐑚𐑤𐑪𐑒𐑑 𐑧𐑯𐑦 𐑿𐑟𐑼𐑟 𐑘𐑧𐑑.", + "empty_column.bookmarks": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑚𐑫𐑒𐑥𐑸𐑒𐑕 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑨𐑛 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.community": "𐑞 𐑤𐑴𐑒𐑩𐑤 𐑑𐑲𐑥𐑤𐑲𐑯 𐑦𐑟 𐑧𐑥𐑐𐑑𐑦. 𐑮𐑲𐑑 𐑕𐑳𐑥𐑔𐑦𐑙 𐑐𐑳𐑚𐑤𐑦𐑒𐑤𐑦 𐑑 𐑜𐑧𐑑 𐑞 𐑚𐑷𐑤 𐑮𐑴𐑤𐑦𐑙!", + "empty_column.direct": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡𐑩𐑟 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑕𐑧𐑯𐑛 𐑹 𐑮𐑦𐑕𐑰𐑝 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.domain_blocks": "𐑞𐑺 𐑸 𐑯𐑴 𐑣𐑦𐑛𐑩𐑯 𐑛𐑴𐑥𐑱𐑯𐑟 𐑘𐑧𐑑.", + "empty_column.favourited_statuses": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑤𐑲𐑒𐑑 𐑐𐑴𐑕𐑑𐑕 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑤𐑲𐑒 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.favourites": "𐑯𐑴 𐑢𐑳𐑯 𐑣𐑨𐑟 𐑤𐑲𐑒𐑑 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑕𐑳𐑥𐑢𐑳𐑯 𐑛𐑳𐑟, 𐑞𐑱 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.filters": "𐑿 𐑣𐑨𐑝𐑩𐑯𐑑 𐑒𐑮𐑦𐑱𐑑𐑩𐑛 𐑧𐑯𐑦 𐑥𐑿𐑑𐑩𐑛 𐑢𐑻𐑛𐑟 𐑘𐑧𐑑.", + "empty_column.follow_recommendations": "𐑤𐑫𐑒𐑕 𐑤𐑲𐑒 𐑯𐑴 𐑕𐑩𐑡𐑧𐑕𐑗𐑩𐑯𐑟 𐑒𐑫𐑛 𐑚𐑰 𐑡𐑧𐑯𐑼𐑱𐑑𐑩𐑛 𐑓 𐑿. 𐑿 𐑒𐑨𐑯 𐑑𐑮𐑲 𐑿𐑟𐑦𐑙 𐑕𐑻𐑗 𐑑 𐑤𐑫𐑒 𐑓 𐑐𐑰𐑐𐑩𐑤 𐑿 𐑥𐑲𐑑 𐑯𐑴 𐑹 𐑦𐑒𐑕𐑐𐑤𐑹 𐑑𐑮𐑧𐑯𐑛𐑦𐑙 𐑣𐑨𐑖𐑑𐑨𐑜𐑟.", + "empty_column.follow_requests": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑕 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑮𐑦𐑕𐑰𐑝 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.group": "𐑞𐑺 𐑦𐑟 𐑯𐑳𐑔𐑦𐑙 𐑦𐑯 𐑞𐑦𐑕 𐑜𐑮𐑵𐑐 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑥𐑧𐑥𐑚𐑼𐑟 𐑝 𐑞𐑦𐑕 𐑜𐑮𐑵𐑐 𐑥𐑱𐑒 𐑯𐑿 𐑐𐑴𐑕𐑑𐑕, 𐑞𐑱 𐑢𐑦𐑤 𐑩𐑐𐑽 𐑣𐑽.", + "empty_column.hashtag": "𐑞𐑺 𐑦𐑟 𐑯𐑳𐑔𐑦𐑙 𐑦𐑯 𐑞𐑦𐑕 𐑣𐑨𐑖𐑑𐑨𐑜 𐑘𐑧𐑑.", + "empty_column.home": "𐑘𐑹 𐑣𐑴𐑥 𐑑𐑲𐑥𐑤𐑲𐑯 𐑦𐑟 𐑧𐑥𐑐𐑑𐑦! 𐑝𐑦𐑟𐑦𐑑 {public} 𐑑 𐑜𐑧𐑑 𐑕𐑑𐑸𐑑𐑩𐑛 𐑯 𐑥𐑰𐑑 𐑳𐑞𐑼 𐑿𐑟𐑼𐑟.", + "empty_column.home.local_tab": "𐑞 {site_title} tab", + "empty_column.list": "𐑞𐑺 𐑦𐑟 𐑯𐑳𐑔𐑦𐑙 𐑦𐑯 𐑞𐑦𐑕 𐑤𐑦𐑕𐑑 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑥𐑧𐑥𐑚𐑼𐑟 𐑝 𐑞𐑦𐑕 𐑤𐑦𐑕𐑑 𐑒𐑮𐑦𐑱𐑑 𐑯𐑿 𐑐𐑴𐑕𐑑𐑕, 𐑞𐑱 𐑢𐑦𐑤 𐑩𐑐𐑽 𐑣𐑽.", + "empty_column.lists": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑤𐑦𐑕𐑑𐑕 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑒𐑮𐑦𐑱𐑑 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.mutes": "𐑿 𐑣𐑨𐑝𐑩𐑯𐑑 𐑥𐑿𐑑𐑩𐑛 𐑧𐑯𐑦 𐑿𐑟𐑼𐑟 𐑘𐑧𐑑.", + "empty_column.notifications": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑘𐑧𐑑. 𐑦𐑯𐑑𐑼𐑨𐑒𐑑 𐑢𐑦𐑞 𐑳𐑞𐑼𐑟 𐑑 𐑕𐑑𐑸𐑑 𐑞 𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯.", + "empty_column.public": "𐑞𐑺 𐑦𐑟 𐑯𐑳𐑔𐑦𐑙 𐑣𐑽! 𐑮𐑲𐑑 𐑕𐑳𐑥𐑔𐑦𐑙 𐑐𐑳𐑚𐑤𐑦𐑒𐑤𐑦, 𐑹 𐑥𐑨𐑯𐑘𐑫𐑩𐑤𐑦 𐑓𐑪𐑤𐑴 𐑿𐑟𐑼𐑟 𐑓𐑮𐑪𐑥 𐑳𐑞𐑼 𐑕𐑻𐑝𐑼𐑟 𐑑 𐑓𐑦𐑤 𐑦𐑑 𐑳𐑐", + "empty_column.remote": "𐑞𐑺 𐑦𐑟 𐑯𐑳𐑔𐑦𐑙 𐑣𐑽! 𐑥𐑨𐑯𐑘𐑫𐑩𐑤𐑦 𐑓𐑪𐑤𐑴 𐑿𐑟𐑼𐑟 𐑓𐑮𐑪𐑥 {instance} 𐑑 𐑓𐑦𐑤 𐑦𐑑 𐑳𐑐.", + "empty_column.scheduled_statuses": "𐑿 𐑛𐑴𐑯𐑑 𐑣𐑨𐑝 𐑧𐑯𐑦 𐑖𐑧𐑡𐑵𐑤𐑛 𐑕𐑑𐑱𐑑𐑩𐑕𐑩𐑟 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑿 𐑨𐑛 𐑢𐑳𐑯, 𐑦𐑑 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "empty_column.search.accounts": "𐑞𐑺 𐑸 𐑯𐑴 𐑐𐑰𐑐𐑩𐑤 𐑮𐑦𐑟𐑳𐑤𐑑𐑕 𐑓 \"{term}\"", + "empty_column.search.hashtags": "𐑞𐑺 𐑸 𐑯𐑴 𐑣𐑨𐑖𐑑𐑨𐑜𐑟 𐑮𐑦𐑟𐑳𐑤𐑑𐑕 𐑓 \"{term}\"", + "empty_column.search.statuses": "𐑞𐑺 𐑸 𐑯𐑴 𐑐𐑴𐑕𐑑𐑕 𐑮𐑦𐑟𐑳𐑤𐑑𐑕 𐑓 \"{term}\"", + "export_data.actions.export": "𐑦𐑒𐑕𐑐𐑹𐑑", + "export_data.actions.export_blocks": "𐑦𐑒𐑕𐑐𐑹𐑑 𐑚𐑤𐑪𐑒𐑕", + "export_data.actions.export_follows": "𐑦𐑒𐑕𐑐𐑹𐑑 𐑓𐑪𐑤𐑴𐑟", + "export_data.actions.export_mutes": "𐑦𐑒𐑕𐑐𐑹𐑑 𐑥𐑿𐑑𐑕", + "export_data.blocks_label": "𐑚𐑤𐑪𐑒𐑕", + "export_data.follows_label": "𐑓𐑪𐑤𐑴𐑟", + "export_data.hints.blocks": "𐑜𐑧𐑑 𐑩 CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑚𐑤𐑪𐑒𐑑 𐑩𐑒𐑬𐑯𐑑𐑕", + "export_data.hints.follows": "𐑜𐑧𐑑 𐑩 CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑓𐑪𐑤𐑴𐑛 𐑩𐑒𐑬𐑯𐑑𐑕", + "export_data.hints.mutes": "𐑜𐑧𐑑 𐑩 CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑥𐑿𐑑𐑩𐑛 𐑩𐑒𐑬𐑯𐑑𐑕", + "export_data.mutes_label": "𐑥𐑿𐑑𐑕", + "export_data.success.blocks": "𐑚𐑤𐑪𐑒𐑕 𐑦𐑒𐑕𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "export_data.success.followers": "𐑓𐑪𐑤𐑴𐑼𐑟 𐑦𐑒𐑕𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "export_data.success.mutes": "𐑥𐑿𐑑𐑕 𐑦𐑒𐑕𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "federation_restriction.federated_timeline_removal": "·𐑓𐑧𐑛𐑦𐑝𐑻𐑕 𐑑𐑲𐑥𐑤𐑲𐑯 𐑮𐑦𐑥𐑵𐑝𐑩𐑤", + "federation_restriction.followers_only": "𐑣𐑦𐑛𐑩𐑯 𐑦𐑒𐑕𐑧𐑐𐑑 𐑑 𐑓𐑪𐑤𐑴𐑼𐑟", + "federation_restriction.full_media_removal": "𐑓𐑫𐑤 𐑥𐑰𐑛𐑾 𐑮𐑦𐑥𐑵𐑝𐑩𐑤", + "federation_restriction.media_nsfw": "𐑩𐑑𐑨𐑗𐑥𐑩𐑯𐑑𐑕 𐑥𐑸𐑒𐑑 ⸰𐑯𐑕𐑓𐑢", + "federation_restriction.partial_media_removal": "𐑐𐑸𐑖𐑩𐑤 𐑥𐑰𐑛𐑾 𐑮𐑦𐑥𐑵𐑝𐑩𐑤", + "federation_restrictions.empty_message": "{siteTitle} 𐑣𐑨𐑟 𐑯𐑪𐑑 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑑𐑩𐑛 𐑧𐑯𐑦 𐑦𐑯𐑕𐑑𐑩𐑯𐑕𐑩𐑟.", + "federation_restrictions.explanation_box.message": "𐑯𐑹𐑥𐑩𐑤𐑦 𐑕𐑻𐑝𐑼𐑟 𐑪𐑯 𐑞 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕 𐑒𐑨𐑯 𐑒𐑩𐑥𐑿𐑯𐑦𐑒𐑱𐑑 𐑓𐑮𐑰𐑤𐑦. {siteTitle} 𐑣𐑨𐑟 𐑦𐑥𐑐𐑴𐑟𐑛 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟 𐑪𐑯 𐑞 𐑓𐑪𐑤𐑴𐑦𐑙 𐑕𐑻𐑝𐑼𐑟.", + "federation_restrictions.explanation_box.title": "𐑦𐑯𐑕𐑑𐑩𐑯𐑕-specific policies", + "federation_restrictions.not_disclosed_message": "{siteTitle} 𐑛𐑳𐑟 𐑯𐑪𐑑 𐑛𐑦𐑕𐑒𐑤𐑴𐑟 𐑓𐑧𐑛𐑼𐑱𐑖𐑩𐑯 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟 𐑔𐑮𐑵 𐑞 API.", + "fediverse_tab.explanation_box.dismiss": "𐑛𐑴𐑯𐑑 𐑖𐑴 𐑩𐑜𐑱𐑯", + "fediverse_tab.explanation_box.explanation": "{site_title} 𐑦𐑟 𐑐𐑸𐑑 𐑝 𐑞 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕, 𐑩 𐑕𐑴𐑖𐑩𐑤 𐑯𐑧𐑑𐑢𐑻𐑒 𐑥𐑱𐑛 𐑳𐑐 𐑝 𐑔𐑬𐑟𐑩𐑯𐑛𐑟 𐑝 𐑦𐑯𐑛𐑦𐑐𐑧𐑯𐑛𐑩𐑯𐑑 𐑕𐑴𐑖𐑩𐑤 𐑥𐑰𐑛𐑾 𐑕𐑲𐑑𐑕 (aka \"𐑕𐑻𐑝𐑼𐑟\"). 𐑞 𐑐𐑴𐑕𐑑𐑕 𐑿 𐑕𐑰 𐑣𐑽 𐑸 𐑓𐑮𐑪𐑥 3rd-𐑐𐑸𐑑𐑦 𐑕𐑻𐑝𐑼𐑟. 𐑿 𐑣𐑨𐑝 𐑞 𐑓𐑮𐑰𐑛𐑩𐑥 𐑑 𐑦𐑯𐑜𐑱𐑡 𐑢𐑦𐑞 𐑞𐑧𐑥, 𐑹 𐑑 𐑚𐑤𐑪𐑒 𐑧𐑯𐑦 𐑕𐑻𐑝𐑼 𐑿 𐑛𐑴𐑯𐑑 𐑤𐑲𐑒. 𐑐𐑱 𐑩𐑑𐑧𐑯𐑖𐑩𐑯 𐑑 𐑞 𐑓𐑫𐑤 𐑿𐑟𐑼𐑯𐑱𐑥 𐑭𐑓𐑑𐑼 𐑞 𐑕𐑧𐑒𐑩𐑯𐑛 @ 𐑕𐑦𐑥𐑚𐑩𐑤 𐑑 𐑯𐑴 𐑢𐑦𐑗 𐑕𐑻𐑝𐑼 𐑩 𐑐𐑴𐑕𐑑 𐑦𐑟 𐑓𐑮𐑪𐑥. 𐑑 𐑕𐑰 𐑴𐑯𐑤𐑦 {site_title} 𐑐𐑴𐑕𐑑𐑕, 𐑝𐑦𐑟𐑦𐑑 {local}.", + "fediverse_tab.explanation_box.title": "𐑢𐑪𐑑 𐑦𐑟 𐑞 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕?", + "filters.added": "𐑓𐑦𐑤𐑑𐑼 𐑨𐑛𐑩𐑛.", + "filters.context_header": "𐑓𐑦𐑤𐑑𐑼 𐑒𐑪𐑯𐑑𐑧𐑒𐑕𐑑𐑕", + "filters.context_hint": "𐑢𐑳𐑯 𐑹 𐑥𐑳𐑤𐑑𐑦𐑐𐑩𐑤 𐑒𐑪𐑯𐑑𐑧𐑒𐑕𐑑𐑕 𐑢𐑺 𐑞 𐑓𐑦𐑤𐑑𐑼 𐑖𐑫𐑛 𐑩𐑐𐑤𐑲", + "filters.filters_list_context_label": "𐑓𐑦𐑤𐑑𐑼 𐑒𐑪𐑯𐑑𐑧𐑒𐑕𐑑𐑕:", + "filters.filters_list_delete": "𐑛𐑦𐑤𐑰𐑑", + "filters.filters_list_details_label": "𐑓𐑦𐑤𐑑𐑼 𐑕𐑧𐑑𐑦𐑙𐑟:", + "filters.filters_list_drop": "𐑛𐑮𐑪𐑐", + "filters.filters_list_hide": "𐑣𐑲𐑛", + "filters.filters_list_phrase_label": "𐑒𐑰𐑢𐑻𐑛 𐑹 𐑓𐑮𐑱𐑟:", + "filters.filters_list_whole-word": "𐑣𐑴𐑤 𐑢𐑻𐑛", + "filters.removed": "𐑓𐑦𐑤𐑑𐑼 𐑛𐑦𐑤𐑰𐑑𐑩𐑛.", + "follow_recommendations.done": "𐑛𐑳𐑯", + "follow_recommendations.heading": "𐑓𐑪𐑤𐑴 𐑐𐑰𐑐𐑩𐑤 𐑿𐑛 𐑤𐑲𐑒 𐑑 𐑕𐑰 𐑐𐑴𐑕𐑑𐑕 𐑓𐑮𐑪𐑥! 𐑣𐑽 𐑸 𐑕𐑳𐑥 𐑕𐑩𐑡𐑧𐑕𐑗𐑩𐑯𐑟.", + "follow_recommendations.lead": "𐑐𐑴𐑕𐑑𐑕 𐑓𐑮𐑪𐑥 𐑐𐑰𐑐𐑩𐑤 𐑿 𐑓𐑪𐑤𐑴 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑦𐑯 𐑒𐑮𐑪𐑯𐑩𐑤𐑪𐑡𐑦𐑒𐑩𐑤 𐑹𐑛𐑼 𐑪𐑯 𐑘𐑹 𐑣𐑴𐑥 𐑓𐑰𐑛. 𐑛𐑴𐑯𐑑 𐑚𐑰 𐑩𐑓𐑮𐑱𐑛 𐑑 𐑥𐑱𐑒 𐑥𐑦𐑕𐑑𐑱𐑒𐑕, 𐑿 𐑒𐑨𐑯 𐑳𐑯𐑓𐑪𐑤𐑴 𐑐𐑰𐑐𐑩𐑤 𐑡𐑳𐑕𐑑 𐑨𐑟 𐑰𐑟𐑦𐑤𐑦 𐑧𐑯𐑦 𐑑𐑲𐑥!", + "follow_request.authorize": "𐑷𐑔𐑼𐑲𐑟", + "follow_request.reject": "𐑮𐑦𐑡𐑧𐑒𐑑", + "forms.copy": "𐑒𐑪𐑐𐑦", + "forms.hide_password": "𐑣𐑲𐑛 𐑐𐑭𐑕𐑢𐑻𐑛", + "forms.show_password": "𐑖𐑴 𐑐𐑭𐑕𐑢𐑻𐑛", + "getting_started.open_source_notice": "{code_name} 𐑦𐑟 𐑴𐑐𐑩𐑯 𐑕𐑹𐑕 𐑕𐑪𐑓𐑑𐑢𐑺. 𐑿 𐑒𐑨𐑯 𐑒𐑩𐑯𐑑𐑮𐑦𐑚𐑿𐑑 𐑹 𐑮𐑦𐑐𐑹𐑑 𐑦𐑖𐑵𐑟 𐑨𐑑 {code_link} (v{code_version}).", + "group.detail.archived_group": "𐑸𐑒𐑲𐑝𐑛 𐑜𐑮𐑵𐑐", + "group.members.empty": "𐑞𐑦𐑕 𐑜𐑮𐑵𐑐 𐑛𐑳𐑟 𐑯𐑪𐑑 𐑣𐑨𐑟 𐑧𐑯𐑦 𐑥𐑧𐑥𐑚𐑼𐑟.", + "group.removed_accounts.empty": "𐑞𐑦𐑕 𐑜𐑮𐑵𐑐 𐑛𐑳𐑟 𐑯𐑪𐑑 𐑣𐑨𐑟 𐑧𐑯𐑦 𐑮𐑦𐑥𐑵𐑝𐑛 𐑩𐑒𐑬𐑯𐑑𐑕.", + "groups.card.join": "𐑡𐑶𐑯", + "groups.card.members": "𐑥𐑧𐑥𐑚𐑼𐑟", + "groups.card.roles.admin": "𐑘𐑫𐑼 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯", + "groups.card.roles.member": "𐑘𐑫𐑼 𐑩 𐑥𐑧𐑥𐑚𐑼", + "groups.card.view": "𐑝𐑿", + "groups.create": "𐑒𐑮𐑦𐑱𐑑 𐑜𐑮𐑵𐑐", + "groups.detail.role_admin": "𐑘𐑫𐑼 𐑩𐑯 𐑨𐑛𐑥𐑦𐑯", + "groups.edit": "𐑧𐑛𐑦𐑑", + "groups.form.coverImage": "𐑳𐑐𐑤𐑴𐑛 𐑯𐑿 𐑚𐑨𐑯𐑼 𐑦𐑥𐑦𐑡 (𐑪𐑐𐑖𐑩𐑯𐑩𐑤)", + "groups.form.coverImageChange": "𐑚𐑨𐑯𐑼 𐑦𐑥𐑦𐑡 𐑕𐑦𐑤𐑧𐑒𐑑𐑩𐑛", + "groups.form.create": "𐑒𐑮𐑦𐑱𐑑 𐑜𐑮𐑵𐑐", + "groups.form.description": "𐑛𐑦𐑕𐑒𐑮𐑦𐑐𐑖𐑩𐑯", + "groups.form.title": "𐑑𐑲𐑑𐑩𐑤", + "groups.form.update": "𐑳𐑐𐑛𐑱𐑑 𐑜𐑮𐑵𐑐", + "groups.join": "𐑡𐑶𐑯 𐑜𐑮𐑵𐑐", + "groups.leave": "𐑤𐑰𐑝 𐑜𐑮𐑵𐑐", + "groups.removed_accounts": "𐑮𐑦𐑥𐑵𐑝𐑛 𐑩𐑒𐑬𐑯𐑑𐑕", + "groups.sidebar-panel.item.no_recent_activity": "𐑯𐑴 𐑮𐑰𐑕𐑩𐑯𐑑 𐑨𐑒𐑑𐑦𐑝𐑦𐑑𐑦", + "groups.sidebar-panel.item.view": "𐑯𐑿 𐑐𐑴𐑕𐑑𐑕", + "groups.sidebar-panel.show_all": "𐑖𐑴 𐑷𐑤", + "groups.sidebar-panel.title": "𐑜𐑮𐑵𐑐𐑕 𐑘𐑫𐑼 𐑦𐑯", + "groups.tab_admin": "𐑥𐑨𐑯𐑦𐑡", + "groups.tab_featured": "𐑓𐑰𐑗𐑼𐑛", + "groups.tab_member": "𐑥𐑧𐑥𐑚𐑼", + "hashtag.column_header.tag_mode.all": "𐑯 {additional}", + "hashtag.column_header.tag_mode.any": "𐑹 {additional}", + "hashtag.column_header.tag_mode.none": "𐑢𐑦𐑞𐑬𐑑 {additional}", + "header.about.label": "𐑩𐑚𐑬𐑑", + "header.back_to.label": "𐑚𐑨𐑒 𐑑 {siteTitle}", + "header.home.label": "𐑣𐑴𐑥", + "header.login.label": "𐑤𐑪𐑜 𐑦𐑯", + "home.column_settings.show_direct": "𐑖𐑴 𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡𐑩𐑟", + "home.column_settings.show_reblogs": "𐑖𐑴 𐑮𐑰𐑐𐑴𐑕𐑑𐑕", + "home.column_settings.show_replies": "𐑖𐑴 𐑮𐑦𐑐𐑤𐑲𐑟", + "home.column_settings.title": "𐑣𐑴𐑥 𐑕𐑧𐑑𐑦𐑙𐑟", + "home_column.lists": "𐑤𐑦𐑕𐑑𐑕", + "home_column_header.all": "𐑷𐑤", + "home_column_header.fediverse": "·𐑓𐑧𐑛𐑦𐑝𐑻𐑕", + "home_column_header.home": "𐑣𐑴𐑥", + "icon_button.icons": "𐑲𐑒𐑪𐑯𐑟", + "icon_button.label": "𐑕𐑦𐑤𐑧𐑒𐑑 𐑲𐑒𐑪𐑯", + "icon_button.not_found": "𐑯𐑴 𐑲𐑒𐑪𐑯𐑟!! (╯°□°)╯︵ ┻━┻", + "import_data.actions.import": "𐑦𐑥𐑐𐑹𐑑", + "import_data.actions.import_blocks": "𐑦𐑥𐑐𐑹𐑑 𐑚𐑤𐑪𐑒𐑕", + "import_data.actions.import_follows": "𐑦𐑥𐑐𐑹𐑑 𐑓𐑪𐑤𐑴𐑟", + "import_data.actions.import_mutes": "𐑦𐑥𐑐𐑹𐑑 𐑥𐑿𐑑𐑕", + "import_data.blocks_label": "𐑚𐑤𐑪𐑒𐑕", + "import_data.follows_label": "𐑓𐑪𐑤𐑴𐑟", + "import_data.hints.blocks": "CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑚𐑤𐑪𐑒𐑑 𐑩𐑒𐑬𐑯𐑑𐑕", + "import_data.hints.follows": "CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑓𐑪𐑤𐑴𐑛 𐑩𐑒𐑬𐑯𐑑𐑕", + "import_data.hints.mutes": "CSV 𐑓𐑲𐑤 𐑒𐑩𐑯𐑑𐑱𐑯𐑦𐑙 𐑩 𐑤𐑦𐑕𐑑 𐑝 𐑥𐑿𐑑𐑩𐑛 𐑩𐑒𐑬𐑯𐑑𐑕", + "import_data.mutes_label": "𐑥𐑿𐑑𐑕", + "import_data.success.blocks": "𐑚𐑤𐑪𐑒𐑕 𐑦𐑥𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "import_data.success.followers": "𐑓𐑪𐑤𐑴𐑼𐑟 𐑦𐑥𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "import_data.success.mutes": "𐑥𐑿𐑑𐑕 𐑦𐑥𐑐𐑹𐑑𐑩𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦", + "intervals.full.days": "{number, plural, one {# day} other {# days}}", + "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", + "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "introduction.federation.action": "𐑯𐑧𐑒𐑕𐑑", + "introduction.federation.home.headline": "𐑣𐑴𐑥", + "introduction.federation.home.text": "𐑐𐑴𐑕𐑑𐑕 𐑓𐑮𐑪𐑥 𐑐𐑰𐑐𐑩𐑤 𐑿 𐑓𐑪𐑤𐑴 𐑢𐑦𐑤 𐑩𐑐𐑽 𐑦𐑯 𐑘𐑹 𐑣𐑴𐑥 𐑓𐑰𐑛. 𐑿 𐑒𐑨𐑯 𐑓𐑪𐑤𐑴 𐑧𐑯𐑦𐑢𐑳𐑯 𐑪𐑯 𐑧𐑯𐑦 𐑕𐑻𐑝𐑼!", + "introduction.interactions.action": "Finish tutorial!", + "introduction.interactions.favourite.headline": "𐑓𐑱𐑝𐑼𐑦𐑑", + "introduction.interactions.favourite.text": "𐑿 𐑒𐑨𐑯 𐑕𐑱𐑝 𐑩 𐑐𐑴𐑕𐑑 𐑓 𐑤𐑱𐑑𐑼, 𐑯 let 𐑞 𐑷𐑔𐑼 𐑯𐑴 𐑞𐑨𐑑 𐑿 𐑤𐑲𐑒𐑑 𐑦𐑑, 𐑚𐑲 𐑓𐑱𐑝𐑼𐑦𐑑𐑦𐑙 𐑦𐑑.", + "introduction.interactions.reblog.headline": "𐑮𐑰𐑐𐑴𐑕𐑑", + "introduction.interactions.reblog.text": "𐑿 𐑒𐑨𐑯 𐑖𐑺 𐑳𐑞𐑼 𐑐𐑰𐑐𐑩𐑤𐑟 𐑐𐑴𐑕𐑑𐑕 𐑢𐑦𐑞 𐑘𐑹 𐑓𐑪𐑤𐑴𐑼𐑟 𐑚𐑲 𐑮𐑰𐑐𐑴𐑕𐑑𐑦𐑙 𐑞𐑧𐑥.", + "introduction.interactions.reply.headline": "𐑮𐑦𐑐𐑤𐑲", + "introduction.interactions.reply.text": "𐑿 𐑒𐑨𐑯 𐑮𐑦𐑐𐑤𐑲 𐑑 𐑳𐑞𐑼 𐑐𐑰𐑐𐑩𐑤𐑟 𐑯 𐑘𐑹 𐑴𐑯 𐑐𐑴𐑕𐑑𐑕, 𐑢𐑦𐑗 𐑢𐑦𐑤 chain 𐑞𐑧𐑥 𐑑𐑩𐑜𐑧𐑞𐑼 𐑦𐑯 𐑩 𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯.", + "introduction.welcome.action": "𐑤𐑧𐑑𐑕 𐑜𐑴!", + "introduction.welcome.headline": "𐑓𐑻𐑕𐑑 𐑕𐑑𐑧𐑐𐑕", + "introduction.welcome.text": "𐑢𐑧𐑤𐑒𐑩𐑥 𐑑 𐑞 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕! 𐑦𐑯 𐑩 𐑓𐑿 𐑥𐑴𐑥𐑩𐑯𐑑𐑕, 𐑿𐑤 𐑚𐑰 𐑱𐑚𐑩𐑤 𐑑 𐑚𐑮𐑷𐑛𐑒𐑭𐑕𐑑 𐑥𐑧𐑕𐑦𐑡𐑩𐑟 𐑯 𐑑𐑷𐑒 𐑑 𐑘𐑹 𐑓𐑮𐑧𐑯𐑛𐑟 𐑩𐑒𐑮𐑪𐑕 𐑩 𐑢𐑲𐑛 𐑝𐑼𐑲𐑩𐑑𐑦 𐑝 𐑕𐑻𐑝𐑼𐑟. 𐑚𐑳𐑑 𐑞𐑦𐑕 𐑕𐑻𐑝𐑼, {domain}, 𐑦𐑟 special—it 𐑣𐑴𐑕𐑑𐑕 𐑘𐑹 𐑐𐑮𐑴𐑓𐑲𐑤, so 𐑮𐑦𐑥𐑧𐑥𐑚𐑼 𐑦𐑑𐑕 𐑯𐑱𐑥.", + "keyboard_shortcuts.back": "𐑑 𐑯𐑨𐑝𐑦𐑜𐑱𐑑 𐑚𐑨𐑒", + "keyboard_shortcuts.blocked": "𐑑 𐑴𐑐𐑩𐑯 𐑚𐑤𐑪𐑒𐑑 𐑿𐑟𐑼𐑟 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.boost": "𐑑 𐑮𐑰𐑐𐑴𐑕𐑑", + "keyboard_shortcuts.compose": "𐑑 𐑓𐑴𐑒𐑩𐑕 𐑞 𐑒𐑩𐑥𐑐𐑴𐑟 𐑑𐑧𐑒𐑕𐑑𐑺𐑾", + "keyboard_shortcuts.down": "𐑑 𐑥𐑵𐑝 𐑛𐑬𐑯 𐑦𐑯 𐑞 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.enter": "𐑑 𐑴𐑐𐑩𐑯 𐑐𐑴𐑕𐑑", + "keyboard_shortcuts.favourite": "𐑑 𐑤𐑲𐑒", + "keyboard_shortcuts.favourites": "𐑑 𐑴𐑐𐑩𐑯 𐑤𐑲𐑒𐑕 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.heading": "𐑒𐑰𐑚𐑹𐑛 𐑖𐑹𐑑𐑒𐑳𐑑𐑕", + "keyboard_shortcuts.home": "𐑑 𐑴𐑐𐑩𐑯 𐑣𐑴𐑥 𐑑𐑲𐑥𐑤𐑲𐑯", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "𐑑 𐑛𐑦𐑕𐑐𐑤𐑱 𐑞𐑦𐑕 legend", + "keyboard_shortcuts.mention": "𐑑 𐑥𐑧𐑯𐑖𐑩𐑯 𐑷𐑔𐑼", + "keyboard_shortcuts.muted": "𐑑 𐑴𐑐𐑩𐑯 𐑥𐑿𐑑𐑩𐑛 𐑿𐑟𐑼𐑟 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.my_profile": "𐑑 𐑴𐑐𐑩𐑯 𐑘𐑹 𐑐𐑮𐑴𐑓𐑲𐑤", + "keyboard_shortcuts.notifications": "𐑑 𐑴𐑐𐑩𐑯 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑒𐑪𐑤𐑩𐑥", + "keyboard_shortcuts.open_media": "𐑑 𐑴𐑐𐑩𐑯 𐑥𐑰𐑛𐑾", + "keyboard_shortcuts.pinned": "𐑑 𐑴𐑐𐑩𐑯 𐑐𐑦𐑯𐑛 𐑐𐑴𐑕𐑑𐑕 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.profile": "𐑑 𐑴𐑐𐑩𐑯 𐑷𐑔𐑼𐑟 𐑐𐑮𐑴𐑓𐑲𐑤", + "keyboard_shortcuts.react": "𐑑 𐑮𐑦𐑨𐑒𐑑", + "keyboard_shortcuts.reply": "𐑑 𐑮𐑦𐑐𐑤𐑲", + "keyboard_shortcuts.requests": "𐑑 𐑴𐑐𐑩𐑯 𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑕 𐑤𐑦𐑕𐑑", + "keyboard_shortcuts.search": "𐑑 𐑓𐑴𐑒𐑩𐑕 𐑕𐑻𐑗", + "keyboard_shortcuts.toggle_hidden": "𐑑 𐑖𐑴/𐑣𐑲𐑛 𐑑𐑧𐑒𐑕𐑑 behind CW", + "keyboard_shortcuts.toggle_sensitivity": "𐑑 𐑖𐑴/𐑣𐑲𐑛 𐑥𐑰𐑛𐑾", + "keyboard_shortcuts.toot": "𐑑 𐑕𐑑𐑸𐑑 𐑩 𐑯𐑿 𐑐𐑴𐑕𐑑", + "keyboard_shortcuts.unfocus": "𐑑 𐑳𐑯-𐑓𐑴𐑒𐑩𐑕 𐑒𐑩𐑥𐑐𐑴𐑟 𐑑𐑧𐑒𐑕𐑑𐑺𐑾/𐑕𐑻𐑗", + "keyboard_shortcuts.up": "𐑑 𐑥𐑵𐑝 𐑳𐑐 𐑦𐑯 𐑞 𐑤𐑦𐑕𐑑", + "lightbox.close": "𐑒𐑤𐑴𐑟", + "lightbox.next": "𐑯𐑧𐑒𐑕𐑑", + "lightbox.previous": "𐑐𐑮𐑰𐑝𐑾𐑕", + "lightbox.view_context": "𐑝𐑿 𐑒𐑪𐑯𐑑𐑧𐑒𐑕𐑑", + "list.click_to_add": "𐑒𐑤𐑦𐑒 𐑣𐑽 𐑑 𐑨𐑛 𐑐𐑰𐑐𐑩𐑤", + "list.label": "𐑕𐑦𐑤𐑧𐑒𐑑 𐑤𐑦𐑕𐑑…", + "list.select": "𐑕𐑦𐑤𐑧𐑒𐑑 𐑤𐑦𐑕𐑑", + "list_adder.header_title": "𐑨𐑛 𐑹 𐑮𐑦𐑥𐑵𐑝 𐑓𐑮𐑪𐑥 𐑤𐑦𐑕𐑑𐑕", + "lists.account.add": "𐑨𐑛 𐑑 𐑤𐑦𐑕𐑑", + "lists.account.remove": "𐑮𐑦𐑥𐑵𐑝 𐑓𐑮𐑪𐑥 𐑤𐑦𐑕𐑑", + "lists.edit": "𐑧𐑛𐑦𐑑 𐑤𐑦𐑕𐑑", + "lists.edit.submit": "𐑗𐑱𐑯𐑡 𐑑𐑲𐑑𐑩𐑤", + "lists.new.create": "𐑨𐑛 𐑤𐑦𐑕𐑑", + "lists.new.create_title": "𐑒𐑮𐑦𐑱𐑑", + "lists.new.save_title": "𐑕𐑱𐑝 𐑑𐑲𐑑𐑩𐑤", + "lists.new.title_placeholder": "𐑯𐑿 𐑤𐑦𐑕𐑑 𐑑𐑲𐑑𐑩𐑤", + "lists.search": "𐑕𐑻𐑗 𐑩𐑥𐑳𐑙 𐑐𐑰𐑐𐑩𐑤 𐑿 𐑓𐑪𐑤𐑴", + "lists.subheading": "𐑘𐑹 𐑤𐑦𐑕𐑑𐑕", + "loading_indicator.label": "𐑤𐑴𐑛𐑦𐑙...", + "login.fields.instance_label": "𐑦𐑯𐑕𐑑𐑩𐑯𐑕", + "login.fields.instance_placeholder": "example.com", + "login.fields.otp_code_hint": "𐑧𐑯𐑑𐑼 𐑞 two-factor 𐑒𐑴𐑛 𐑡𐑧𐑯𐑼𐑱𐑑𐑩𐑛 𐑚𐑲 𐑘𐑹 𐑓𐑴𐑯 𐑨𐑐 𐑹 𐑿𐑕 𐑢𐑳𐑯 𐑝 𐑘𐑹 𐑮𐑦𐑒𐑳𐑝𐑼𐑦 𐑒𐑴𐑛𐑟", + "login.fields.otp_code_label": "Two-factor 𐑒𐑴𐑛:", + "login.fields.password_placeholder": "𐑐𐑭𐑕𐑢𐑻𐑛", + "login.fields.username_placeholder": "𐑿𐑟𐑼𐑯𐑱𐑥", + "login.log_in": "𐑤𐑪𐑜 𐑦𐑯", + "login.otp_log_in": "OTP 𐑤𐑪𐑜𐑦𐑯", + "login.otp_log_in.fail": "𐑦𐑯𐑝𐑨𐑤𐑦𐑛 𐑒𐑴𐑛, 𐑐𐑤𐑰𐑟 𐑑𐑮𐑲 𐑩𐑜𐑱𐑯.", + "login.reset_password_hint": "𐑑𐑮𐑳𐑚𐑩𐑤 𐑤𐑪𐑜𐑦𐑙 𐑦𐑯?", + "media_gallery.toggle_visible": "𐑑𐑪𐑜𐑩𐑤 𐑝𐑦𐑟𐑩𐑚𐑦𐑤𐑦𐑑𐑦", + "media_panel.empty_message": "𐑯𐑴 𐑥𐑰𐑛𐑾 𐑓𐑬𐑯𐑛.", + "media_panel.title": "𐑥𐑰𐑛𐑾", + "mfa.mfa_disable_enter_password": "𐑧𐑯𐑑𐑼 𐑘𐑹 𐑒𐑳𐑮𐑩𐑯𐑑 𐑐𐑭𐑕𐑢𐑻𐑛 𐑑 𐑛𐑦𐑕𐑱𐑚𐑩𐑤 two-factor auth.", + "mfa.mfa_setup_enter_password": "𐑧𐑯𐑑𐑼 𐑘𐑹 𐑒𐑳𐑮𐑩𐑯𐑑 𐑐𐑭𐑕𐑢𐑻𐑛 𐑑 𐑒𐑩𐑯𐑓𐑻𐑥 𐑘𐑹 𐑲𐑛𐑧𐑯𐑑𐑦𐑑𐑦", + "mfa.mfa_setup_scan_description": "𐑿𐑟𐑦𐑙 𐑘𐑹 two-factor 𐑨𐑐, 𐑕𐑒𐑨𐑯 𐑞𐑦𐑕 QR 𐑒𐑴𐑛 𐑹 𐑧𐑯𐑑𐑼 𐑞 𐑑𐑧𐑒𐑕𐑑 𐑒𐑰.", + "mfa.mfa_setup_scan_key": "𐑒𐑰:", + "mfa.mfa_setup_scan_title": "𐑕𐑒𐑨𐑯", + "mfa.mfa_setup_verify_description": "𐑑 𐑦𐑯𐑱𐑚𐑩𐑤 two-factor 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯, 𐑧𐑯𐑑𐑼 𐑞 𐑒𐑴𐑛 𐑓𐑮𐑪𐑥 𐑘𐑹 two-factor 𐑨𐑐", + "mfa.mfa_setup_verify_title": "𐑝𐑧𐑮𐑦𐑓𐑲", + "mfa.otp_enabled_description": "𐑿 𐑣𐑨𐑝 𐑦𐑯𐑱𐑚𐑩𐑤𐑛 two-factor 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯 via OTP.", + "mfa.otp_enabled_title": "OTP 𐑦𐑯𐑱𐑚𐑩𐑤𐑛", + "mfa.setup_hint": "𐑓𐑪𐑤𐑴 𐑞𐑰𐑟 𐑕𐑑𐑧𐑐𐑕 𐑑 𐑕𐑧𐑑 𐑳𐑐 𐑥𐑳𐑤𐑑𐑦-𐑓𐑨𐑒𐑑𐑼 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯 𐑪𐑯 𐑘𐑹 𐑩𐑒𐑬𐑯𐑑 𐑢𐑦𐑞 OTP", + "mfa.setup_otp_title": "OTP 𐑛𐑦𐑕𐑱𐑚𐑩𐑤𐑛", + "mfa.setup_recoverycodes": "𐑮𐑦𐑒𐑳𐑝𐑼𐑦 𐑒𐑴𐑛𐑟", + "mfa.setup_warning": "𐑮𐑲𐑑 𐑞𐑰𐑟 𐑒𐑴𐑛𐑟 𐑛𐑬𐑯 𐑹 𐑕𐑱𐑝 𐑞𐑧𐑥 𐑕𐑳𐑥𐑢𐑺 𐑕𐑦𐑒𐑘𐑫𐑼 - 𐑳𐑞𐑼𐑢𐑲𐑟 𐑿 𐑢𐑴𐑯𐑑 𐑕𐑰 𐑞𐑧𐑥 𐑩𐑜𐑱𐑯. 𐑦𐑓 𐑿 𐑤𐑵𐑟 𐑨𐑒𐑕𐑧𐑕 𐑑 𐑘𐑹 2FA 𐑨𐑐 𐑯 𐑮𐑦𐑒𐑳𐑝𐑼𐑦 𐑒𐑴𐑛𐑟 𐑿𐑤 𐑚𐑰 𐑤𐑪𐑒𐑑 𐑬𐑑 𐑝 𐑘𐑹 𐑩𐑒𐑬𐑯𐑑.", + "missing_description_modal.cancel": "𐑒𐑨𐑯𐑕𐑩𐑤", + "missing_description_modal.continue": "𐑐𐑴𐑕𐑑", + "missing_description_modal.text": "𐑿 𐑣𐑨𐑝 𐑯𐑪𐑑 𐑧𐑯𐑑𐑼𐑛 𐑩 𐑛𐑦𐑕𐑒𐑮𐑦𐑐𐑖𐑩𐑯 𐑓 𐑷𐑤 𐑩𐑑𐑨𐑗𐑥𐑩𐑯𐑑𐑕. 𐑒𐑩𐑯𐑑𐑦𐑯𐑿 𐑧𐑯𐑦𐑢𐑱?", + "missing_indicator.label": "𐑯𐑪𐑑 𐑓𐑬𐑯𐑛", + "missing_indicator.sublabel": "𐑞𐑦𐑕 𐑮𐑦𐑟𐑹𐑕 𐑒𐑫𐑛 𐑯𐑪𐑑 𐑚𐑰 𐑓𐑬𐑯𐑛", + "morefollows.followers_label": "…𐑯 {count} 𐑥𐑹 {count, plural, one {follower} other {followers}} 𐑪𐑯 𐑮𐑦𐑥𐑴𐑑 𐑕𐑲𐑑𐑕.", + "morefollows.following_label": "…𐑯 {count} 𐑥𐑹 {count, plural, one {follow} other {follows}} 𐑪𐑯 𐑮𐑦𐑥𐑴𐑑 𐑕𐑲𐑑𐑕.", + "mute_modal.hide_notifications": "𐑣𐑲𐑛 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟 𐑓𐑮𐑪𐑥 𐑞𐑦𐑕 𐑿𐑟𐑼?", + "navigation.chats": "𐑗𐑨𐑑𐑕", + "navigation.dashboard": "𐑛𐑨𐑖𐑚𐑹𐑛", + "navigation.developers": "𐑛𐑦𐑝𐑧𐑤𐑩𐑐𐑼𐑟", + "navigation.direct_messages": "𐑥𐑧𐑕𐑦𐑡𐑩𐑟", + "navigation.home": "𐑣𐑴𐑥", + "navigation.invites": "𐑦𐑯𐑝𐑲𐑑𐑕", + "navigation.notifications": "𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "navigation.search": "𐑕𐑻𐑗", + "navigation_bar.account_aliases": "𐑩𐑒𐑬𐑯𐑑 𐑱𐑤𐑾𐑕𐑩𐑟", + "navigation_bar.admin_settings": "AdminFE", + "navigation_bar.blocks": "𐑚𐑤𐑪𐑒𐑕", + "navigation_bar.bookmarks": "𐑚𐑫𐑒𐑥𐑸𐑒𐑕", + "navigation_bar.compose": "𐑒𐑩𐑥𐑐𐑴𐑟 𐑯𐑿 𐑐𐑴𐑕𐑑", + "navigation_bar.compose_direct": "𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡", + "navigation_bar.compose_reply": "𐑮𐑦𐑐𐑤𐑲 𐑑 𐑐𐑴𐑕𐑑", + "navigation_bar.domain_blocks": "𐑛𐑴𐑥𐑱𐑯 𐑚𐑤𐑪𐑒𐑕", + "navigation_bar.export_data": "𐑦𐑒𐑕𐑐𐑹𐑑 𐑛𐑱𐑑𐑩", + "navigation_bar.favourites": "𐑤𐑲𐑒𐑕", + "navigation_bar.filters": "𐑓𐑦𐑤𐑑𐑼𐑟", + "navigation_bar.follow_requests": "𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑕", + "navigation_bar.import_data": "𐑦𐑥𐑐𐑹𐑑 𐑛𐑱𐑑𐑩", + "navigation_bar.in_reply_to": "In 𐑮𐑦𐑐𐑤𐑲 to", + "navigation_bar.info": "𐑩𐑚𐑬𐑑 𐑞𐑦𐑕 𐑕𐑻𐑝𐑼", + "navigation_bar.invites": "𐑦𐑯𐑝𐑲𐑑𐑕", + "navigation_bar.keyboard_shortcuts": "𐑣𐑪𐑑𐑒𐑰𐑟", + "navigation_bar.lists": "𐑤𐑦𐑕𐑑𐑕", + "navigation_bar.logout": " 𐑤𐑪𐑜𐑬𐑑", + "navigation_bar.messages": "𐑥𐑧𐑕𐑦𐑡𐑩𐑟", + "navigation_bar.mutes": "𐑥𐑿𐑑𐑕", + "navigation_bar.pins": "𐑐𐑦𐑯𐑛 𐑐𐑴𐑕𐑑𐑕", + "navigation_bar.preferences": "𐑐𐑮𐑧𐑓𐑼𐑩𐑯𐑕𐑩𐑟", + "navigation_bar.profile_directory": "𐑐𐑮𐑴𐑓𐑲𐑤 𐑛𐑦𐑮𐑧𐑒𐑑𐑼𐑦", + "navigation_bar.security": "𐑕𐑦𐑒𐑘𐑫𐑼𐑦𐑑𐑦", + "navigation_bar.soapbox_config": "·𐑕𐑴𐑐𐑚𐑪𐑒𐑕 𐑒𐑩𐑯𐑓𐑦𐑜", + "notification.chat_mention": "{name} 𐑕𐑧𐑯𐑑 𐑿 𐑩 𐑥𐑧𐑕𐑦𐑡", + "notification.favourite": "{name} 𐑤𐑲𐑒𐑑 𐑘𐑹 𐑐𐑴𐑕𐑑", + "notification.follow": "{name} 𐑓𐑪𐑤𐑴𐑛 𐑿", + "notification.follow_request": "{name} 𐑣𐑨𐑟 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑩𐑛 𐑑 𐑓𐑪𐑤𐑴 𐑿", + "notification.mention": "{name} 𐑥𐑧𐑯𐑖𐑩𐑯𐑛 𐑿", + "notification.move": "{name} 𐑥𐑵𐑝𐑛 𐑑 {targetName}", + "notification.pleroma:emoji_reaction": "{name} 𐑮𐑦𐑨𐑒𐑑𐑩𐑛 𐑑 𐑘𐑹 𐑐𐑴𐑕𐑑", + "notification.poll": "A 𐑐𐑴𐑤 𐑿 𐑣𐑨𐑝 𐑝𐑴𐑑𐑩𐑛 𐑦𐑯 𐑣𐑨𐑟 𐑧𐑯𐑛𐑩𐑛", + "notification.reblog": "{name} 𐑮𐑰𐑐𐑴𐑕𐑑𐑩𐑛 𐑘𐑹 𐑐𐑴𐑕𐑑", + "notifications.clear": "𐑒𐑤𐑽 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "notifications.clear_confirmation": "𐑸 𐑿 𐑖𐑫𐑼 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑐𐑻𐑥𐑩𐑯𐑩𐑯𐑑𐑤𐑦 𐑒𐑤𐑽 𐑷𐑤 𐑘𐑹 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟?", + "notifications.column_settings.alert": "𐑛𐑧𐑕𐑒𐑑𐑪𐑐 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "notifications.column_settings.emoji_react": "𐑦𐑥𐑴𐑡𐑦 𐑮𐑦𐑨𐑒𐑑𐑕:", + "notifications.column_settings.favourite": "𐑤𐑲𐑒𐑕:", + "notifications.column_settings.filter_bar.advanced": "𐑛𐑦𐑕𐑐𐑤𐑱 𐑷𐑤 𐑒𐑨𐑑𐑩𐑜𐑼𐑦𐑟", + "notifications.column_settings.filter_bar.category": "𐑒𐑢𐑦𐑒 𐑓𐑦𐑤𐑑𐑼 𐑚𐑸", + "notifications.column_settings.filter_bar.show": "𐑖𐑴", + "notifications.column_settings.follow": "𐑯𐑿 𐑓𐑪𐑤𐑴𐑼𐑟:", + "notifications.column_settings.follow_request": "𐑯𐑿 𐑓𐑪𐑤𐑴 𐑮𐑦𐑒𐑢𐑧𐑕𐑑𐑕:", + "notifications.column_settings.mention": "𐑥𐑧𐑯𐑖𐑩𐑯𐑟:", + "notifications.column_settings.move": "𐑥𐑵𐑝𐑟:", + "notifications.column_settings.poll": "𐑐𐑴𐑤 𐑮𐑦𐑟𐑳𐑤𐑑𐑕:", + "notifications.column_settings.push": "𐑐𐑫𐑖 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "notifications.column_settings.reblog": "𐑮𐑰𐑐𐑴𐑕𐑑𐑕:", + "notifications.column_settings.show": "𐑖𐑴 𐑦𐑯 𐑒𐑪𐑤𐑩𐑥", + "notifications.column_settings.sound": "𐑐𐑤𐑱 𐑕𐑬𐑯𐑛", + "notifications.column_settings.sounds": "𐑕𐑬𐑯𐑛𐑟", + "notifications.column_settings.sounds.all_sounds": "𐑐𐑤𐑱 𐑕𐑬𐑯𐑛 𐑓 𐑷𐑤 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "notifications.column_settings.title": "𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯 𐑕𐑧𐑑𐑦𐑙𐑟", + "notifications.filter.all": "𐑷𐑤", + "notifications.filter.boosts": "𐑮𐑰𐑐𐑴𐑕𐑑𐑕", + "notifications.filter.emoji_reacts": "𐑦𐑥𐑴𐑡𐑦 𐑮𐑦𐑨𐑒𐑑𐑕", + "notifications.filter.favourites": "𐑤𐑲𐑒𐑕", + "notifications.filter.follows": "𐑓𐑪𐑤𐑴𐑟", + "notifications.filter.mentions": "𐑥𐑧𐑯𐑖𐑩𐑯𐑟", + "notifications.filter.moves": "𐑥𐑵𐑝𐑟", + "notifications.filter.polls": "𐑐𐑴𐑤 𐑮𐑦𐑟𐑳𐑤𐑑𐑕", + "notifications.group": "{count} 𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "notifications.queue_label": "𐑒𐑤𐑦𐑒 𐑑 𐑕𐑰 {count} 𐑯𐑿 {count, plural, one {notification} other {notifications}}", + "password_reset.confirmation": "𐑗𐑧𐑒 𐑘𐑹 𐑰𐑥𐑱𐑤 𐑓 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯.", + "password_reset.fields.username_placeholder": "𐑰𐑥𐑱𐑤 𐑹 𐑿𐑟𐑼𐑯𐑱𐑥", + "password_reset.reset": "𐑮𐑰𐑕𐑧𐑑 𐑐𐑭𐑕𐑢𐑻𐑛", + "pinned_statuses.none": "𐑯𐑴 𐑐𐑦𐑯𐑟 𐑑 𐑖𐑴.", + "poll.closed": "𐑒𐑤𐑴𐑟𐑛", + "poll.refresh": "𐑮𐑦𐑓𐑮𐑧𐑖", + "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", + "poll.vote": "𐑝𐑴𐑑", + "poll.voted": "𐑿 𐑝𐑴𐑑𐑩𐑛 𐑓 𐑞𐑦𐑕 answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", + "poll_button.add_poll": "𐑨𐑛 𐑩 𐑐𐑴𐑤", + "poll_button.remove_poll": "𐑮𐑦𐑥𐑵𐑝 𐑐𐑴𐑤", + "preferences.fields.auto_play_gif_label": "𐑷𐑑𐑴-𐑐𐑤𐑱 𐑨𐑯𐑦𐑥𐑱𐑑𐑩𐑛 GIFs", + "preferences.fields.autoload_more_label": "𐑷𐑑𐑩𐑥𐑨𐑑𐑦𐑒𐑤𐑦 𐑤𐑴𐑛 𐑥𐑹 𐑲𐑑𐑩𐑥𐑟 𐑢𐑧𐑯 scrolled 𐑑 𐑞 𐑚𐑪𐑑𐑩𐑥 𐑝 𐑞 𐑐𐑱𐑡", + "preferences.fields.autoload_timelines_label": "𐑷𐑑𐑩𐑥𐑨𐑑𐑦𐑒𐑤𐑦 𐑤𐑴𐑛 𐑯𐑿 𐑐𐑴𐑕𐑑𐑕 𐑢𐑧𐑯 scrolled 𐑑 𐑞 𐑑𐑪𐑐 𐑝 𐑞 𐑐𐑱𐑡", + "preferences.fields.boost_modal_label": "𐑖𐑴 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑛𐑲𐑩𐑤𐑪𐑜 𐑚𐑦𐑓𐑹 𐑮𐑰𐑐𐑴𐑕𐑑𐑦𐑙", + "preferences.fields.content_type_label": "𐑐𐑴𐑕𐑑 format", + "preferences.fields.delete_modal_label": "𐑖𐑴 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑛𐑲𐑩𐑤𐑪𐑜 𐑚𐑦𐑓𐑹 𐑛𐑦𐑤𐑰𐑑𐑦𐑙 𐑩 𐑐𐑴𐑕𐑑", + "preferences.fields.demetricator_label": "𐑿𐑕 Demetricator", + "preferences.fields.developer_label": "𐑛𐑦𐑝𐑧𐑤𐑩𐑐𐑼 𐑑𐑵𐑤𐑟", + "preferences.fields.display_media.default": "𐑣𐑲𐑛 𐑥𐑰𐑛𐑾 𐑥𐑸𐑒𐑑 𐑨𐑟 𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝", + "preferences.fields.display_media.hide_all": "𐑷𐑤𐑢𐑱𐑟 𐑣𐑲𐑛 𐑥𐑰𐑛𐑾", + "preferences.fields.display_media.show_all": "𐑷𐑤𐑢𐑱𐑟 𐑖𐑴 𐑥𐑰𐑛𐑾", + "preferences.fields.dyslexic_font_label": "Dyslexic 𐑥𐑴𐑛", + "preferences.fields.expand_spoilers_label": "𐑷𐑤𐑢𐑱𐑟 𐑦𐑒𐑕𐑐𐑨𐑯𐑛 𐑐𐑴𐑕𐑑𐑕 𐑥𐑸𐑒𐑑 𐑢𐑦𐑞 𐑒𐑪𐑯𐑑𐑧𐑯𐑑 𐑢𐑹𐑯𐑦𐑙𐑟", + "preferences.fields.halloween_label": "Halloween 𐑥𐑴𐑛", + "preferences.fields.language_label": "𐑤𐑨𐑙𐑜𐑢𐑦𐑡", + "preferences.fields.media_display_label": "𐑥𐑰𐑛𐑾 𐑛𐑦𐑕𐑐𐑤𐑱", + "preferences.fields.missing_description_modal_label": "𐑖𐑴 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑛𐑲𐑩𐑤𐑪𐑜 𐑚𐑦𐑓𐑹 𐑕𐑧𐑯𐑛𐑦𐑙 𐑩 𐑐𐑴𐑕𐑑 𐑢𐑦𐑞𐑬𐑑 𐑥𐑰𐑛𐑾 𐑛𐑦𐑕𐑒𐑮𐑦𐑐𐑖𐑩𐑯𐑟", + "preferences.fields.privacy_label": "𐑐𐑴𐑕𐑑 𐑐𐑮𐑦𐑝𐑩𐑕𐑦", + "preferences.fields.reduce_motion_label": "𐑮𐑦𐑛𐑿𐑕 𐑥𐑴𐑖𐑩𐑯 𐑦𐑯 𐑨𐑯𐑦𐑥𐑱𐑖𐑩𐑯𐑟", + "preferences.fields.system_font_label": "𐑿𐑕 𐑕𐑦𐑕𐑑𐑩𐑥𐑟 𐑛𐑦𐑓𐑷𐑤𐑑 𐑓𐑪𐑯𐑑", + "preferences.fields.underline_links_label": "𐑷𐑤𐑢𐑱𐑟 𐑳𐑯𐑛𐑼𐑤𐑲𐑯 𐑤𐑦𐑙𐑒𐑕 𐑦𐑯 𐑐𐑴𐑕𐑑𐑕", + "preferences.fields.unfollow_modal_label": "𐑖𐑴 𐑒𐑪𐑯𐑓𐑼𐑥𐑱𐑖𐑩𐑯 𐑛𐑲𐑩𐑤𐑪𐑜 𐑚𐑦𐑓𐑹 𐑳𐑯𐑓𐑪𐑤𐑴𐑦𐑙 𐑕𐑳𐑥𐑢𐑳𐑯", + "preferences.hints.content_type_markdown": "𐑢𐑹𐑯𐑦𐑙: 𐑦𐑒𐑕𐑐𐑧𐑮𐑦𐑥𐑧𐑯𐑑𐑩𐑤!", + "preferences.hints.demetricator": "𐑛𐑦𐑒𐑮𐑰𐑕 𐑕𐑴𐑖𐑩𐑤 𐑥𐑰𐑛𐑾 𐑨𐑙𐑟𐑲𐑩𐑑𐑦 𐑚𐑲 𐑣𐑲𐑛𐑦𐑙 𐑷𐑤 𐑯𐑳𐑥𐑚𐑼𐑟 𐑓𐑮𐑪𐑥 𐑞 𐑕𐑲𐑑.", + "preferences.hints.halloween": "𐑚𐑦𐑢𐑺: SPOOKY! 𐑕𐑩𐑐𐑹𐑑𐑕 𐑤𐑲𐑑/𐑛𐑸𐑒 𐑑𐑪𐑜𐑩𐑤.", + "preferences.hints.privacy_followers_only": "𐑴𐑯𐑤𐑦 𐑖𐑴 𐑑 𐑓𐑪𐑤𐑴𐑼𐑟", + "preferences.hints.privacy_public": "𐑧𐑝𐑮𐑦𐑢𐑳𐑯 𐑒𐑨𐑯 𐑕𐑰", + "preferences.hints.privacy_unlisted": "𐑧𐑝𐑮𐑦𐑢𐑳𐑯 𐑒𐑨𐑯 𐑕𐑰, 𐑚𐑳𐑑 𐑯𐑪𐑑 𐑤𐑦𐑕𐑑𐑩𐑛 𐑪𐑯 𐑐𐑳𐑚𐑤𐑦𐑒 𐑑𐑲𐑥𐑤𐑲𐑯𐑟", + "preferences.options.content_type_markdown": "𐑥𐑸𐑒𐑛𐑬𐑯", + "preferences.options.content_type_plaintext": "𐑐𐑤𐑱𐑯 𐑑𐑧𐑒𐑕𐑑", + "preferences.options.privacy_followers_only": "𐑓𐑪𐑤𐑴𐑼𐑟-𐑴𐑯𐑤𐑦", + "preferences.options.privacy_public": "𐑐𐑳𐑚𐑤𐑦𐑒", + "preferences.options.privacy_unlisted": "𐑳𐑯𐑤𐑦𐑕𐑑𐑩𐑛", + "privacy.change": "𐑩𐑡𐑳𐑕𐑑 𐑐𐑴𐑕𐑑 𐑐𐑮𐑦𐑝𐑩𐑕𐑦", + "privacy.direct.long": "𐑐𐑴𐑕𐑑 𐑑 𐑥𐑧𐑯𐑖𐑩𐑯𐑛 𐑿𐑟𐑼𐑟 𐑴𐑯𐑤𐑦", + "privacy.direct.short": "𐑛𐑦𐑮𐑧𐑒𐑑", + "privacy.private.long": "𐑐𐑴𐑕𐑑 𐑑 𐑓𐑪𐑤𐑴𐑼𐑟 𐑴𐑯𐑤𐑦", + "privacy.private.short": "𐑓𐑪𐑤𐑴𐑼𐑟-𐑴𐑯𐑤𐑦", + "privacy.public.long": "𐑐𐑴𐑕𐑑 𐑑 𐑐𐑳𐑚𐑤𐑦𐑒 𐑑𐑲𐑥𐑤𐑲𐑯𐑟", + "privacy.public.short": "𐑐𐑳𐑚𐑤𐑦𐑒", + "privacy.unlisted.long": "𐑛𐑵 𐑯𐑪𐑑 𐑐𐑴𐑕𐑑 𐑑 𐑐𐑳𐑚𐑤𐑦𐑒 𐑑𐑲𐑥𐑤𐑲𐑯𐑟", + "privacy.unlisted.short": "𐑳𐑯𐑤𐑦𐑕𐑑𐑩𐑛", + "profile_dropdown.add_account": "𐑨𐑛 𐑩𐑯 𐑦𐑜𐑟𐑦𐑕𐑑𐑦𐑙 𐑩𐑒𐑬𐑯𐑑", + "profile_dropdown.logout": "𐑤𐑪𐑜 𐑬𐑑 @{acct}", + "public.column_settings.title": "·𐑓𐑧𐑛𐑦𐑝𐑻𐑕 𐑑𐑲𐑥𐑤𐑲𐑯 𐑕𐑧𐑑𐑦𐑙𐑟", + "reactions.all": "𐑷𐑤", + "regeneration_indicator.label": "𐑤𐑴𐑛𐑦𐑙…", + "regeneration_indicator.sublabel": "𐑘𐑹 𐑣𐑴𐑥 𐑓𐑰𐑛 𐑦𐑟 𐑚𐑰𐑦𐑙 𐑐𐑮𐑦𐑐𐑺𐑛!", + "register_invite.lead": "𐑒𐑩𐑥𐑐𐑤𐑰𐑑 𐑞 𐑓𐑹𐑥 𐑚𐑦𐑤𐑴 𐑑 𐑒𐑮𐑦𐑱𐑑 𐑩𐑯 𐑩𐑒𐑬𐑯𐑑.", + "register_invite.title": "𐑿𐑝 𐑚𐑰𐑯 𐑦𐑯𐑝𐑲𐑑𐑩𐑛 𐑑 𐑡𐑶𐑯 {siteTitle}!", + "registration.agreement": "𐑲 𐑩𐑜𐑮𐑰 𐑑 𐑞 {tos}.", + "registration.captcha.hint": "𐑒𐑤𐑦𐑒 𐑞 𐑦𐑥𐑦𐑡 𐑑 𐑜𐑧𐑑 𐑩 𐑯𐑿 ·𐑒𐑨𐑐𐑗𐑩", + "registration.closed_message": "{instance} 𐑦𐑟 𐑯𐑪𐑑 𐑩𐑒𐑕𐑧𐑐𐑑𐑦𐑙 𐑯𐑿 𐑥𐑧𐑥𐑚𐑼𐑟", + "registration.closed_title": "𐑮𐑧𐑡𐑦𐑕𐑑𐑮𐑱𐑖𐑩𐑯𐑟 𐑒𐑤𐑴𐑟𐑛", + "registration.confirmation_modal.close": "𐑒𐑤𐑴𐑟", + "registration.fields.confirm_placeholder": "𐑐𐑭𐑕𐑢𐑻𐑛 (𐑩𐑜𐑱𐑯)", + "registration.fields.email_placeholder": "𐑰𐑥𐑱𐑤 𐑩𐑛𐑮𐑧𐑕", + "registration.fields.password_placeholder": "𐑐𐑭𐑕𐑢𐑻𐑛", + "registration.fields.username_hint": "𐑴𐑯𐑤𐑦 𐑤𐑧𐑑𐑼𐑟, 𐑯𐑳𐑥𐑚𐑼𐑟, 𐑯 𐑳𐑯𐑛𐑼𐑕𐑒𐑹𐑟 𐑸 𐑩𐑤𐑬𐑛.", + "registration.fields.username_placeholder": "𐑿𐑟𐑼𐑯𐑱𐑥", + "registration.lead": "𐑢𐑦𐑞 𐑩𐑯 𐑩𐑒𐑬𐑯𐑑 𐑪𐑯 {instance} 𐑿𐑤 𐑚𐑰 𐑱𐑚𐑩𐑤 𐑑 𐑓𐑪𐑤𐑴 𐑐𐑰𐑐𐑩𐑤 𐑪𐑯 𐑧𐑯𐑦 𐑕𐑻𐑝𐑼 𐑦𐑯 𐑞 ·𐑓𐑧𐑛𐑦𐑝𐑻𐑕.", + "registration.newsletter": "𐑕𐑩𐑚𐑕𐑒𐑮𐑲𐑚 𐑑 𐑯𐑿𐑟𐑤𐑧𐑑𐑼.", + "registration.password_mismatch": "𐑐𐑭𐑕𐑢𐑻𐑛𐑟 𐑛𐑴𐑯𐑑 match.", + "registration.reason": "𐑢𐑲 𐑛𐑵 𐑿 𐑢𐑪𐑯𐑑 𐑑 𐑡𐑶𐑯?", + "registration.reason_hint": "𐑞𐑦𐑕 𐑢𐑦𐑤 help 𐑳𐑕 𐑮𐑦𐑝𐑿 𐑘𐑹 𐑨𐑐𐑤𐑦𐑒𐑱𐑖𐑩𐑯", + "registration.sign_up": "𐑕𐑲𐑯 𐑳𐑐", + "registration.tos": "Terms 𐑝 𐑕𐑻𐑝𐑦𐑕", + "registration.username_unavailable": "𐑿𐑟𐑼𐑯𐑱𐑥 𐑦𐑟 𐑷𐑤𐑮𐑧𐑛𐑦 𐑑𐑱𐑒𐑩𐑯.", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "𐑯𐑬", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "remote_instance.edit_federation": "𐑧𐑛𐑦𐑑 𐑓𐑧𐑛𐑼𐑱𐑖𐑩𐑯", + "remote_instance.federation_panel.heading": "𐑓𐑧𐑛𐑼𐑱𐑖𐑩𐑯 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟", + "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} 𐑣𐑨𐑟 𐑐𐑤𐑱𐑕𐑑 𐑯𐑴 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟 𐑪𐑯 {host}.", + "remote_instance.federation_panel.restricted_message": "{siteTitle} 𐑚𐑤𐑪𐑒𐑕 𐑷𐑤 𐑨𐑒𐑑𐑦𐑝𐑦𐑑𐑦𐑟 𐑓𐑮𐑪𐑥 {host}.", + "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} 𐑣𐑨𐑟 𐑐𐑤𐑱𐑕𐑑 𐑕𐑳𐑥 𐑮𐑦𐑕𐑑𐑮𐑦𐑒𐑖𐑩𐑯𐑟 𐑪𐑯 {host}.", + "remote_instance.pin_host": "𐑐𐑦𐑯 {host}", + "remote_instance.unpin_host": "𐑳𐑯𐑐𐑦𐑯 {host}", + "remote_interaction.account_placeholder": "𐑧𐑯𐑑𐑼 𐑘𐑹 username@domain 𐑿 𐑢𐑪𐑯𐑑 𐑑 act 𐑓𐑮𐑪𐑥", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑤𐑲𐑒", + "remote_interaction.favourite_title": "𐑤𐑲𐑒 𐑩 𐑐𐑴𐑕𐑑 𐑮𐑦𐑥𐑴𐑑𐑤𐑦", + "remote_interaction.follow": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑓𐑪𐑤𐑴", + "remote_interaction.follow_title": "𐑓𐑪𐑤𐑴 {user} 𐑮𐑦𐑥𐑴𐑑𐑤𐑦", + "remote_interaction.poll_vote": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑝𐑴𐑑", + "remote_interaction.poll_vote_title": "𐑝𐑴𐑑 𐑦𐑯 𐑩 𐑐𐑴𐑤 𐑮𐑦𐑥𐑴𐑑𐑤𐑦", + "remote_interaction.reblog": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑮𐑰𐑐𐑴𐑕𐑑", + "remote_interaction.reblog_title": "𐑮𐑰𐑚𐑤𐑪𐑜 𐑩 𐑐𐑴𐑕𐑑 𐑮𐑦𐑥𐑴𐑑𐑤𐑦", + "remote_interaction.reply": "𐑐𐑮𐑩𐑕𐑰𐑛 𐑑 𐑮𐑦𐑐𐑤𐑲", + "remote_interaction.reply_title": "𐑮𐑦𐑐𐑤𐑲 𐑑 𐑩 𐑐𐑴𐑕𐑑 𐑮𐑦𐑥𐑴𐑑𐑤𐑦", + "remote_interaction.user_not_found_error": "𐑒𐑫𐑛𐑩𐑯𐑑 find given 𐑿𐑟𐑼", + "remote_timeline.filter_message": "𐑿 𐑸 𐑝𐑿𐑦𐑙 𐑞 𐑑𐑲𐑥𐑤𐑲𐑯 𐑝 {instance}.", + "reply_indicator.cancel": "𐑒𐑨𐑯𐑕𐑩𐑤", + "reply_mentions.account.add": "𐑨𐑛 𐑑 𐑥𐑧𐑯𐑖𐑩𐑯𐑟", + "reply_mentions.account.remove": "𐑮𐑦𐑥𐑵𐑝 𐑓𐑮𐑪𐑥 𐑥𐑧𐑯𐑖𐑩𐑯𐑟", + "reply_mentions.more": "𐑯 {count} 𐑥𐑹", + "reply_mentions.reply": "𐑮𐑦𐑐𐑤𐑲𐑦𐑙 𐑑 {accounts}{more}", + "reply_mentions.reply_empty": "𐑮𐑦𐑐𐑤𐑲𐑦𐑙 𐑑 𐑐𐑴𐑕𐑑", + "report.block": "𐑚𐑤𐑪𐑒 {target}", + "report.block_hint": "𐑛𐑵 𐑿 𐑷𐑤𐑕𐑴 𐑢𐑪𐑯𐑑 𐑑 𐑚𐑤𐑪𐑒 𐑞𐑦𐑕 𐑩𐑒𐑬𐑯𐑑?", + "report.forward": "𐑓𐑹𐑢𐑼𐑛 𐑑 {target}", + "report.forward_hint": "𐑞 𐑩𐑒𐑬𐑯𐑑 𐑦𐑟 𐑓𐑮𐑪𐑥 𐑩𐑯𐑳𐑞𐑼 𐑕𐑻𐑝𐑼. 𐑕𐑧𐑯𐑛 𐑩 𐑒𐑪𐑐𐑦 𐑝 𐑞 𐑮𐑦𐑐𐑹𐑑 𐑞𐑺 𐑨𐑟 𐑢𐑧𐑤?", + "report.hint": "𐑞 𐑮𐑦𐑐𐑹𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑕𐑧𐑯𐑑 𐑑 𐑘𐑹 𐑕𐑻𐑝𐑼 𐑥𐑪𐑛𐑼𐑱𐑑𐑼𐑟. 𐑿 𐑒𐑨𐑯 𐑐𐑮𐑩𐑝𐑲𐑛 𐑩𐑯 𐑧𐑒𐑕𐑐𐑤𐑩𐑯𐑱𐑖𐑩𐑯 𐑝 𐑢𐑲 𐑿 𐑸 𐑮𐑦𐑐𐑹𐑑𐑦𐑙 𐑞𐑦𐑕 𐑩𐑒𐑬𐑯𐑑 𐑚𐑦𐑤𐑴:", + "report.placeholder": "𐑩𐑛𐑦𐑖𐑩𐑯𐑩𐑤 𐑒𐑪𐑥𐑧𐑯𐑑𐑕", + "report.submit": "𐑕𐑩𐑚𐑥𐑦𐑑", + "report.target": "𐑮𐑦𐑐𐑹𐑑𐑦𐑙 {target}", + "schedule.post_time": "𐑐𐑴𐑕𐑑 𐑛𐑱𐑑/𐑑𐑲𐑥", + "schedule.remove": "𐑮𐑦𐑥𐑵𐑝 𐑖𐑧𐑡𐑵𐑤", + "schedule_button.add_schedule": "𐑖𐑧𐑡𐑵𐑤 𐑐𐑴𐑕𐑑 𐑓 𐑤𐑱𐑑𐑼", + "schedule_button.remove_schedule": "𐑐𐑴𐑕𐑑 𐑦𐑥𐑰𐑛𐑾𐑑𐑤𐑦", + "scheduled_status.cancel": "𐑒𐑨𐑯𐑕𐑩𐑤", + "search.action": "𐑕𐑻𐑗 𐑓 “{query}”", + "search.placeholder": "𐑕𐑻𐑗", + "search_results.accounts": "𐑐𐑰𐑐𐑩𐑤", + "search_results.hashtags": "𐑣𐑨𐑖𐑑𐑨𐑜𐑟", + "search_results.statuses": "𐑐𐑴𐑕𐑑𐑕", + "search_results.top": "𐑑𐑪𐑐", + "security.codes.fail": "𐑓𐑱𐑤𐑛 𐑑 𐑓𐑧𐑗 𐑚𐑨𐑒𐑳𐑐 𐑒𐑴𐑛𐑟", + "security.confirm.fail": "𐑦𐑯𐑒𐑼𐑧𐑒𐑑 𐑒𐑴𐑛 𐑹 𐑐𐑭𐑕𐑢𐑻𐑛. 𐑑𐑮𐑲 𐑩𐑜𐑱𐑯.", + "security.delete_account.fail": "𐑩𐑒𐑬𐑯𐑑 𐑛𐑦𐑤𐑰𐑖𐑩𐑯 𐑓𐑱𐑤𐑛.", + "security.delete_account.success": "𐑩𐑒𐑬𐑯𐑑 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦 𐑛𐑦𐑤𐑰𐑑𐑩𐑛.", + "security.disable.fail": "𐑦𐑯𐑒𐑼𐑧𐑒𐑑 𐑐𐑭𐑕𐑢𐑻𐑛. 𐑑𐑮𐑲 𐑩𐑜𐑱𐑯.", + "security.disable_mfa": "𐑛𐑦𐑕𐑱𐑚𐑩𐑤", + "security.fields.email.label": "𐑰𐑥𐑱𐑤 𐑩𐑛𐑮𐑧𐑕", + "security.fields.new_password.label": "𐑯𐑿 𐑐𐑭𐑕𐑢𐑻𐑛", + "security.fields.old_password.label": "𐑒𐑳𐑮𐑩𐑯𐑑 𐑐𐑭𐑕𐑢𐑻𐑛", + "security.fields.password.label": "𐑐𐑭𐑕𐑢𐑻𐑛", + "security.fields.password_confirmation.label": "𐑯𐑿 𐑐𐑭𐑕𐑢𐑻𐑛 (𐑩𐑜𐑱𐑯)", + "security.headers.delete": "𐑛𐑦𐑤𐑰𐑑 𐑩𐑒𐑬𐑯𐑑", + "security.headers.tokens": "𐑕𐑧𐑖𐑩𐑯𐑟", + "security.headers.update_email": "𐑗𐑱𐑯𐑡 𐑰𐑥𐑱𐑤", + "security.headers.update_password": "𐑗𐑱𐑯𐑡 𐑐𐑭𐑕𐑢𐑻𐑛", + "security.mfa": "𐑕𐑧𐑑 𐑳𐑐 2-Factor Auth", + "security.mfa_enabled": "𐑿 𐑣𐑨𐑝 𐑥𐑳𐑤𐑑𐑦-𐑓𐑨𐑒𐑑𐑼 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯 𐑕𐑧𐑑 𐑳𐑐 𐑢𐑦𐑞 OTP.", + "security.mfa_header": "𐑷𐑔𐑼𐑲𐑟𐑱𐑖𐑩𐑯 𐑥𐑧𐑔𐑩𐑛𐑟", + "security.mfa_setup_hint": "𐑒𐑩𐑯𐑓𐑦𐑜𐑼 𐑥𐑳𐑤𐑑𐑦-𐑓𐑨𐑒𐑑𐑼 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯 𐑢𐑦𐑞 OTP", + "security.qr.fail": "𐑓𐑱𐑤𐑛 𐑑 𐑓𐑧𐑗 𐑕𐑧𐑑𐑳𐑐 key", + "security.submit": "𐑕𐑱𐑝 𐑗𐑱𐑯𐑡𐑩𐑟", + "security.submit.delete": "𐑛𐑦𐑤𐑰𐑑 𐑩𐑒𐑬𐑯𐑑", + "security.text.delete": "𐑑 𐑛𐑦𐑤𐑰𐑑 𐑘𐑹 𐑩𐑒𐑬𐑯𐑑, 𐑧𐑯𐑑𐑼 𐑘𐑹 𐑐𐑭𐑕𐑢𐑻𐑛 𐑞𐑧𐑯 𐑒𐑤𐑦𐑒 𐑛𐑦𐑤𐑰𐑑 𐑩𐑒𐑬𐑯𐑑. 𐑞𐑦𐑕 𐑦𐑟 𐑩 𐑐𐑻𐑥𐑩𐑯𐑩𐑯𐑑 𐑨𐑒𐑖𐑩𐑯 𐑞𐑨𐑑 𐑒𐑨𐑯𐑪𐑑 𐑚𐑰 𐑳𐑯𐑛𐑳𐑯. 𐑘𐑹 𐑩𐑒𐑬𐑯𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑛𐑦𐑕𐑑𐑮𐑶𐑛 𐑓𐑮𐑪𐑥 𐑞𐑦𐑕 𐑕𐑻𐑝𐑼, 𐑯 𐑩 𐑛𐑦𐑤𐑰𐑖𐑩𐑯 𐑮𐑦𐑒𐑢𐑧𐑕𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑕𐑧𐑯𐑑 𐑑 𐑳𐑞𐑼 𐑕𐑻𐑝𐑼𐑟. 𐑦𐑑𐑕 𐑯𐑪𐑑 𐑜𐑨𐑮𐑩𐑯𐑑𐑰𐑛 𐑞𐑨𐑑 𐑷𐑤 𐑕𐑻𐑝𐑼𐑟 𐑢𐑦𐑤 𐑐𐑻𐑡 𐑘𐑹 𐑩𐑒𐑬𐑯𐑑.", + "security.tokens.revoke": "𐑮𐑦𐑝𐑴𐑒", + "security.update_email.fail": "𐑳𐑐𐑛𐑱𐑑 𐑰𐑥𐑱𐑤 𐑓𐑱𐑤𐑛.", + "security.update_email.success": "𐑰𐑥𐑱𐑤 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦 𐑳𐑐𐑛𐑱𐑑𐑩𐑛.", + "security.update_password.fail": "𐑳𐑐𐑛𐑱𐑑 𐑐𐑭𐑕𐑢𐑻𐑛 𐑓𐑱𐑤𐑛.", + "security.update_password.success": "𐑐𐑭𐑕𐑢𐑻𐑛 𐑕𐑩𐑒𐑕𐑧𐑕𐑓𐑩𐑤𐑦 𐑳𐑐𐑛𐑱𐑑𐑩𐑛.", + "signup_panel.subtitle": "𐑕𐑲𐑯 𐑳𐑐 𐑯𐑬 𐑑 𐑛𐑦𐑕𐑒𐑳𐑕.", + "signup_panel.title": "𐑯𐑿 𐑑 {site_title}?", + "soapbox_config.authenticated_profile_hint": "𐑿𐑟𐑼𐑟 𐑥𐑳𐑕𐑑 𐑚𐑰 𐑤𐑪𐑜𐑛-𐑦𐑯 𐑑 𐑝𐑿 𐑮𐑦𐑐𐑤𐑲𐑟 𐑯 𐑥𐑰𐑛𐑾 𐑪𐑯 𐑿𐑟𐑼 𐑐𐑮𐑴𐑓𐑲𐑤𐑟.", + "soapbox_config.authenticated_profile_label": "𐑐𐑮𐑴𐑓𐑲𐑤𐑟 𐑮𐑦𐑒𐑢𐑲𐑼 𐑷𐑔𐑧𐑯𐑑𐑦𐑒𐑱𐑖𐑩𐑯", + "soapbox_config.copyright_footer.meta_fields.label_placeholder": "Copyright footer", + "soapbox_config.crypto_address.meta_fields.address_placeholder": "𐑩𐑛𐑮𐑧𐑕", + "soapbox_config.crypto_address.meta_fields.note_placeholder": "𐑯𐑴𐑑 (𐑪𐑐𐑖𐑩𐑯𐑩𐑤)", + "soapbox_config.crypto_address.meta_fields.ticker_placeholder": "𐑑𐑦𐑒𐑼", + "soapbox_config.crypto_donate_panel_limit.meta_fields.limit_placeholder": "𐑯𐑳𐑥𐑚𐑼 𐑝 𐑲𐑑𐑩𐑥𐑟 𐑑 𐑛𐑦𐑕𐑐𐑤𐑱 𐑦𐑯 𐑞 𐑒𐑮𐑦𐑐𐑑𐑴 𐑣𐑴𐑥𐑐𐑱𐑡 widget", + "soapbox_config.custom_css.meta_fields.url_placeholder": "URL", + "soapbox_config.display_fqn_label": "𐑛𐑦𐑕𐑐𐑤𐑱 𐑛𐑴𐑥𐑱𐑯 (eg @user@domain) 𐑓 𐑤𐑴𐑒𐑩𐑤 𐑩𐑒𐑬𐑯𐑑𐑕.", + "soapbox_config.fields.brand_color_label": "𐑚𐑮𐑨𐑯𐑛 𐑒𐑳𐑤𐑼", + "soapbox_config.fields.crypto_address.add": "𐑨𐑛 𐑯𐑿 𐑒𐑮𐑦𐑐𐑑𐑴 𐑩𐑛𐑮𐑧𐑕", + "soapbox_config.fields.crypto_addresses_label": "𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦 𐑩𐑛𐑮𐑧𐑕𐑩𐑟", + "soapbox_config.fields.home_footer.add": "𐑨𐑛 𐑯𐑿 𐑣𐑴𐑥 𐑓𐑫𐑑𐑼 𐑲𐑑𐑩𐑥", + "soapbox_config.fields.home_footer_fields_label": "𐑣𐑴𐑥 𐑓𐑫𐑑𐑼 𐑲𐑑𐑩𐑥𐑟", + "soapbox_config.fields.logo_label": "Logo", + "soapbox_config.fields.promo_panel.add": "𐑨𐑛 𐑯𐑿 Promo panel 𐑲𐑑𐑩𐑥", + "soapbox_config.fields.promo_panel_fields_label": "Promo panel 𐑲𐑑𐑩𐑥𐑟", + "soapbox_config.fields.theme_label": "𐑛𐑦𐑓𐑷𐑤𐑑 𐑔𐑰𐑥", + "soapbox_config.greentext_label": "𐑦𐑯𐑱𐑚𐑩𐑤 𐑜𐑮𐑰𐑯𐑑𐑧𐑒𐑕𐑑 𐑕𐑩𐑐𐑹𐑑", + "soapbox_config.hints.crypto_addresses": "𐑨𐑛 𐑒𐑮𐑦𐑐𐑑𐑴𐑒𐑳𐑮𐑩𐑯𐑕𐑦 𐑩𐑛𐑮𐑧𐑕𐑩𐑟 so 𐑿𐑟𐑼𐑟 𐑝 𐑘𐑹 𐑕𐑲𐑑 𐑒𐑨𐑯 𐑛𐑴𐑯𐑱𐑑 𐑑 𐑿. 𐑹𐑛𐑼 matters, 𐑯 𐑿 𐑥𐑳𐑕𐑑 𐑿𐑕 lowercase 𐑑𐑦𐑒𐑼 values.", + "soapbox_config.hints.home_footer_fields": "𐑿 𐑒𐑨𐑯 𐑣𐑨𐑝 custom defined 𐑤𐑦𐑙𐑒𐑕 𐑛𐑦𐑕𐑐𐑤𐑱𐑛 𐑪𐑯 𐑞 𐑓𐑫𐑑𐑼 𐑝 𐑘𐑹 static 𐑐𐑱𐑡𐑩𐑟", + "soapbox_config.hints.logo": "SVG. 𐑨𐑑 𐑥𐑴𐑕𐑑 2 MB. 𐑢𐑦𐑤 𐑚𐑰 𐑛𐑦𐑕𐑐𐑤𐑱𐑛 𐑑 50px height, maintaining aspect ratio", + "soapbox_config.hints.promo_panel_fields": "𐑿 𐑒𐑨𐑯 𐑣𐑨𐑝 custom defined 𐑤𐑦𐑙𐑒𐑕 𐑛𐑦𐑕𐑐𐑤𐑱𐑛 𐑪𐑯 𐑞 right panel 𐑝 𐑞 𐑑𐑲𐑥𐑤𐑲𐑯𐑟 𐑐𐑱𐑡.", + "soapbox_config.hints.promo_panel_icons": "{ link }", + "soapbox_config.hints.promo_panel_icons.link": "·𐑕𐑴𐑐𐑚𐑪𐑒𐑕 𐑲𐑒𐑪𐑯𐑟 List", + "soapbox_config.home_footer.meta_fields.label_placeholder": "Label", + "soapbox_config.home_footer.meta_fields.url_placeholder": "URL", + "soapbox_config.promo_panel.meta_fields.icon_placeholder": "𐑲𐑒𐑪𐑯", + "soapbox_config.promo_panel.meta_fields.label_placeholder": "Label", + "soapbox_config.promo_panel.meta_fields.url_placeholder": "URL", + "soapbox_config.raw_json_hint": "𐑧𐑛𐑦𐑑 𐑞 𐑕𐑧𐑑𐑦𐑙𐑟 𐑛𐑱𐑑𐑩 𐑛𐑦𐑮𐑧𐑒𐑑𐑤𐑦. 𐑗𐑱𐑯𐑡𐑩𐑟 𐑥𐑱𐑛 𐑛𐑦𐑮𐑧𐑒𐑑𐑤𐑦 𐑑 𐑞 JSON 𐑓𐑲𐑤 𐑢𐑦𐑤 𐑴𐑝𐑼𐑮𐑲𐑛 𐑞 𐑓𐑹𐑥 𐑓𐑰𐑤𐑛𐑟 𐑩𐑚𐑳𐑝. 𐑒𐑤𐑦𐑒 𐑕𐑱𐑝 𐑑 𐑩𐑐𐑤𐑲 𐑘𐑹 𐑗𐑱𐑯𐑡𐑩𐑟.", + "soapbox_config.raw_json_label": "𐑩𐑛𐑝𐑭𐑯𐑕𐑑: 𐑧𐑛𐑦𐑑 raw JSON 𐑛𐑱𐑑𐑩", + "soapbox_config.save": "𐑕𐑱𐑝", + "soapbox_config.saved": "·𐑕𐑴𐑐𐑚𐑪𐑒𐑕 𐑒𐑩𐑯𐑓𐑦𐑜 𐑕𐑱𐑝𐑛!", + "soapbox_config.verified_can_edit_name_label": "𐑩𐑤𐑬 𐑝𐑧𐑮𐑦𐑓𐑲𐑛 𐑿𐑟𐑼𐑟 𐑑 𐑧𐑛𐑦𐑑 𐑞𐑺 𐑴𐑯 𐑛𐑦𐑕𐑐𐑤𐑱 𐑯𐑱𐑥.", + "status.admin_account": "𐑴𐑐𐑩𐑯 𐑥𐑪𐑛𐑼𐑱𐑖𐑩𐑯 𐑦𐑯𐑑𐑼𐑓𐑱𐑕 𐑓 @{name}", + "status.admin_status": "𐑴𐑐𐑩𐑯 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑦𐑯 𐑞 𐑥𐑪𐑛𐑼𐑱𐑖𐑩𐑯 𐑦𐑯𐑑𐑼𐑓𐑱𐑕", + "status.block": "𐑚𐑤𐑪𐑒 @{name}", + "status.bookmark": "𐑚𐑫𐑒𐑥𐑸𐑒", + "status.bookmarked": "𐑚𐑫𐑒𐑥𐑸𐑒 𐑨𐑛𐑩𐑛.", + "status.cancel_reblog_private": "𐑳𐑯-𐑮𐑰𐑐𐑴𐑕𐑑", + "status.cannot_reblog": "𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑒𐑨𐑯𐑪𐑑 𐑚𐑰 𐑮𐑰𐑐𐑴𐑕𐑑𐑩𐑛", + "status.chat": "𐑗𐑨𐑑 𐑢𐑦𐑞 @{name}", + "status.copy": "𐑒𐑪𐑐𐑦 𐑤𐑦𐑙𐑒 𐑑 𐑐𐑴𐑕𐑑", + "status.delete": "𐑛𐑦𐑤𐑰𐑑", + "status.detailed_status": "𐑛𐑰𐑑𐑱𐑤𐑛 𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯 𐑝𐑿", + "status.direct": "𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡 @{name}", + "status.embed": " 𐑦𐑥𐑚𐑧𐑛", + "status.favourite": "𐑤𐑲𐑒", + "status.filtered": "𐑓𐑦𐑤𐑑𐑼𐑛", + "status.load_more": "𐑤𐑴𐑛 𐑥𐑹", + "status.media_hidden": "𐑥𐑰𐑛𐑾 𐑣𐑦𐑛𐑩𐑯", + "status.mention": "𐑥𐑧𐑯𐑖𐑩𐑯 @{name}", + "status.more": "𐑥𐑹", + "status.mute": "𐑥𐑿𐑑 @{name}", + "status.mute_conversation": "𐑥𐑿𐑑 𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯", + "status.open": "𐑦𐑒𐑕𐑐𐑨𐑯𐑛 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑", + "status.pin": "𐑐𐑦𐑯 𐑪𐑯 𐑐𐑮𐑴𐑓𐑲𐑤", + "status.pinned": "𐑐𐑦𐑯𐑛 𐑐𐑴𐑕𐑑", + "status.reactions.cry": "𐑕𐑨𐑛", + "status.reactions.empty": "𐑯𐑴 𐑢𐑳𐑯 𐑣𐑨𐑟 𐑮𐑦𐑨𐑒𐑑𐑩𐑛 𐑑 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑕𐑳𐑥𐑢𐑳𐑯 𐑛𐑳𐑟, 𐑞𐑱 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "status.reactions.heart": "𐑤𐑳𐑝", + "status.reactions.laughing": "𐑣𐑭𐑣𐑭", + "status.reactions.like": "𐑤𐑲𐑒", + "status.reactions.open_mouth": "𐑢𐑬", + "status.reactions.weary": "𐑢𐑽𐑦", + "status.reactions_expand": "𐑕𐑦𐑤𐑧𐑒𐑑 𐑦𐑥𐑴𐑡𐑦", + "status.read_more": "𐑮𐑧𐑛 𐑥𐑹", + "status.reblog": "𐑮𐑰𐑐𐑴𐑕𐑑", + "status.reblog_private": "𐑮𐑰𐑐𐑴𐑕𐑑 𐑑 𐑼𐑦𐑡𐑦𐑯𐑩𐑤 𐑷𐑛𐑾𐑯𐑕", + "status.reblogged_by": "{name} 𐑮𐑰𐑐𐑴𐑕𐑑𐑩𐑛", + "status.reblogs.empty": "𐑯𐑴 𐑢𐑳𐑯 𐑣𐑨𐑟 𐑮𐑰𐑐𐑴𐑕𐑑𐑩𐑛 𐑞𐑦𐑕 𐑐𐑴𐑕𐑑 𐑘𐑧𐑑. 𐑢𐑧𐑯 𐑕𐑳𐑥𐑢𐑳𐑯 𐑛𐑳𐑟, 𐑞𐑱 𐑢𐑦𐑤 𐑖𐑴 𐑳𐑐 𐑣𐑽.", + "status.redraft": "𐑛𐑦𐑤𐑰𐑑 𐑯 𐑮𐑰𐑛𐑮𐑭𐑓𐑑", + "status.remove_account_from_group": "𐑮𐑦𐑥𐑵𐑝 𐑩𐑒𐑬𐑯𐑑 𐑓𐑮𐑪𐑥 𐑜𐑮𐑵𐑐", + "status.remove_post_from_group": "𐑮𐑦𐑥𐑵𐑝 𐑐𐑴𐑕𐑑 𐑓𐑮𐑪𐑥 𐑜𐑮𐑵𐑐", + "status.reply": "𐑮𐑦𐑐𐑤𐑲", + "status.replyAll": "𐑮𐑦𐑐𐑤𐑲 𐑑 𐑔𐑮𐑧𐑛", + "status.report": "𐑮𐑦𐑐𐑹𐑑 @{name}", + "status.sensitive_warning": "𐑕𐑧𐑯𐑕𐑦𐑑𐑦𐑝 𐑒𐑪𐑯𐑑𐑧𐑯𐑑", + "status.share": "𐑖𐑺", + "status.show_less": "𐑖𐑴 𐑤𐑧𐑕", + "status.show_less_all": "𐑖𐑴 𐑤𐑧𐑕 𐑓 𐑷𐑤", + "status.show_more": "𐑖𐑴 𐑥𐑹", + "status.show_more_all": "𐑖𐑴 𐑥𐑹 𐑓 𐑷𐑤", + "status.show_thread": "𐑖𐑴 𐑔𐑮𐑧𐑛", + "status.title": "𐑐𐑴𐑕𐑑", + "status.title_direct": "𐑛𐑦𐑮𐑧𐑒𐑑 𐑥𐑧𐑕𐑦𐑡", + "status.unbookmark": "𐑮𐑦𐑥𐑵𐑝 𐑚𐑫𐑒𐑥𐑸𐑒", + "status.unbookmarked": "𐑚𐑫𐑒𐑥𐑸𐑒 𐑮𐑦𐑥𐑵𐑝𐑛.", + "status.unmute_conversation": "𐑳𐑯𐑥𐑿𐑑 𐑒𐑪𐑯𐑝𐑼𐑕𐑱𐑖𐑩𐑯", + "status.unpin": "𐑳𐑯𐑐𐑦𐑯 𐑓𐑮𐑪𐑥 𐑐𐑮𐑴𐑓𐑲𐑤", + "status_list.queue_label": "𐑒𐑤𐑦𐑒 𐑑 𐑕𐑰 {count} 𐑯𐑿 {count, plural, 𐑢𐑳𐑯 {post} 𐑳𐑞𐑼 {posts}}", + "statuses.tombstone": "𐑢𐑳𐑯 𐑹 𐑥𐑹 𐑐𐑴𐑕𐑑𐑕 𐑦𐑟 𐑳𐑯𐑩𐑝𐑱𐑤𐑩𐑚𐑩𐑤.", + "suggestions.dismiss": "𐑛𐑦𐑕𐑥𐑦𐑕 𐑕𐑩𐑡𐑧𐑕𐑗𐑩𐑯", + "tabs_bar.all": "𐑷𐑤", + "tabs_bar.apps": "𐑨𐑐𐑕", + "tabs_bar.chats": "𐑗𐑨𐑑𐑕", + "tabs_bar.dashboard": "𐑛𐑨𐑖𐑚𐑹𐑛", + "tabs_bar.fediverse": "·𐑓𐑧𐑛𐑦𐑝𐑻𐑕", + "tabs_bar.header": "𐑩𐑒𐑬𐑯𐑑 𐑦𐑯𐑓𐑴", + "tabs_bar.home": "𐑣𐑴𐑥", + "tabs_bar.news": "𐑯𐑿𐑟", + "tabs_bar.notifications": "𐑯𐑴𐑑𐑦𐑓𐑦𐑒𐑱𐑖𐑩𐑯𐑟", + "tabs_bar.post": "𐑐𐑴𐑕𐑑", + "tabs_bar.search": "𐑕𐑻𐑗", + "tabs_bar.theme_toggle_dark": "𐑕𐑢𐑦𐑗 𐑑 𐑛𐑸𐑒 𐑔𐑰𐑥", + "tabs_bar.theme_toggle_light": "𐑕𐑢𐑦𐑗 𐑑 𐑤𐑲𐑑 𐑔𐑰𐑥", + "time_remaining.days": "{number, plural, one {# day} other {# days}} 𐑤𐑧𐑓𐑑", + "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} 𐑤𐑧𐑓𐑑", + "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} 𐑤𐑧𐑓𐑑", + "time_remaining.moments": "𐑥𐑴𐑥𐑩𐑯𐑑𐑕 remaining", + "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} 𐑤𐑧𐑓𐑑", + "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people} 𐑑𐑷𐑒𐑦𐑙", + "trends.title": "𐑑𐑮𐑧𐑯𐑛𐑟", + "ui.beforeunload": "𐑘𐑹 𐑛𐑮𐑭𐑓𐑑 𐑢𐑦𐑤 𐑚𐑰 𐑤𐑪𐑕𐑑 𐑦𐑓 𐑿 𐑤𐑰𐑝.", + "unauthorized_modal.footer": "𐑷𐑤𐑮𐑧𐑛𐑦 𐑣𐑨𐑝 𐑩𐑯 𐑩𐑒𐑬𐑯𐑑? {login}.", + "unauthorized_modal.text": "𐑿 𐑯𐑰𐑛 𐑑 𐑚𐑰 𐑤𐑪𐑜𐑛 𐑦𐑯 𐑑 𐑛𐑵 𐑞𐑨𐑑.", + "unauthorized_modal.title": "𐑕𐑲𐑯 𐑳𐑐 𐑓 {site_title}", + "upload_area.title": "𐑛𐑮𐑨𐑜 𐑯 𐑛𐑮𐑪𐑐 𐑑 𐑳𐑐𐑤𐑴𐑛", + "upload_button.label": "𐑨𐑛 𐑥𐑰𐑛𐑾 𐑩𐑑𐑨𐑗𐑥𐑩𐑯𐑑", + "upload_error.limit": "𐑓𐑲𐑤 𐑳𐑐𐑤𐑴𐑛 𐑤𐑦𐑥𐑦𐑑 𐑦𐑒𐑕𐑰𐑛𐑩𐑛.", + "upload_error.poll": "𐑓𐑲𐑤 𐑳𐑐𐑤𐑴𐑛 𐑯𐑪𐑑 𐑩𐑤𐑬𐑛 𐑢𐑦𐑞 𐑐𐑴𐑤𐑟.", + "upload_form.description": "𐑛𐑦𐑕𐑒𐑮𐑲𐑚 𐑓 𐑞 𐑝𐑦𐑠𐑫𐑩𐑤𐑦 𐑦𐑥𐑐𐑺𐑛", + "upload_form.preview": "𐑐𐑮𐑰𐑝𐑿", + "upload_form.undo": "𐑛𐑦𐑤𐑰𐑑", + "upload_progress.label": "𐑳𐑐𐑤𐑴𐑛𐑦𐑙...", + "video.close": "𐑒𐑤𐑴𐑟 𐑝𐑦𐑛𐑦𐑴", + "video.download": "𐑛𐑬𐑯𐑤𐑴𐑛 𐑓𐑲𐑤", + "video.exit_fullscreen": "𐑧𐑒𐑕𐑦𐑑 𐑓𐑫𐑤 𐑕𐑒𐑮𐑰𐑯", + "video.expand": "𐑦𐑒𐑕𐑐𐑨𐑯𐑛 𐑝𐑦𐑛𐑦𐑴", + "video.fullscreen": "𐑓𐑫𐑤 𐑕𐑒𐑮𐑰𐑯", + "video.hide": "𐑣𐑲𐑛 𐑝𐑦𐑛𐑦𐑴", + "video.mute": "𐑥𐑿𐑑 𐑕𐑬𐑯𐑛", + "video.pause": "𐑐𐑷𐑟", + "video.play": "𐑐𐑤𐑱", + "video.unmute": "𐑳𐑯𐑥𐑿𐑑 𐑕𐑬𐑯𐑛", + "who_to_follow.title": "𐑣𐑵 𐑑 𐑓𐑪𐑤𐑴" +} diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index acf1a24fd..f90434132 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -530,12 +580,12 @@ "media_gallery.toggle_visible": "Toggle visibility", "media_panel.empty_message": "No media found.", "media_panel.title": "Media", - "mfa.mfa_disable_enter_password": "Enter your current password to disable two-factor auth:", - "mfa.mfa_setup_enter_password": "Enter your current password to confirm your identity:", - "mfa.mfa_setup_scan_description": "Using your two-factor app, scan this QR code or enter text key:", + "mfa.mfa_disable_enter_password": "Enter your current password to disable two-factor auth.", + "mfa.mfa_setup_enter_password": "Enter your current password to confirm your identity", + "mfa.mfa_setup_scan_description": "Using your two-factor app, scan this QR code or enter the text key.", "mfa.mfa_setup_scan_key": "Key:", "mfa.mfa_setup_scan_title": "Scan", - "mfa.mfa_setup_verify_description": "To enable two-factor authentication, enter the code from your two-factor app:", + "mfa.mfa_setup_verify_description": "To enable two-factor authentication, enter the code from your two-factor app", "mfa.mfa_setup_verify_title": "Verify", "mfa.otp_enabled_description": "You have enabled two-factor authentication via OTP.", "mfa.otp_enabled_title": "OTP Enabled", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domain blocks", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Likes", "navigation_bar.filters": "Filters", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Mutes", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/eo.json b/app/soapbox/locales/eo.json index ed6fa316a..8b5b7e10e 100644 --- a/app/soapbox/locales/eo.json +++ b/app/soapbox/locales/eo.json @@ -8,6 +8,7 @@ "account.block_domain": "Kaŝi ĉion de {domain}", "account.blocked": "Blokita", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Tiu uzanto ankoraŭ ne sekvas iun.", "account.follows_you": "Sekvas vin", "account.hide_reblogs": "Kaŝi diskonigojn de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La posedanto de tiu ligilo estis kontrolita je {date}", "account.locked_info": "La privateco de tiu konto estas elektita kiel fermita. La posedanto povas mane akcepti tiun, kiu povas sekvi rin.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} moviĝis al:", "account.mute": "Silentigi @{name}", "account.muted": "Silentigita", + "account.never_active": "Never", "account.posts": "Mesaĝoj", "account.posts_with_replies": "Kun respondoj", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Fermi", "bundle_modal_error.message": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", "bundle_modal_error.retry": "Bonvolu reprovi", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokitaj uzantoj", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Loka tempolinio", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Rektaj mesaĝoj", + "column.directory": "Browse profiles", "column.domain_blocks": "Kaŝitaj domajnoj", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Petoj de sekvado", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hejmo", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listoj", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Silentigitaj uzantoj", "column.notifications": "Sciigoj", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Fratara tempolinio", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Reveni", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Kaŝi agordojn", "column_header.show_settings": "Montri agordojn", "community.column_settings.media_only": "Nur aŭdovidaĵoj", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Balotenketa daŭro", "compose_form.poll.option_placeholder": "Elekteblo {number}", "compose_form.poll.remove_option": "Forigi ĉi tiu elekteblon", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Hup", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloki kaj signali", "confirmations.block.confirm": "Bloki", "confirmations.block.message": "Ĉu vi certas, ke vi volas bloki {name}?", "confirmations.delete.confirm": "Forigi", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ĉu vi certas, ke vi volas forigi ĉi tiun mesaĝon?", "confirmations.delete_list.confirm": "Forigi", "confirmations.delete_list.message": "Ĉu vi certas, ke vi volas porĉiame forigi ĉi tiun liston?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Rajtigi", "follow_request.reject": "Rifuzi", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} estas malfermitkoda programo. Vi povas kontribui aŭ raporti problemojn en GitLab je {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Antaŭa", "lightbox.view_context": "Vidi kuntekston", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Aldoni al la listo", "lists.account.remove": "Forigi de la listo", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Ĉu vi volas kaŝi la sciigojn de ĉi tiu uzanto?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Skribi novan mesaĝon", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Kaŝitaj domajnoj", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Stelumoj", "navigation_bar.filters": "Silentigitaj vortoj", "navigation_bar.follow_requests": "Petoj de sekvado", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Pri ĉi tiu servilo", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Rapidklavoj", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Elsaluti", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Silentigitaj uzantoj", "navigation_bar.pins": "Alpinglitaj mesaĝoj", "navigation_bar.preferences": "Preferoj", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sekureco", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Aktualigi", "poll.total_votes": "{count, plural, one {# voĉdono} other {# voĉdonoj}}", "poll.vote": "Voĉdoni", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Aldoni balotenketon", "poll_button.remove_poll": "Forigi balotenketon", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Ŝargado…", "regeneration_indicator.sublabel": "Via hejma fluo pretiĝas!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}t", "relative_time.hours": "{number}h", "relative_time.just_now": "nun", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Nuligi", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Plusendi al {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Serĉi", - "search_popout.search_format": "Detala serĉo", - "search_popout.tips.full_text": "Simplaj tekstoj montras la mesaĝojn, kiujn vi skribis, stelumis, diskonigis, aŭ en kiuj vi estis menciita, sed ankaŭ kongruajn uzantnomojn, montratajn nomojn, kaj kradvortojn.", - "search_popout.tips.hashtag": "kradvorto", - "search_popout.tips.status": "mesaĝoj", - "search_popout.tips.user": "uzanto", "search_results.accounts": "Homoj", "search_results.hashtags": "Kradvortoj", "search_results.statuses": "Mesaĝoj", diff --git a/app/soapbox/locales/es-AR.json b/app/soapbox/locales/es-AR.json index 5083242a9..7ede8331c 100644 --- a/app/soapbox/locales/es-AR.json +++ b/app/soapbox/locales/es-AR.json @@ -8,6 +8,7 @@ "account.block_domain": "Ocultar todo de {domain}", "account.blocked": "Bloqueado", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Todavía este usuario no sigue a nadie.", "account.follows_you": "Te sigue", "account.hide_reblogs": "Ocultar retoots de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La propiedad de este enlace fue verificada el {date}", "account.locked_info": "El estado de privacidad de esta cuenta está establecido como bloqueado. El propietario manualmente revisa quién puede seguirle.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se ha muó a:", "account.mute": "Silenciar a @{name}", "account.muted": "Silenciado", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots con respuestas", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Cerrar", "bundle_modal_error.message": "Algo salió mal al cargar este componente.", "bundle_modal_error.retry": "Intentá de nuevo", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Usuarios bloqueados", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Línea temporal local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mensajes directos", + "column.directory": "Browse profiles", "column.domain_blocks": "Dominios ocultos", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Solicitudes de seguimiento", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Principal", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Usuarios silenciados", "column.notifications": "Notificaciones", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Línea temporal federada", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Volver", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Ocultar configuración", "column_header.show_settings": "Mostrar configuración", "community.column_settings.media_only": "Sólo medios", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.option_placeholder": "Opción {number}", "compose_form.poll.remove_option": "Quitá esta opción", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tootear", "compose_form.publish_loud": "¡{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquear y denunciar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "¿Estás seguro que querés bloquear a {name}?", "confirmations.delete.confirm": "Eliminar", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "¿Estás seguro que querés eliminar este estado?", "confirmations.delete_list.confirm": "Eliminar", "confirmations.delete_list.message": "¿Estás seguro que querés eliminar permanentemente esta lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Rechazar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} es software libre. Podés contribuir o informar errores en {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Ver contexto", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Agregar a lista", "lists.account.remove": "Quitar de lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "¿Querés ocultar las notificaciones de este usuario?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Redactar un nuevo toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dominios ocultos", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritos", "navigation_bar.filters": "Palabras silenciadas", "navigation_bar.follow_requests": "Solicitudes de seguimiento", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Acerca de este servidor", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atajos", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Cerrar sesión", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuarios silenciados", "navigation_bar.pins": "Toots fijados", "navigation_bar.preferences": "Configuración", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguridad", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refrescar", "poll.total_votes": "{count, plural, one {# voto} other {# votos}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Agregar una encuesta", "poll_button.remove_poll": "Quitar encuesta", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Cargando…", "regeneration_indicator.sublabel": "¡Se está preparando tu línea temporal principal!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "recién", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancelar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Reenviar a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Buscar", - "search_popout.search_format": "Formato de búsqueda avanzada", - "search_popout.tips.full_text": "Las búsquedas de texto simple devuelven los estados que escribiste, los marcados como favoritos, los retooteados o en los que te mencionaron, así como nombres usuarios, nombres mostrados y etiquetas.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estado", - "search_popout.tips.user": "usuario", "search_results.accounts": "Gente", "search_results.hashtags": "Etiquetas", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/es.json b/app/soapbox/locales/es.json index 3258ec0b6..8e4f5cb89 100644 --- a/app/soapbox/locales/es.json +++ b/app/soapbox/locales/es.json @@ -8,6 +8,7 @@ "account.block_domain": "Ocultar todo de {domain}", "account.blocked": "Bloqueado", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Este usuario todavía no sigue a nadie.", "account.follows_you": "Te sigue", "account.hide_reblogs": "Ocultar retoots de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "El proprietario de este link fue comprobado el {date}", "account.locked_info": "El estado de privacidad de esta cuenta està configurado como bloqueado. El proprietario debe revisar manualmente quien puede seguirle.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se ha mudado a:", "account.mute": "Silenciar a @{name}", "account.muted": "Silenciado", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots con respuestas", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Cerrar", "bundle_modal_error.message": "Algo salió mal al cargar este componente.", "bundle_modal_error.retry": "Inténtalo de nuevo", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Usuarios bloqueados", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Línea de tiempo local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mensajes directos", + "column.directory": "Browse profiles", "column.domain_blocks": "Dominios ocultados", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Solicitudes de seguimiento", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Inicio", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Usuarios silenciados", "column.notifications": "Notificaciones", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Línea de tiempo federada", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Atrás", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Ocultar configuración", "column_header.show_settings": "Mostrar ajustes", "community.column_settings.media_only": "Solo media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.option_placeholder": "Elección {number}", "compose_form.poll.remove_option": "Eliminar esta opción", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tootear", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquear y Reportar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "¿Estás seguro de que quieres bloquear a {name}?", "confirmations.delete.confirm": "Eliminar", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "¿Estás seguro de que quieres borrar este toot?", "confirmations.delete_list.confirm": "Eliminar", "confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Rechazar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} es software libre. Puedes contribuir o reportar errores en {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Ver contexto", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Añadir a lista", "lists.account.remove": "Quitar de lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Ocultar notificaciones de este usuario?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Escribir un nuevo toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dominios ocultos", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritos", "navigation_bar.filters": "Palabras silenciadas", "navigation_bar.follow_requests": "Solicitudes para seguirte", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Información adicional", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atajos", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Cerrar sesión", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuarios silenciados", "navigation_bar.pins": "Toots fijados", "navigation_bar.preferences": "Preferencias", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguridad", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Actualizar", "poll.total_votes": "{count, plural, one {# voto} other {# votos}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Añadir una encuesta", "poll_button.remove_poll": "Eliminar encuesta", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Cargando…", "regeneration_indicator.sublabel": "¡Tu historia de inicio se está preparando!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "ahora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancelar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Reenviar a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Buscar", - "search_popout.search_format": "Formato de búsqueda avanzada", - "search_popout.tips.full_text": "Búsquedas de texto recuperan posts que has escrito, marcado como favoritos, retooteado o en los que has sido mencionado, así como usuarios, nombres y hashtags.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estado", - "search_popout.tips.user": "usuario", "search_results.accounts": "Gente", "search_results.hashtags": "Etiquetas", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/et.json b/app/soapbox/locales/et.json index 68c4a3d39..99272c6be 100644 --- a/app/soapbox/locales/et.json +++ b/app/soapbox/locales/et.json @@ -8,6 +8,7 @@ "account.block_domain": "Peida kõik domeenist {domain}", "account.blocked": "Blokeeritud", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "See kasutaja ei jälgi veel kedagi.", "account.follows_you": "Jälgib sind", "account.hide_reblogs": "Peida upitused kasutajalt @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Selle lingi autorsust kontrolliti {date}", "account.locked_info": "Selle konto privaatsus on lukustatud. Omanik vaatab manuaalselt üle, kes teda jägida saab.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} on kolinud:", "account.mute": "Vaigista @{name}", "account.muted": "Vaigistatud", + "account.never_active": "Never", "account.posts": "Tuututused", "account.posts_with_replies": "Tuututused ja vastused", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Sulge", "bundle_modal_error.message": "Selle komponendi laadimisel läks midagi viltu.", "bundle_modal_error.retry": "Proovi uuesti", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokeeritud kasutajad", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Kohalik ajajoon", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Otsesõnumid", + "column.directory": "Browse profiles", "column.domain_blocks": "Peidetud domeenid", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Jälgimistaotlused", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Kodu", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Nimekirjad", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Vaigistatud kasutajad", "column.notifications": "Teated", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Föderatiivne ajajoon", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tagasi", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Peida sätted", "column_header.show_settings": "Näita sätteid", "community.column_settings.media_only": "Ainult meedia", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Küsitluse kestus", "compose_form.poll.option_placeholder": "Valik {number}", "compose_form.poll.remove_option": "Eemalda see valik", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tuut", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokeeri & Teata", "confirmations.block.confirm": "Blokeeri", "confirmations.block.message": "Oled kindel, et soovid blokkida {name}?", "confirmations.delete.confirm": "Kustuta", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Oled kindel, et soovid selle staatuse kustutada?", "confirmations.delete_list.confirm": "Kustuta", "confirmations.delete_list.message": "Oled kindel, et soovid selle nimekirja püsivalt kustutada?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autoriseeri", "follow_request.reject": "Hülga", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} on avatud lähtekoodiga tarkvara. Saad panustada või teatada probleemidest GitLabis {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Eelmine", "lightbox.view_context": "Vaata konteksti", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Lisa nimistusse", "lists.account.remove": "Eemalda nimistust", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Kas peita teated sellelt kasutajalt?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Koosta uus tuut", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Peidetud domeenid", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Lemmikud", "navigation_bar.filters": "Vaigistatud sõnad", "navigation_bar.follow_requests": "Jälgimistaotlused", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Selle serveri kohta", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Kiirklahvid", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logi välja", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Vaigistatud kasutajad", "navigation_bar.pins": "Kinnitatud tuutid", "navigation_bar.preferences": "Eelistused", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Turvalisus", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Värskenda", "poll.total_votes": "{count, plural, one {# hääl} other {# hääli}}", "poll.vote": "Hääleta", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Lisa küsitlus", "poll_button.remove_poll": "Eemalda küsitlus", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Laeb…", "regeneration_indicator.sublabel": "Sinu kodu voog on ettevalmistamisel!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}p", "relative_time.hours": "{number}t", "relative_time.just_now": "nüüd", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Tühista", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Edasta kasutajale {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Otsi", - "search_popout.search_format": "Täiustatud otsiformaat", - "search_popout.tips.full_text": "Lihtne tekst toob esile staatused mida olete kirjutanud, lisanud lemmikuks, upitanud või olete seal mainitud, ning lisaks veel kattuvad kasutajanimed, kuvanimed ja sildid.", - "search_popout.tips.hashtag": "silt", - "search_popout.tips.status": "staatus", - "search_popout.tips.user": "kasutaja", "search_results.accounts": "Inimesed", "search_results.hashtags": "Sildid", "search_results.statuses": "Tuudid", diff --git a/app/soapbox/locales/eu.json b/app/soapbox/locales/eu.json index bb3e4c746..7a6086cf0 100644 --- a/app/soapbox/locales/eu.json +++ b/app/soapbox/locales/eu.json @@ -8,6 +8,7 @@ "account.block_domain": "Ezkutatu {domain} domeinuko guztia", "account.blocked": "Blokeatuta", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.", "account.follows_you": "Jarraitzen dizu", "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", + "account.last_status": "Last active", "account.link_verified_on": "Esteka honen jabetzaren egiaztaketa data: {date}", "account.locked_info": "Kontu honen pribatutasun egoera blokeatuta gisa ezarri da. Jabeak eskuz erabakitzen du nork jarraitu diezaioken.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} hona migratu da:", "account.mute": "Mututu @{name}", "account.muted": "Mutututa", + "account.never_active": "Never", "account.posts": "Tootak", "account.posts_with_replies": "Toot-ak eta erantzunak", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Itxi", "bundle_modal_error.message": "Zerbait okerra gertatu da osagai hau kargatzean.", "bundle_modal_error.retry": "Saiatu berriro", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokeatutako erabiltzaileak", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Denbora-lerro lokala", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mezu zuzenak", + "column.directory": "Browse profiles", "column.domain_blocks": "Ezkutatutako domeinuak", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Jarraitzeko eskariak", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hasiera", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Zerrendak", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Mutututako erabiltzaileak", "column.notifications": "Jakinarazpenak", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federatutako denbora-lerroa", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Atzera", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Ezkutatu ezarpenak", "column_header.show_settings": "Erakutsi ezarpenak", "community.column_settings.media_only": "Multimedia besterik ez", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Inkestaren iraupena", "compose_form.poll.option_placeholder": "{number}. aukera", "compose_form.poll.remove_option": "Kendu aukera hau", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokeatu eta salatu", "confirmations.block.confirm": "Blokeatu", "confirmations.block.message": "Ziur {name} blokeatu nahi duzula?", "confirmations.delete.confirm": "Ezabatu", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ziur mezu hau ezabatu nahi duzula?", "confirmations.delete_list.confirm": "Ezabatu", "confirmations.delete_list.message": "Ziur behin betiko ezabatu nahi duzula zerrenda hau?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Baimendu", "follow_request.reject": "Ukatu", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} software librea da. Ekarpenak egin ditzakezu edo akatsen berri eman GitLab bidez: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Aurrekoa", "lightbox.view_context": "Ikusi testuingurua", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Gehitu zerrendara", "lists.account.remove": "Kendu zerrendatik", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Ezkutatu erabiltzaile honen jakinarazpenak?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Idatzi toot berria", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Ezkutatutako domeinuak", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Gogokoak", "navigation_bar.filters": "Mutututako hitzak", "navigation_bar.follow_requests": "Jarraitzeko eskariak", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Zerbitzari honi buruz", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Laster-teklak", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Amaitu saioa", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Mutututako erabiltzaileak", "navigation_bar.pins": "Finkatutako toot-ak", "navigation_bar.preferences": "Hobespenak", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Segurtasuna", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Berritu", "poll.total_votes": "{count, plural, one {boto #} other {# boto}}", "poll.vote": "Bozkatu", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Gehitu inkesta bat", "poll_button.remove_poll": "Kendu inkesta", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Kargatzen…", "regeneration_indicator.sublabel": "Zure hasiera-jarioa prestatzen ari da!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}e", "relative_time.hours": "{number}o", "relative_time.just_now": "orain", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Utzi", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Birbidali hona: {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Bilatu", - "search_popout.search_format": "Bilaketa aurreratuaren formatua", - "search_popout.tips.full_text": "Testu hutsarekin zuk idatzitako mezuak, gogokoak, bultzadak edo aipamenak aurkitu ditzakezu, bat datozen erabiltzaile-izenak, pantaila-izenak, eta traolak.", - "search_popout.tips.hashtag": "traola", - "search_popout.tips.status": "mezua", - "search_popout.tips.user": "erabiltzailea", "search_results.accounts": "Jendea", "search_results.hashtags": "Traolak", "search_results.statuses": "Toot-ak", diff --git a/app/soapbox/locales/fa.json b/app/soapbox/locales/fa.json index 72987d59a..7429fb5c2 100644 --- a/app/soapbox/locales/fa.json +++ b/app/soapbox/locales/fa.json @@ -8,6 +8,7 @@ "account.block_domain": "پنهان‌سازی همه چیز از سرور {domain}", "account.blocked": "مسدود شده", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "این کاربر هنوز هیچ کسی را پی نمی‌گیرد.", "account.follows_you": "پیگیر شماست", "account.hide_reblogs": "پنهان کردن بازبوق‌های @{name}", + "account.last_status": "Last active", "account.link_verified_on": "مالکیت این نشانی در تاریخ {date} بررسی شد", "account.locked_info": "این حساب خصوصی است. صاحب این حساب تصمیم می‌گیرد که چه کسی می‌تواند پیگیرش باشد.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} منتقل شده است به:", "account.mute": "بی‌صدا کردن @{name}", "account.muted": "بی‌صداشده", + "account.never_active": "Never", "account.posts": "نوشته‌ها", "account.posts_with_replies": "نوشته‌ها و پاسخ‌ها", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "بستن", "bundle_modal_error.message": "هنگام بازکردن این بخش خطایی رخ داد.", "bundle_modal_error.retry": "تلاش دوباره", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "کاربران مسدودشده", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "نوشته‌های محلی", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "پیغام‌های خصوصی", + "column.directory": "Browse profiles", "column.domain_blocks": "دامین‌های پنهان‌شده", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "درخواست‌های پیگیری", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "خانه", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "فهرست‌ها", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "کاربران بی‌صداشده", "column.notifications": "اعلان‌ها", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "نوشته‌های همه‌جا", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "بازگشت", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "نهفتن تنظیمات", "column_header.show_settings": "نمایش تنظیمات", "community.column_settings.media_only": "فقط عکس و ویدیو", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "مدت نظرسنجی", "compose_form.poll.option_placeholder": "گزینهٔ {number}", "compose_form.poll.remove_option": "حذف این گزینه", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "بوق", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "مسدودسازی و گزارش", "confirmations.block.confirm": "مسدود کن", "confirmations.block.message": "آیا واقعاً می‌خواهید {name} را مسدود کنید؟", "confirmations.delete.confirm": "پاک کن", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "آیا واقعاً می‌خواهید این نوشته را پاک کنید؟", "confirmations.delete_list.confirm": "پاک کن", "confirmations.delete_list.message": "آیا واقعاً می‌خواهید این فهرست را برای همیشه پاک کنید؟", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "اجازه دهید", "follow_request.reject": "اجازه ندهید", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "ماستدون یک نرم‌افزار آزاد است. می‌توانید در ساخت آن مشارکت کنید یا مشکلاتش را در {code_link} (v{code_version}) گزارش دهید.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "قبلی", "lightbox.view_context": "نمایش گفتگو", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "افزودن به فهرست", "lists.account.remove": "پاک‌کردن از فهرست", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "اعلان‌های این کاربر پنهان شود؟", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "نوشتن بوق تازه", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "دامین‌های پنهان‌شده", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "پسندیده‌ها", "navigation_bar.filters": "واژگان بی‌صداشده", "navigation_bar.follow_requests": "درخواست‌های پیگیری", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "دربارهٔ این سرور", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "میان‌برهای صفحه‌کلید", "navigation_bar.lists": "Lists", "navigation_bar.logout": "خروج", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "کاربران بی‌صداشده", "navigation_bar.pins": "نوشته‌های ثابت", "navigation_bar.preferences": "ترجیحات", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "امنیت", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "به‌روزرسانی", "poll.total_votes": "{count, plural, one {# رأی} other {# رأی}}", "poll.vote": "رأی", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "افزودن نظرسنجی", "poll_button.remove_poll": "حذف نظرسنجی", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "در حال باز شدن…", "regeneration_indicator.sublabel": "این فهرست دارد آماده می‌شود!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} روز", "relative_time.hours": "{number} ساعت", "relative_time.just_now": "الان", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "لغو", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "فرستادن به {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "جستجو", - "search_popout.search_format": "راهنمای جستجوی پیشرفته", - "search_popout.tips.full_text": "جستجوی متنی ساده می‌تواند بوق‌هایی که شما نوشته‌اید، پسندیده‌اید، بازبوقیده‌اید، یا در آن‌ها از شما نام برده شده است را پیدا کند. همچنین نام‌های کاربری، نام نمایش‌یافته، و هشتگ‌ها را هم شامل می‌شود.", - "search_popout.tips.hashtag": "برچسب", - "search_popout.tips.status": "نوشته", - "search_popout.tips.user": "کاربر", "search_results.accounts": "افراد", "search_results.hashtags": "برچسب‌ها", "search_results.statuses": "بوق‌ها", diff --git a/app/soapbox/locales/fi.json b/app/soapbox/locales/fi.json index 0d84900e7..657fea6d0 100644 --- a/app/soapbox/locales/fi.json +++ b/app/soapbox/locales/fi.json @@ -8,6 +8,7 @@ "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", "account.blocked": "Estetty", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.", "account.follows_you": "Seuraa sinua", "account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Tämän linkin omistaja tarkistettiin {date}", "account.locked_info": "Tämän tili on yksityinen. Käyttäjä vahvistaa itse kuka voi seurata häntä.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} on muuttanut instanssiin:", "account.mute": "Mykistä @{name}", "account.muted": "Mykistetty", + "account.never_active": "Never", "account.posts": "Tuuttaukset", "account.posts_with_replies": "Tuuttaukset ja vastaukset", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Sulje", "bundle_modal_error.message": "Jokin meni vikaan komponenttia ladattaessa.", "bundle_modal_error.retry": "Yritä uudestaan", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Estetyt käyttäjät", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Paikallinen aikajana", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Viestit", + "column.directory": "Browse profiles", "column.domain_blocks": "Piilotetut verkkotunnukset", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Seuraamispyynnöt", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Koti", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listat", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Mykistetyt käyttäjät", "column.notifications": "Ilmoitukset", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Yleinen aikajana", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Takaisin", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Piilota asetukset", "column_header.show_settings": "Näytä asetukset", "community.column_settings.media_only": "Vain media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Äänestyksen kesto", "compose_form.poll.option_placeholder": "Valinta numero", "compose_form.poll.remove_option": "Poista tämä valinta", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tuuttaa", "compose_form.publish_loud": "Julkista!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Estä ja raportoi", "confirmations.block.confirm": "Estä", "confirmations.block.message": "Haluatko varmasti estää käyttäjän {name}?", "confirmations.delete.confirm": "Poista", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Haluatko varmasti poistaa tämän tilapäivityksen?", "confirmations.delete_list.confirm": "Poista", "confirmations.delete_list.message": "Haluatko varmasti poistaa tämän listan kokonaan?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Valtuuta", "follow_request.reject": "Hylkää", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitLabissa: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Edellinen", "lightbox.view_context": "Näytä kontekstissa", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Lisää listaan", "lists.account.remove": "Poista listasta", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Piilota tältä käyttäjältä tulevat ilmoitukset?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Kirjoita uusi tuuttaus", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Piilotetut verkkotunnukset", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Suosikit", "navigation_bar.filters": "Mykistetyt sanat", "navigation_bar.follow_requests": "Seuraamispyynnöt", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Tietoa tästä instanssista", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Näppäinkomennot", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Kirjaudu ulos", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Mykistetyt käyttäjät", "navigation_bar.pins": "Kiinnitetyt tuuttaukset", "navigation_bar.preferences": "Asetukset", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Tunnukset", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Päivitä", "poll.total_votes": "{count, plural, one {# ääni} other {# ääntä}}", "poll.vote": "Äänestä", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Lisää kysely", "poll_button.remove_poll": "Poista kysely", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Ladataan…", "regeneration_indicator.sublabel": "Kotinäkymääsi valmistellaan!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} pv", "relative_time.hours": "{number} h", "relative_time.just_now": "nyt", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Peruuta", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Välitä kohteeseen {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Hae", - "search_popout.search_format": "Tarkennettu haku", - "search_popout.tips.full_text": "Tekstihaku palauttaa tilapäivitykset, jotka olet kirjoittanut, lisännyt suosikkeihisi, boostannut tai joissa sinut mainitaan, sekä tekstin sisältävät käyttäjänimet, nimimerkit ja hastagit.", - "search_popout.tips.hashtag": "hashtagit", - "search_popout.tips.status": "tila", - "search_popout.tips.user": "käyttäjä", "search_results.accounts": "Ihmiset", "search_results.hashtags": "Hashtagit", "search_results.statuses": "Tuuttaukset", diff --git a/app/soapbox/locales/fr.json b/app/soapbox/locales/fr.json index ebfb14601..192ff71da 100644 --- a/app/soapbox/locales/fr.json +++ b/app/soapbox/locales/fr.json @@ -8,6 +8,7 @@ "account.block_domain": "Tout masquer venant de {domain}", "account.blocked": "Bloqué", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Cet·te utilisateur·rice ne suit personne pour l’instant.", "account.follows_you": "Vous suit", "account.hide_reblogs": "Masquer les partages de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La propriété de ce lien a été vérifiée le {date}", "account.locked_info": "Ce compte est verrouillé. Son propriétaire approuve manuellement qui peut le ou la suivre.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} a déménagé vers :", "account.mute": "Masquer @{name}", "account.muted": "Silencé", + "account.never_active": "Never", "account.posts": "Pouets", "account.posts_with_replies": "Pouets et réponses", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Fermer", "bundle_modal_error.message": "Une erreur s’est produite lors du chargement de ce composant.", "bundle_modal_error.retry": "Réessayer", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Comptes bloqués", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Fil public local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Messages privés", + "column.directory": "Browse profiles", "column.domain_blocks": "Domaines cachés", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Demandes de suivi", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Accueil", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listes", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Comptes masqués", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Fil public global", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Retour", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Masquer les paramètres", "column_header.show_settings": "Afficher les paramètres", "community.column_settings.media_only": "Média uniquement", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durée du sondage", "compose_form.poll.option_placeholder": "Choix {number}", "compose_form.poll.remove_option": "Supprimer ce choix", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Pouet", "compose_form.publish_loud": "{publish} !", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquer et signaler", "confirmations.block.confirm": "Bloquer", "confirmations.block.message": "Confirmez-vous le blocage de {name} ?", "confirmations.delete.confirm": "Supprimer", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Confirmez-vous la suppression de ce pouet ?", "confirmations.delete_list.confirm": "Supprimer", "confirmations.delete_list.message": "Êtes-vous sûr·e de vouloir supprimer définitivement cette liste ?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Accepter", "follow_request.reject": "Rejeter", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} est un logiciel libre. Vous pouvez contribuer et envoyer vos commentaires et rapports de bogues via {code_link} (v{code_version}) sur GitLab.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Précédent", "lightbox.view_context": "Voir le contexte", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Ajouter à la liste", "lists.account.remove": "Supprimer de la liste", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Masquer les notifications de cette personne ?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Rédiger un nouveau toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domaines cachés", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoris", "navigation_bar.filters": "Mots silenciés", "navigation_bar.follow_requests": "Demandes de suivi", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "À propos de ce serveur", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Raccourcis clavier", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Déconnexion", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Comptes masqués", "navigation_bar.pins": "Pouets épinglés", "navigation_bar.preferences": "Préférences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sécurité", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Actualiser", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Voter", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Ajouter un sondage", "poll_button.remove_poll": "Supprimer le sondage", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Chargement…", "regeneration_indicator.sublabel": "Le flux de votre page principale est en cours de préparation !", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} j", "relative_time.hours": "{number} h", "relative_time.just_now": "à l’instant", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Annuler", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Transférer à {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Rechercher", - "search_popout.search_format": "Recherche avancée", - "search_popout.tips.full_text": "Les textes simples retournent les pouets que vous avez écris, mis en favori, épinglés, ou ayant été mentionnés, ainsi que les identifiants, les noms affichés, et les hashtags des personnes et messages correspondant.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "statuts", - "search_popout.tips.user": "utilisateur⋅ice", "search_results.accounts": "Comptes", "search_results.hashtags": "Hashtags", "search_results.statuses": "Pouets", diff --git a/app/soapbox/locales/ga.json b/app/soapbox/locales/ga.json index ff9c45ab7..da12d9295 100644 --- a/app/soapbox/locales/ga.json +++ b/app/soapbox/locales/ga.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/gl.json b/app/soapbox/locales/gl.json index 1849f2285..947c88778 100644 --- a/app/soapbox/locales/gl.json +++ b/app/soapbox/locales/gl.json @@ -8,6 +8,7 @@ "account.block_domain": "Ocultar calquer contido de {domain}", "account.blocked": "Bloqueada", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Esta usuaria aínda non segue a ninguén.", "account.follows_you": "Séguete", "account.hide_reblogs": "Ocultar repeticións de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "A propiedade de esta ligazón foi comprobada en {date}", "account.locked_info": "O estado da intimidade de esta conta estableceuse en pechado. A persoa dona da conta revisa quen pode seguila.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} marchou a:", "account.mute": "Acalar @{name}", "account.muted": "Acalada", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots e respostas", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Pechar", "bundle_modal_error.message": "Algo fallou mentras se cargaba este compoñente.", "bundle_modal_error.retry": "Inténteo de novo", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Usuarias bloqueadas", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Liña temporal local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mensaxes directas", + "column.directory": "Browse profiles", "column.domain_blocks": "Dominios agochados", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Peticións de seguimento", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Inicio", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Usuarias acaladas", "column.notifications": "Notificacións", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Liña temporal federada", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Atrás", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Agochar axustes", "column_header.show_settings": "Mostras axustes", "community.column_settings.media_only": "Só medios", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duración da sondaxe", "compose_form.poll.option_placeholder": "Opción {number}", "compose_form.poll.remove_option": "Eliminar esta opción", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquear e Informar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Está segura de querer bloquear a {name}?", "confirmations.delete.confirm": "Borrar", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Está segura de que quere eliminar este estado?", "confirmations.delete_list.confirm": "Eliminar", "confirmations.delete_list.message": "Estás seguro de que queres eliminar permanentemente esta lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Rexeitar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} é software de código aberto. Pode contribuír ou informar de fallos en {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Ver contexto", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Engadir á lista", "lists.account.remove": "Eliminar da lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Esconder notificacións deste usuario?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Escribir novo toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dominios agochados", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritas", "navigation_bar.filters": "Palabras acaladas", "navigation_bar.follow_requests": "Peticións de seguimento", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Sobre este servidor", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atallos", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Sair", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuarias acaladas", "navigation_bar.pins": "Mensaxes fixadas", "navigation_bar.preferences": "Preferencias", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguridade", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Actualizar", "poll.total_votes": "{count, plural, one {# voto} outros {# votos}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Engadir sondaxe", "poll_button.remove_poll": "Eliminar sondaxe", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Cargando…", "regeneration_indicator.sublabel": "Estase a preparar a súa liña temporal de inicio!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "agora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancelar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Reenviar a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Buscar", - "search_popout.search_format": "Formato de busca avanzada", - "search_popout.tips.full_text": "Texto simple devolve estados que vostede escribeu, promoveu, marcou favoritos, ou foi mencionada, así como nomes de usuaria coincidentes, nomes públicos e etiquetas.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estado", - "search_popout.tips.user": "usuaria", "search_results.accounts": "Xente", "search_results.hashtags": "Etiquetas", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 7d9d9194b..a454c56de 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -1,18 +1,19 @@ { - "about.also_available": "Available in:", - "accordion.collapse": "Collapse", - "accordion.expand": "Expand", + "about.also_available": "זמין ב", + "accordion.collapse": "כווץ", + "accordion.expand": "הרחבה", "account.add_or_remove_from_list": "הוסף או הסר מהרשימות", "account.badges.bot": "בוט", "account.block": "חסימת @{name}", "account.block_domain": "להסתיר הכל מהקהילה {domain}", "account.blocked": "חסום", - "account.chat": "Chat with @{name}", - "account.column_settings.title": "Acccount timeline settings", - "account.deactivated": "Deactivated", - "account.deactivated_description": "This account has been deactivated.", - "account.direct": "Direct Message @{name}", - "account.domain_blocked": "הדומיין חסוי", + "account.chat": "צ'אט עם @{name}", + "account.column_settings.description": ".ההגדרות האלו מיושמות על כל ציר הזמן", + "account.column_settings.title": "הגדרות ציר זמן של המשתמש", + "account.deactivated": "מושבת", + "account.deactivated_description": "החשבון הזה הושבת", + "account.direct": "הודעה ישירה @{name}", + "account.domain_blocked": "הדומיין חסום", "account.edit_profile": "עריכת פרופיל", "account.endorse": "הצג בפרופיל", "account.follow": "מעקב", @@ -22,293 +23,341 @@ "account.follows.empty": "משתמש זה לא עוקב אחר אף אחד עדיין.", "account.follows_you": "במעקב אחריך", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", + "account.last_status": "פעיל לאחרונה", "account.link_verified_on": "בעלות על הקישור הזה נבדקה לאחרונה ב{date}", - "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", - "account.login": "Log in", + "account.locked_info": "החשבון הוגדר כנעול. בעל החשבון בודק ידנית מי יכול לעקוב אחריו", + "account.login": "התחברות", "account.media": "מדיה", - "account.member_since": "Joined {date}", + "account.member_since": "הצטרף {date}", "account.mention": "אזכור של", "account.moved_to": "החשבון {name} הועבר אל:", "account.mute": "להשתיק את @{name}", - "account.muted": "Muted", - "account.posts": "הודעות", - "account.posts_with_replies": "Toots with replies", - "account.profile": "Profile", - "account.register": "Sign up", - "account.remote_follow": "Remote follow", + "account.muted": "מושתק", + "account.never_active": "אף פעם", + "account.posts": "פוסטים", + "account.posts_with_replies": "פוסטים עם תגובות", + "account.profile": "פרופיל", + "account.register": "הרשם", + "account.remote_follow": "מעקב מרחוק", "account.report": "לדווח על @{name}", "account.requested": "בהמתנה לאישור", - "account.requested_small": "Awaiting approval", + "account.requested_small": "מחכה לאישור", "account.share": "לשתף את הפרופיל של @{name}", "account.show_reblogs": "להראות הדהודים מאת @{name}", - "account.subscribe": "Subscribe to notifications from @{name}", - "account.subscribed": "Subscribed", + "account.subscribe": "הרשם להתראות מאת @{name}", + "account.subscribed": "רשום", "account.unblock": "הסרת חסימה מעל @{name}", "account.unblock_domain": "הסר חסימה מקהילת {domain}", "account.unendorse": "לא להציג בפרופיל", "account.unfollow": "הפסקת מעקב", "account.unmute": "הפסקת השתקת @{name}", - "account.unsubscribe": "Unsubscribe to notifications from @{name}", - "account_gallery.none": "No media to show.", - "account_search.placeholder": "Search for an account", - "account_timeline.column_settings.show_pinned": "Show pinned posts", - "admin.awaiting_approval.approved_message": "{acct} was approved!", - "admin.awaiting_approval.empty_message": "There is nobody waiting for approval. When a new user signs up, you can review them here.", - "admin.awaiting_approval.rejected_message": "{acct} was rejected.", - "admin.dashboard.registration_mode.approval_hint": "Users can sign up, but their account only gets activated when an admin approves it.", - "admin.dashboard.registration_mode.approval_label": "Approval Required", - "admin.dashboard.registration_mode.closed_hint": "Nobody can sign up. You can still invite people.", - "admin.dashboard.registration_mode.closed_label": "Closed", - "admin.dashboard.registration_mode.open_hint": "Anyone can join.", - "admin.dashboard.registration_mode.open_label": "Open", - "admin.dashboard.registration_mode_label": "Registrations", - "admin.dashboard.settings_saved": "Settings saved!", - "admin.dashcounters.domain_count_label": "peers", - "admin.dashcounters.mau_label": "monthly active users", - "admin.dashcounters.retention_label": "user retention", - "admin.dashcounters.status_count_label": "posts", - "admin.dashcounters.user_count_label": "total users", - "admin.dashwidgets.email_list_header": "Email list", - "admin.dashwidgets.software_header": "Software", - "admin.latest_accounts_panel.expand_message": "Click to see {count} more {count, plural, one {account} other {accounts}}", - "admin.latest_accounts_panel.title": "Latest Accounts", - "admin.moderation_log.empty_message": "You have not performed any moderation actions yet. When you do, a history will be shown here.", - "admin.reports.actions.close": "Close", - "admin.reports.actions.view_status": "View post", - "admin.reports.empty_message": "There are no open reports. If a user gets reported, they will show up here.", - "admin.reports.report_closed_message": "Report on @{name} was closed", - "admin.reports.report_title": "Report on {acct}", - "admin.statuses.actions.delete_status": "Delete post", - "admin.statuses.actions.mark_status_not_sensitive": "Mark post not sensitive", - "admin.statuses.actions.mark_status_sensitive": "Mark post sensitive", - "admin.statuses.status_deleted_message": "Post by @{acct} was deleted", - "admin.statuses.status_marked_message_not_sensitive": "Post by @{acct} was marked not sensitive", - "admin.statuses.status_marked_message_sensitive": "Post by @{acct} was marked sensitive", - "admin.user_index.empty": "No users found.", - "admin.user_index.search_input_placeholder": "Who are you looking for?", - "admin.users.actions.deactivate_user": "Deactivate @{name}", - "admin.users.actions.delete_user": "Delete @{name}", - "admin.users.actions.demote_to_moderator": "Demote @{name} to a moderator", - "admin.users.actions.demote_to_moderator_message": "@{acct} was demoted to a moderator", - "admin.users.actions.demote_to_user": "Demote @{name} to a regular user", - "admin.users.actions.demote_to_user_message": "@{acct} was demoted to a regular user", - "admin.users.actions.promote_to_admin": "Promote @{name} to an admin", - "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", - "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", - "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", - "admin.users.actions.unverify_user": "Unverify @{name}", - "admin.users.actions.verify_user": "Verify @{name}", - "admin.users.user_deactivated_message": "@{acct} was deactivated", - "admin.users.user_deleted_message": "@{acct} was deleted", - "admin.users.user_unverified_message": "@{acct} was unverified", - "admin.users.user_verified_message": "@{acct} was verified", - "admin_nav.awaiting_approval": "Awaiting Approval", - "admin_nav.dashboard": "Dashboard", - "admin_nav.reports": "Reports", - "alert.unexpected.clear_cookies": "clear cookies and browser data", - "alert.unexpected.help_text": "If the problem persists, please notify a site admin with a screenshot and information about your web browser. You may also {clear_cookies} (this will log you out).", + "account.unsubscribe": "בטל הרשמה מ@{name}", + "account_gallery.none": "אין מדיה להראות.", + "account_search.placeholder": "חפש משתמש", + "account_timeline.column_settings.show_pinned": "הצג הודעות מוצמדות", + "admin.awaiting_approval.approved_message": "{acct} הואשר!", + "admin.awaiting_approval.empty_message": "אף אחד לא מחכה לאישור. כאשר משתמש חדש יירשם, תוכל לבחון אותו פה.", + "admin.awaiting_approval.rejected_message": "{acct} נדחה", + "admin.dashboard.registration_mode.approval_hint": "משתמשים יכולים להרשם, אבל החשבון שלהם מופעל רק כשמנהל יאשר אותו.", + "admin.dashboard.registration_mode.approval_label": "נדרש אישור", + "admin.dashboard.registration_mode.closed_hint": "אף אחד לא יכול להרשם. אתה עדיין יכול להזמין אנשים.", + "admin.dashboard.registration_mode.closed_label": "סגור להרשמה", + "admin.dashboard.registration_mode.open_hint": "כל אחד יכול להצטרף", + "admin.dashboard.registration_mode.open_label": "פתוח", + "admin.dashboard.registration_mode_label": "הרשמות", + "admin.dashboard.settings_saved": "ההגדרות נשמרו!", + "admin.dashcounters.domain_count_label": "עמיתים", + "admin.dashcounters.mau_label": "משתמשים פעילים חודשית", + "admin.dashcounters.retention_label": "שימור משתמשים", + "admin.dashcounters.status_count_label": "פוסטים", + "admin.dashcounters.user_count_label": "סך כל המשתמשים", + "admin.dashwidgets.email_list_header": "רשימת אימייל", + "admin.dashwidgets.software_header": "תוכנה", + "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {חשבון} other {חשבונות}}", + "admin.latest_accounts_panel.title": "חשבונות אחרונים", + "admin.moderation_log.empty_message": "לא ביצעת פעולות ניהול עדיין. כשתבצע, ההיסטוריה תהיה כאן.", + "admin.reports.actions.close": "סגור", + "admin.reports.actions.view_status": "צפה בפוסט", + "admin.reports.empty_message": "אין דוחות פתוחים. אם משתמש יידווח, הוא יופיע כאן.", + "admin.reports.report_closed_message": "דיווח על @{name} נסגר", + "admin.reports.report_title": "דיווח על {acct}", + "admin.statuses.actions.delete_status": "מחק פוסט", + "admin.statuses.actions.mark_status_not_sensitive": "סמן פוסט כלא רגיש", + "admin.statuses.actions.mark_status_sensitive": "סמן פוסט כרגיש", + "admin.statuses.status_deleted_message": "פוסט מ@{acct} נמחק", + "admin.statuses.status_marked_message_not_sensitive": "פוסטים מ@{acct} סומנו כלא רגישים", + "admin.statuses.status_marked_message_sensitive": "פוסטים מ@{acct} סומנו כרגישים", + "admin.user_index.empty": "לא נמצאו משתמשים.", + "admin.user_index.search_input_placeholder": "את מי אתה מחפש?", + "admin.users.actions.deactivate_user": "השבת @{name}", + "admin.users.actions.delete_user": "מחק @{name}", + "admin.users.actions.demote_to_moderator": "הורד @{name} בדרגה למנהל", + "admin.users.actions.demote_to_moderator_message": "@{acct} הורד בדרגה למנהל", + "admin.users.actions.demote_to_user": "הורד @{name} בדרגה למשתמש רגיל", + "admin.users.actions.demote_to_user_message": "@{acct} הורד בדרגה למשתמש רגיל", + "admin.users.actions.promote_to_admin": "קדם @{name} לאדמין", + "admin.users.actions.promote_to_admin_message": "@{acct} קודם לאדמין", + "admin.users.actions.promote_to_moderator": "קדם @{name} למנהל", + "admin.users.actions.promote_to_moderator_message": "@{acct} קודם למנהל", + "admin.users.actions.suggest_user": "הצע @{name}", + "admin.users.actions.unsuggest_user": "הסר הצעה @{name}", + "admin.users.actions.unverify_user": "הסר אימות @{name}", + "admin.users.actions.verify_user": "אמת @{name}", + "admin.users.user_deactivated_message": "@{acct} הושבת", + "admin.users.user_deleted_message": "@{acct} נמחק", + "admin.users.user_suggested_message": "הוצע @{acct}", + "admin.users.user_unsuggested_message": "‎@{acct} הוסר מהצעה", + "admin.users.user_unverified_message": "@{acct} הוסר מאימות", + "admin.users.user_verified_message": "@{acct} אומת", + "admin_nav.awaiting_approval": "מחכה לאישור", + "admin_nav.dashboard": "לוח מחוונים", + "admin_nav.reports": "דיווחים", + "alert.unexpected.clear_cookies": "נקה קובצי 'עוגיות' ונתוני דפדפן", + "alert.unexpected.help_text": "אם הבעיה נמשכת, אנא הודע למנהל האתר עם צילום מסך ומידע על דפדפן האינטרנט שלך. אתה יכול גם {clear_cookies} (זה יוציא אותך מהחשבון).", "alert.unexpected.message": "אירעה שגיאה בלתי צפויה.", - "alert.unexpected.return_home": "Return Home", + "alert.unexpected.return_home": "חזור הביתה", "alert.unexpected.title": "אופס!", - "aliases.account.add": "Create alias", - "aliases.account_label": "Old account:", - "aliases.aliases_list_delete": "Unlink alias", - "aliases.search": "Search your old account", - "aliases.success.add": "Account alias created successfully", - "aliases.success.remove": "Account alias removed successfully", - "auth.invalid_credentials": "Wrong username or password", - "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", - "backups.actions.create": "Create backup", - "backups.empty_message": "No backups found. {action}", - "backups.empty_message.action": "Create one now?", - "backups.pending": "Pending", + "aliases.account.add": "צור כינוי", + "aliases.account_label": "חשבון ישן:", + "aliases.aliases_list_delete": "בטל קישור בכינוי", + "aliases.search": "חפש חשבון ישן", + "aliases.success.add": "כינוי חשבון נוצר בהצלחה", + "aliases.success.remove": "כינוי חשבון הוסר בהצלחה", + "app_create.name_label": "שם אפליקציה", + "app_create.name_placeholder": "לדוגמא 'סבוניה'", + "app_create.redirect_uri_label": "נתב URIs", + "app_create.restart": "צור עוד", + "app_create.results.app_label": "אפליקציה", + "app_create.results.explanation_text": "יצרת אפליקציה ואסימון חדשים! אנא העתק את האישורים למקום כלשהו; לא תראה אותם שוב לאחר ניווט מדף זה.", + "app_create.results.explanation_title": "האפליקציה נוצרה בהצלחה", + "app_create.results.token_label": "אסימון OAuth", + "app_create.scopes_label": "היקפים", + "app_create.scopes_placeholder": "למשל 'קרא כתוב עקוב'", + "app_create.submit": "צור אפליקציה", + "app_create.website_label": "אתר", + "auth.invalid_credentials": "שם משתמש או סיסמא שגוי", + "auth.logged_out": "מנותק", + "backups.actions.create": "צור גיבוי", + "backups.empty_message": "לא נמצאו גיבויים. {action}", + "backups.empty_message.action": "האם ליצור אחד עכשיו?", + "backups.pending": "בהמתנה", "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה", "bundle_column_error.body": "משהו השתבש בעת הצגת הרכיב הזה.", "bundle_column_error.retry": "לנסות שוב", - "bundle_column_error.title": "Network error", + "bundle_column_error.title": "תקלת רשת", "bundle_modal_error.close": "לסגור", "bundle_modal_error.message": "משהו השתבש בעת טעינת הרכיב הזה.", "bundle_modal_error.retry": "לנסות שוב", - "chat_box.actions.send": "Send", - "chat_box.input.placeholder": "Send a message…", - "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", - "chat_panels.main_window.title": "Chats", - "chats.actions.delete": "Delete message", - "chats.actions.more": "More", - "chats.actions.report": "Report user", - "chats.audio_toggle_off": "Audio notification off", - "chats.audio_toggle_on": "Audio notification on", - "chats.dividers.today": "Today", - "chats.search_placeholder": "Start a chat with…", - "column.admin.awaiting_approval": "Awaiting Approval", - "column.admin.dashboard": "Dashboard", - "column.admin.moderation_log": "Moderation Log", - "column.admin.reports": "Reports", - "column.admin.reports.menu.moderation_log": "Moderation Log", - "column.aliases": "Account aliases", - "column.aliases.create_error": "Error creating alias", - "column.aliases.delete": "Delete", - "column.aliases.delete_error": "Error deleting alias", - "column.aliases.subheading_add_new": "Add New Alias", - "column.aliases.subheading_aliases": "Current aliases", - "column.backups": "Backups", + "chat_box.actions.close": "סגור צ'אט", + "chat_box.actions.send": "שליחה", + "chat_box.input.placeholder": "שלח הודעה", + "chat_panels.main_window.empty": "לא נמצאו צ'אטים. כדי להתחיל צ'אט, בקר בפרופיל של משתמש.", + "chat_panels.main_window.title": "צ'אטים", + "chats.actions.delete": "מחק הודעה", + "chats.actions.more": "עוד", + "chats.actions.report": "דווח על משתמש", + "chats.attachment": "צירוף", + "chats.attachment_image": "תמונה", + "chats.audio_toggle_off": "התראת שמע כבויה", + "chats.audio_toggle_on": "התראת שמע דלוקה", + "chats.dividers.today": "היום", + "chats.search_placeholder": "התחל בצ'אט עם", + "column.admin.awaiting_approval": "מחכה לאישור", + "column.admin.dashboard": "לוח מחוונים", + "column.admin.moderation_log": "יומן ניהול", + "column.admin.reports": "דיווחים", + "column.admin.reports.menu.moderation_log": "יומן ניהול", + "column.admin.users": "משתמשים", + "column.aliases": "כינויים בחשבון", + "column.aliases.create_error": "שגיאה ביצירת כינוי", + "column.aliases.delete": "מחק כינוי", + "column.aliases.delete_error": "שגיאה במחיקת כינוי", + "column.aliases.subheading_add_new": "הוסף כינוי חדש", + "column.aliases.subheading_aliases": "כינויים נוכחיים", + "column.app_create": "צור אפליקציה", + "column.backups": "גיבויים", "column.blocks": "חסימות", - "column.bookmarks": "Bookmarks", - "column.chats": "Chats", + "column.bookmarks": "סימניות", + "column.chats": "צ'אטים", "column.community": "ציר זמן מקומי", - "column.crypto_donate": "Donate Cryptocurrency", - "column.direct": "Direct messages", - "column.domain_blocks": "Hidden domains", - "column.edit_profile": "Edit profile", - "column.export_data": "Export data", - "column.favourites": "Likes", - "column.federation_restrictions": "Federation Restrictions", - "column.filters": "Muted words", - "column.filters.add_new": "Add New Filter", - "column.filters.conversations": "Conversations", - "column.filters.create_error": "Error adding filter", - "column.filters.delete": "Delete", - "column.filters.delete_error": "Error deleting filter", - "column.filters.drop_header": "Drop instead of hide", - "column.filters.drop_hint": "Filtered posts will disappear irreversibly, even if filter is later removed", - "column.filters.expires": "Expire after", - "column.filters.expires_hint": "Expiration dates are not currently supported", - "column.filters.home_timeline": "Home timeline", - "column.filters.keyword": "Keyword or phrase", - "column.filters.notifications": "Notifications", - "column.filters.public_timeline": "Public timeline", - "column.filters.subheading_add_new": "Add New Filter", - "column.filters.subheading_filters": "Current Filters", - "column.filters.whole_word_header": "Whole word", - "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", + "column.crypto_donate": "תרום קריפטו", + "column.developers": "מפתחים", + "column.direct": "הודעות ישירות", + "column.directory": "דפדף בין פרופילים", + "column.domain_blocks": "דומיינים מוסתרים", + "column.edit_profile": "ערוך פרופיל", + "column.export_data": "יצא נתונים", + "column.favourited_statuses": "פוסטים שאהבתי", + "column.favourites": "לייקים", + "column.federation_restrictions": "הגבלות פדרציה", + "column.filters": "מילים מושתקות", + "column.filters.add_new": "הוסף פילטר חדש", + "column.filters.conversations": "שיחות", + "column.filters.create_error": "שגיאה בהוספת פילטר", + "column.filters.delete": "מחק פילטר", + "column.filters.delete_error": "שגיאה במחיקת פילטר", + "column.filters.drop_header": "הורד במקום להסתיר", + "column.filters.drop_hint": "פוסטים מסוננים ייעלמו באופן בלתי הפיך, גם אם הפילטר יוסר מאוחר יותר", + "column.filters.expires": "פג תוקף לאחר", + "column.filters.expires_hint": "תאריכי תפוגה אינם נתמכים כעת", + "column.filters.home_timeline": "ציר זמן ביתי", + "column.filters.keyword": "מילת מפתח או ביטוי", + "column.filters.notifications": "התראות", + "column.filters.public_timeline": "ציר זמן ציבורי", + "column.filters.subheading_add_new": "הוסף פילטר חדש", + "column.filters.subheading_filters": "פילטרים נוכחיים", + "column.filters.whole_word_header": "מילה שלמה", + "column.filters.whole_word_hint": "כאשר מילת המפתח או הביטוי הם אלפאנומריים בלבד, הם יוחלו רק אם הם תואמים לכל המילה.", "column.follow_requests": "בקשות מעקב", - "column.groups": "Groups", - "column.home": "בבית", - "column.import_data": "Import data", - "column.info": "Server information", - "column.lists": "Lists", - "column.mfa": "Multi-Factor Authentication", - "column.mfa_cancel": "Cancel", - "column.mfa_confirm_button": "Confirm", - "column.mfa_disable_button": "Disable", - "column.mfa_setup": "Proceed to Setup", + "column.followers": "עוקבים", + "column.following": "עוקב אחרי", + "column.groups": "קבוצות", + "column.home": "בית", + "column.import_data": "יבא נתונים", + "column.info": "מידע על הסרבר", + "column.lists": "רשימות", + "column.mentions": "אזכורים", + "column.mfa": "אימות מרובה גורמים", + "column.mfa_cancel": "בטל", + "column.mfa_confirm_button": "אמת", + "column.mfa_disable_button": "השבת", + "column.mfa_setup": "המשך להתקנה", "column.mutes": "השתקות", "column.notifications": "התראות", - "column.preferences": "Preferences", + "column.pins": "פוסטים נעוצים", + "column.preferences": "העדפות", + "column.profile_directory": "מדריך פרופילים", "column.public": "בפרהסיה", - "column.reblogs": "Reposts", - "column.remote": "Federated timeline", - "column.scheduled_statuses": "Scheduled Posts", - "column.search": "Search", - "column.security": "Security", - "column.soapbox_config": "Soapbox config", + "column.reactions": "תגובות", + "column.reblogs": "הדהודים", + "column.remote": "ציר זמן פדרטיבי", + "column.scheduled_statuses": "פוסטים מתוזמנים", + "column.search": "חפש", + "column.security": "אבטחה", + "column.soapbox_config": "תצורות סבוניה", "column_back_button.label": "חזרה", + "column_forbidden.body": "אין לך הרשאה לגשת לדף זה.", + "column_forbidden.title": "אסור", "column_header.hide_settings": "הסתרת העדפות", "column_header.show_settings": "הצגת העדפות", - "community.column_settings.media_only": "Media only", - "community.column_settings.title": "Local timeline settings", - "compose.character_counter.title": "Used {chars} out of {maxChars} characters", - "compose.invalid_schedule": "You must schedule a post at least 5 minutes out.", - "compose.submit_success": "Your post was sent", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", - "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", + "community.column_settings.media_only": "רק מדיה", + "community.column_settings.title": "הגדרות ציר זמן מקומי", + "compose.character_counter.title": "השתמת ב{chars} מתוך {maxChars} תווים", + "compose.invalid_schedule": "עליך לתזמן פוסט לפחות 5 דקות.", + "compose.submit_success": "הפוסט שלך נשלח", + "compose_form.direct_message_warning": "פוסט זה יהיה גלוי רק לכל המשתמשים שהוזכרו.", + "compose_form.hashtag_warning": "פוסט זה לא יופיע תחת שום האשטאג מכיוון שהוא לא רשום. ניתן לחפש רק פוסטים ציבוריים לפי האשטאג.", "compose_form.lock_disclaimer": "חשבונך אינו {locked}. כל אחד יוכל לעקוב אחריך כדי לקרוא את הודעותיך המיועדות לעוקבים בלבד.", "compose_form.lock_disclaimer.lock": "נעול", - "compose_form.markdown.marked": "Post markdown enabled", - "compose_form.markdown.unmarked": "Post markdown disabled", - "compose_form.message": "Message", - "compose_form.placeholder": "מה עובר לך בראש?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.markdown.marked": "סימון פוסט למארקדאון מופעל", + "compose_form.markdown.unmarked": "סימון פוסט למארקדאון מושבת", + "compose_form.message": "הודעה", + "compose_form.placeholder": "נחתתי בלוס אנג'לס", + "compose_form.poll.add_option": "הוסף בחירה", + "compose_form.poll.duration": "משך הסקר", + "compose_form.poll.option_placeholder": "בחירה {number}", + "compose_form.poll.remove_option": "הסר את הבחירה הזו", + "compose_form.poll.switch_to_multiple": "שנה סקר כדי לאפשר אפשרויות בחירה מרובות", + "compose_form.poll.switch_to_single": "שנה סקר כדי לאפשר בחירה יחידה", "compose_form.publish": "ללחוש", - "compose_form.publish_loud": "לחצרץ!", - "compose_form.schedule": "Schedule", - "compose_form.scheduled_statuses.click_here": "Click here", - "compose_form.scheduled_statuses.message": "You have scheduled posts. {click_here} to see them.", - "compose_form.sensitive.hide": "Mark media as sensitive", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.publish_loud": "!פרסם", + "compose_form.schedule": "לתזמן", + "compose_form.scheduled_statuses.click_here": "לחץ כאן", + "compose_form.scheduled_statuses.message": "יש לך פוסטים מתוזמנים. {לחץ_כאן} כדי לראות אותם.", + "compose_form.sensitive.hide": "סמן מדיה כרגישה", + "compose_form.sensitive.marked": "מדיה מסומנת כרגישה", + "compose_form.sensitive.unmarked": "מדיה לא מסומנת כרגישה", + "compose_form.spoiler.marked": "טקסט מוסתר מאחורי אזהרה", + "compose_form.spoiler.unmarked": "הטקסט אינו מוסתר", "compose_form.spoiler_placeholder": "אזהרת תוכן", "confirmation_modal.cancel": "ביטול", - "confirmations.admin.deactivate_user.confirm": "Deactivate @{name}", - "confirmations.admin.deactivate_user.message": "You are about to deactivate @{acct}. Deactivating a user is a reversible action.", - "confirmations.admin.delete_local_user.checkbox": "I understand that I am about to delete a local user.", - "confirmations.admin.delete_status.confirm": "Delete post", - "confirmations.admin.delete_status.message": "You are about to delete a post by @{acct}. This action cannot be undone.", - "confirmations.admin.delete_user.confirm": "Delete @{name}", - "confirmations.admin.delete_user.message": "You are about to delete @{acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.", - "confirmations.admin.mark_status_not_sensitive.confirm": "Mark post not sensitive", - "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", - "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", - "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", - "confirmations.block.block_and_report": "Block & Report", + "confirmations.admin.deactivate_user.confirm": "השבת @{name}", + "confirmations.admin.deactivate_user.message": "אתה עומד להשבית את @{acct}. השבתת משתמש היא פעולה הפיכה.", + "confirmations.admin.delete_local_user.checkbox": "אני מבין שאני עומד למחוק משתמש מקומי.", + "confirmations.admin.delete_status.confirm": "מחק פוסט", + "confirmations.admin.delete_status.message": "אתה עומד למחוק פוסט מאת @{acct}. לא ניתן לבטל פעולה זו.", + "confirmations.admin.delete_user.confirm": "מחק @{name}", + "confirmations.admin.delete_user.message": "אתה עומד למחוק את @{acct}. זוהי פעולה הרסנית שלא ניתן לבטלה!!!", + "confirmations.admin.mark_status_not_sensitive.confirm": "סמן שהפוסט לא רגיש", + "confirmations.admin.mark_status_not_sensitive.message": "אתה עומד לסמן שפוסט מאת @{acct} אינו רגיש.", + "confirmations.admin.mark_status_sensitive.confirm": "סמן את הפוסט כרגיש", + "confirmations.admin.mark_status_sensitive.message": "אתה עומד לסמן פוסט של @{acct} רגיש.", + "confirmations.admin.reject_user.confirm": "דחה @{name}", + "confirmations.admin.reject_user.message": "אתה עומד לדחות את בקשת הרישום @{acct}. לא ניתן לבטל פעולה זו.", + "confirmations.block.block_and_report": "חסום ודווח", "confirmations.block.confirm": "לחסום", "confirmations.block.message": "לחסום את {name}?", "confirmations.delete.confirm": "למחוק", + "confirmations.delete.heading": "מחק הודעה", "confirmations.delete.message": "למחוק את ההודעה?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "confirmations.delete_list.confirm": "מחק רשימה", + "confirmations.delete_list.message": "האם אתה בטוח שברצונך למחוק רשימה זו לצמיתות?", "confirmations.domain_block.confirm": "הסתר קהילה שלמה", "confirmations.domain_block.message": "באמת באמת לחסום את כל קהילת {domain}? ברב המקרים השתקות נבחרות של מספר משתמשים מסויימים צריכה להספיק.", "confirmations.mute.confirm": "להשתיק", "confirmations.mute.message": "להשתיק את {name}?", - "confirmations.redraft.confirm": "Delete & redraft", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", - "confirmations.register.needs_approval": "Your account will be manually approved by an admin. Please be patient while we review your details.", - "confirmations.register.needs_confirmation": "Please check your inbox at {email} for confirmation instructions. You will need to verify your email address to continue.", - "confirmations.reply.confirm": "Reply", - "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "confirmations.redraft.confirm": "מחק ותנסח מחדש", + "confirmations.redraft.message": "האם אתה בטוח שברצונך למחוק את הפוסט הזה ולנסח אותו מחדש? אתה תאבד את כל התגובות,ההדוהודים והלייקים שלו.", + "confirmations.register.needs_approval": "החשבון שלך יאושר באופן ידני על ידי מנהל. אנא התאזר בסבלנות בזמן שאנו בודקים את הפרטים שלך.", + "confirmations.register.needs_confirmation": "אנא בדוק את תיבת הדואר הנכנס שלך בכתובת {email} לקבלת הוראות אישור. תצטרך לאמת את כתובת הדואר שלך כדי להמשיך.", + "confirmations.reply.confirm": "הגב", + "confirmations.reply.message": "כתיבת תגובה עכשיו תחליף את ההודעה שאתה כותב כעת. האם אתה בטוח שאתה רוצה להמשיך?", "confirmations.unfollow.confirm": "להפסיק מעקב", "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?", - "crypto_donate.explanation_box.message": "{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!", - "crypto_donate.explanation_box.title": "Sending cryptocurrency donations", - "crypto_donate_panel.actions.more": "Click to see {count} more {count, plural, one {wallet} other {wallets}}", - "crypto_donate_panel.heading": "Donate Cryptocurrency", - "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", - "datepicker.hint": "Scheduled to post at…", - "direct.search_placeholder": "Send a message to…", - "donate": "Donate", - "donate_crypto": "Donate cryptocurrency", - "edit_federation.followers_only": "Hide posts except to followers", - "edit_federation.force_nsfw": "Force attachments to be marked sensitive", - "edit_federation.media_removal": "Strip media", - "edit_federation.reject": "Reject all activities", - "edit_federation.save": "Save", - "edit_federation.success": "{host} federation was updated", - "edit_federation.unlisted": "Force posts unlisted", - "edit_profile.error": "Profile update failed", - "edit_profile.fields.accepts_email_list_label": "Subscribe to newsletter", - "edit_profile.fields.avatar_label": "Avatar", - "edit_profile.fields.bio_label": "Bio", - "edit_profile.fields.bio_placeholder": "Tell us about yourself.", - "edit_profile.fields.bot_label": "This is a bot account", - "edit_profile.fields.display_name_label": "Display name", - "edit_profile.fields.display_name_placeholder": "Name", - "edit_profile.fields.header_label": "Header", - "edit_profile.fields.hide_network_label": "Hide network", - "edit_profile.fields.locked_label": "Lock account", - "edit_profile.fields.meta_fields.content_placeholder": "Content", - "edit_profile.fields.meta_fields.label_placeholder": "Label", - "edit_profile.fields.meta_fields_label": "Profile metadata", - "edit_profile.fields.stranger_notifications_label": "Block notifications from strangers", - "edit_profile.fields.verified_display_name": "Verified users may not update their display name", - "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", - "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", - "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", - "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", - "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", - "edit_profile.hints.locked": "Requires you to manually approve followers", - "edit_profile.hints.meta_fields": "You can have up to {count, plural, one {# item} other {# items}} displayed as a table on your profile", - "edit_profile.hints.stranger_notifications": "Only show notifications from people you follow", - "edit_profile.meta_fields.add": "Add new item", - "edit_profile.save": "Save", - "edit_profile.success": "Profile saved!", + "crypto_donate.explanation_box.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים. ניתן לשלוח תרומה לכל אחת מהכתובות למטה. תודה על תמיכתך!", + + "crypto_donate.explanation_box.title": "שליחת תרומות מטבעות קריפטוגרפיים", + "crypto_donate_panel.actions.more": "לחץ כדי לראות {count} עוד {count, plural, one {ארנק} other {ארנקים}}", + "crypto_donate_panel.heading": "תרום מטבעות קריפטו", + "crypto_donate_panel.intro.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים כדי לממן את השירות שלנו. תודה על תמיכתך!", + "datepicker.hint": "מתוכנן לפרסם ב...", + "developers.navigation.app_create_label": "צור אפליקציה", + "developers.navigation.intentional_error_label": "הפעלת שגיאה", + "direct.search_placeholder": "שלח הודעה ל...", + "directory.federated": "מהפדיברס הידוע", + "directory.local": "מ{domain} בלבד", + "directory.new_arrivals": "מגיעים חדשים", + "directory.recently_active": "פעיל לאחרונה", + "donate": "תרומה", + "donate_crypto": "תרום מטבע קריפטוגרפי", + "edit_federation.followers_only": "הסתר פוסטים למעט מעוקבים", + "edit_federation.force_nsfw": "כפה על סימון קבצים מצורפים כרגישים", + "edit_federation.media_removal": "הסר מדיה", + "edit_federation.reject": "דחה את כל הפעילויות", + "edit_federation.save": "שמור", + "edit_federation.success": "הפדרציה של {host} עודכנה", + "edit_federation.unlisted": "לכפות פוסטים כלא רשומים", + "edit_profile.error": "עדכון הפרופיל נכשל", + "edit_profile.fields.accepts_email_list_label": "הירשם לעדכונים", + "edit_profile.fields.avatar_label": "אווטאר", + "edit_profile.fields.bio_label": "ביוגרפיה", + "edit_profile.fields.bio_placeholder": "ספר לנו על עצמך.", + "edit_profile.fields.bot_label": "זה חשבון בוט", + "edit_profile.fields.discoverable_label": "אפשר גילוי חשבון", + "edit_profile.fields.display_name_label": "שם תצוגה", + "edit_profile.fields.display_name_placeholder": "שם", + "edit_profile.fields.birthday_label": "יום הולדת", + "edit_profile.fields.birthday_placeholder": "תאריך הלידה שלך", + "edit_profile.fields.header_label": "כותרת", + "edit_profile.fields.hide_network_label": "הסתר רשת", + "edit_profile.fields.locked_label": "נעל חשבון", + "edit_profile.fields.meta_fields.content_placeholder": "תוכן", + "edit_profile.fields.meta_fields.label_placeholder": "תווית", + "edit_profile.fields.meta_fields_label": "מטא נתונים של פרופיל", + "edit_profile.fields.stranger_notifications_label": "חסום התראות מזרים", + "edit_profile.fields.verified_display_name": "משתמשים מאומתים לא יכולים לעדכן את שם התצוגה שלהם", + "edit_profile.hints.accepts_email_list": "הצטרפו לעדכוני חדשות ועדכונים שיווקיים.", + "edit_profile.hints.avatar": "PNG, GIF או JPG. יוקטן ל-{size}", + "edit_profile.hints.bot": "חשבון זה מבצע בעיקר פעולות אוטומטיות וייתכן שלא יהיה פיקוח", + "edit_profile.hints.discoverable": "הצג חשבון בספריית הפרופילים ואפשר הוספה לאינדקס על ידי שירותים חיצוניים", + "edit_profile.hints.header": "PNG, GIF או JPG. יוקטן ל-{size}", + "edit_profile.hints.hide_network": "מי אתה עוקב ומי עוקב אחריך לא יוצג בפרופיל שלך", + "edit_profile.hints.locked": "מחייב אותך לאשר עוקבים באופן ידני", + "edit_profile.hints.meta_fields": "תוכל להציג עד {count, plural, one {# פריט} other {# פריטים}} אחרים כטבלה בפרופיל שלך", + "edit_profile.hints.stranger_notifications": "הצג רק התראות מאנשים שאתה עוקב אחריהם", + "edit_profile.meta_fields.add": "הוסף פריט חדש", + "edit_profile.save": "שמירה", + "edit_profile.success": "הפרופיל נשמר!", "embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.", "embed.preview": "דוגמא כיצד זה יראה:", "emoji_button.activity": "פעילות", @@ -325,341 +374,354 @@ "emoji_button.search_results": "תוצאות חיפוש", "emoji_button.symbols": "סמלים", "emoji_button.travel": "טיולים ואתרים", - "empty_column.account_blocked": "You are blocked by @{accountUsername}.", - "empty_column.account_favourited_statuses": "This user doesn't have any liked posts yet.", - "empty_column.account_timeline": "No posts here!", - "empty_column.account_unavailable": "Profile unavailable", - "empty_column.aliases": "You haven't created any account alias yet.", - "empty_column.aliases.suggestions": "There are no account suggestions available for the provided term.", - "empty_column.blocks": "You haven't blocked any users yet.", - "empty_column.bookmarks": "You don't have any bookmarks yet. When you add one, it will show up here.", - "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!", - "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", - "empty_column.domain_blocks": "There are no hidden domains yet.", - "empty_column.favourited_statuses": "You don't have any favorite posts yet. When you favorite one, it will show up here.", - "empty_column.favourites": "No one has favorited this post yet. When someone does, they will show up here.", - "empty_column.filters": "You haven't created any muted words yet.", - "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.", - "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", - "empty_column.group": "There is nothing in this group yet. When members of this group make new posts, they will appear here.", + "empty_column.account_blocked": "אתה נחסם על ידי @{accountUsername}.", + "empty_column.account_favourited_statuses": "למשתמש הזה אין עדיין פוסטים שאהב.", + "empty_column.account_timeline": "אין כאן פוסטים!", + "empty_column.account_unavailable": "הפרופיל אינו זמין", + "empty_column.aliases": "עדיין לא יצרת שום כינוי חשבון.", + "empty_column.aliases.suggestions": "אין הצעות לחשבון זמינות עבור המונח שסופק.", + "empty_column.blocks": "עדיין לא חסמת אף משתמש.", + "empty_column.bookmarks": "עדיין אין לך סימניות. כאשר אתה מוסיף אחד, הוא יופיע כאן.", + "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתחילו להתגלגל!", + "empty_column.direct": "עדיין אין לך הודעות ישירות. כאשר אתה שולח או מקבל אחד, הם יופיעו כאן.", + "empty_column.domain_blocks": "אין עדיין דומיינים נסתרים.", + "empty_column.favourited_statuses": "עדיין אין לך פוסטים שאהבת. כאשר אתה עושה לייק, הם יופיעו כאן.", + "empty_column.favourites": "אף אחד עדיין לא סימן את הפוסט הזה כאהוב. כשמישהו יעשה זאת, הוא יופיע כאן.", + "empty_column.filters": "עדיין לא יצרת מילים מושתקות.", + "empty_column.follow_recommendations": "נראה שלא ניתן היה ליצור עבורך הצעות. אתה יכול לנסות להשתמש בחיפוש כדי לחפש אנשים שאתה עשוי להכיר או לחקור תגי האשטאג פופולריים.", + "empty_column.follow_requests": "עדיין אין לך בקשות מעקב. כשתקבל אחד, הוא יופיע כאן.", + "empty_column.group": "עדיין אין כלום בקבוצה הזו. כאשר חברי הקבוצה הזו מעלים פוסטים חדשים, הם יופיעו כאן.", "empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.", - "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.", - "empty_column.home.local_tab": "the {site_title} tab", - "empty_column.list": "אין עדיין מאום ברשימה.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", - "empty_column.mutes": "You haven't muted any users yet.", - "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב.", + "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר משתמשים אחרים.", + "empty_column.home.local_tab": "הכרטיסייה {site_title} של", + "empty_column.list": "אין עדיין כלום ברשימה.", + "empty_column.lists": "עדיין אין לך רשימות. כאשר אתה יוצר אחד, הוא יופיע כאן.", + "empty_column.mutes": "עדיין לא השתקת אף משתמש.", + "empty_column.notifications": "אין התראות.", "empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות", - "empty_column.remote": "There is nothing here! Manually follow users from {instance} to fill it up.", - "empty_column.scheduled_statuses": "You don't have any scheduled statuses yet. When you add one, it will show up here.", - "empty_column.search.accounts": "There are no people results for \"{term}\"", - "empty_column.search.hashtags": "There are no hashtags results for \"{term}\"", - "empty_column.search.statuses": "There are no posts results for \"{term}\"", - "export_data.actions.export": "Export", - "export_data.actions.export_blocks": "Export blocks", - "export_data.actions.export_follows": "Export follows", - "export_data.actions.export_mutes": "Export mutes", - "export_data.blocks_label": "Blocks", - "export_data.follows_label": "Follows", - "export_data.hints.blocks": "Get a CSV file containing a list of blocked accounts", - "export_data.hints.follows": "Get a CSV file containing a list of followed accounts", - "export_data.hints.mutes": "Get a CSV file containing a list of muted accounts", - "export_data.mutes_label": "Mutes", - "export_data.success.blocks": "Blocks exported successfully", - "export_data.success.followers": "Followers exported successfully", - "export_data.success.mutes": "Mutes exported successfully", - "federation_restriction.federated_timeline_removal": "Fediverse timeline removal", - "federation_restriction.followers_only": "Hidden except to followers", - "federation_restriction.full_media_removal": "Full media removal", - "federation_restriction.media_nsfw": "Attachments marked NSFW", - "federation_restriction.partial_media_removal": "Partial media removal", - "federation_restrictions.empty_message": "{siteTitle} has not restricted any instances.", - "federation_restrictions.explanation_box.message": "Normally servers on the Fediverse can communicate freely. {siteTitle} has imposed restrictions on the following servers.", - "federation_restrictions.explanation_box.title": "Instance-specific policies", - "federation_restrictions.not_disclosed_message": "{siteTitle} does not disclose federation restrictions through the API.", - "fediverse_tab.explanation_box.dismiss": "Don't show again", - "fediverse_tab.explanation_box.explanation": "{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka \"servers\"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don't like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.", - "fediverse_tab.explanation_box.title": "What is the Fediverse?", - "filters.added": "Filter added.", - "filters.context_header": "Filter contexts", - "filters.context_hint": "One or multiple contexts where the filter should apply", - "filters.filters_list_context_label": "Filter contexts:", - "filters.filters_list_delete": "Delete", - "filters.filters_list_details_label": "Filter settings:", - "filters.filters_list_drop": "Drop", - "filters.filters_list_hide": "Hide", - "filters.filters_list_phrase_label": "Keyword or phrase:", - "filters.filters_list_whole-word": "Whole word", - "filters.removed": "Filter deleted.", - "follow_recommendations.done": "Done", - "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.", - "follow_recommendations.lead": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!", + "empty_column.remote": "אין פה כלום! עקוב ידנית אחר משתמשים מ-{instance} כדי למלא אותו.", + "empty_column.scheduled_statuses": "עדיין אין לך סטטוסים מתוזמנים. כאשר אתה מוסיף אחד, הוא יופיע כאן.", + "empty_column.search.accounts": "אין תוצאות של אנשים עבור \"{term}\"", + "empty_column.search.hashtags": "אין תוצאות האשטאג עבור \"{term}\"", + "empty_column.search.statuses": "אין תוצאות פוסטים עבור \"{term}\"", + "export_data.actions.export": "ייצא נתונים", + "export_data.actions.export_blocks": "ייצא חסימות", + "export_data.actions.export_follows": "ייצא מעקבים", + "export_data.actions.export_mutes": "ייצא השתקות", + "export_data.blocks_label": "חסימות", + "export_data.follows_label": "מעקבים", + "export_data.hints.blocks": "קבל קובץ CSV המכיל רשימה של חשבונות חסומים", + "export_data.hints.follows": "קבל קובץ CSV המכיל רשימה של חשבונות במעקב", + "export_data.hints.mutes": "קבל קובץ CSV המכיל רשימה של חשבונות מושתקים", + "export_data.mutes_label": "השתקות", + "export_data.success.blocks": "חסימות יוצאו בהצלחה", + "export_data.success.followers": "מעקבים יוצאו בהצלחה", + "export_data.success.mutes": "השתקות יוצאו בהצלחה", + "federation_restriction.federated_timeline_removal": "הסרת ציר הזמן פדרטיבי", + "federation_restriction.followers_only": "מוסתר מלבד לעוקבים", + "federation_restriction.full_media_removal": "הסרת מדיה מלאה", + "federation_restriction.media_nsfw": "קבצים מצורפים מסומנים לא בטוח לעבודה", + "federation_restriction.partial_media_removal": "הסרת מדיה חלקית", + "federation_restrictions.empty_message": "{siteTitle} לא הגביל אף שרת.", + "federation_restrictions.explanation_box.message": "בדרך כלל שרתים בפדרציה יכולים לתקשר בחופשיות. {siteTitle} הטיל הגבלות על השרתים הבאים.", + "federation_restrictions.explanation_box.title": "מדיניות ספציפית לשרת", + "federation_restrictions.not_disclosed_message": "{siteTitle} אינו חושף הגבלות הפדרציה דרך ה-API.", + "fediverse_tab.explanation_box.dismiss": "אל תראה שוב", + "fediverse_tab.explanation_box.explanation": "{site_title} הוא חלק מה-Fediverse, רשת חברתית המורכבת מאלפי אתרי מדיה חברתית עצמאית (הידועה בשם \"servers\"). הפוסטים שאתה רואה כאן הם משרתים של צד שלישי. יש לך את החופש לעסוק בהם, או לחסום כל שרת שאתה לא אוהב. שימו לב לשם המשתמש המלא אחרי הסימן @ השני כדי לדעת מאיזה שרת מגיע הפוסט. כדי לראות רק פוסטים של {site_title}, בקר ב-{local}.", + "fediverse_tab.explanation_box.title": "מה זה הפדיברס?", + "filters.added": "פילטר נוסף.", + "filters.context_header": "הקשרי הפילטר", + "filters.context_hint": "הקשר אחד או מרובים שבהם הפילטר צריך לחול", + "filters.filters_list_context_label": "הקשרי הפילטר:", + "filters.filters_list_delete": "מחק פילטר", + "filters.filters_list_details_label": "הגדרות פילטר:", + "filters.filters_list_drop": "הורד", + "filters.filters_list_hide": "הסתר", + "filters.filters_list_phrase_label": "מילת מפתח או ביטוי:", + "filters.filters_list_whole-word": "מילה שלמה", + "filters.removed": "פילטר נמחק.", + "follow_recommendations.done": "בוצע", + "follow_recommendations.heading": "עקוב אחר אנשים שאתה רוצה לראות מהם פוסטים! הנה כמה הצעות.", + "follow_recommendations.lead": "פוסטים מאנשים שאתה עוקב אחריהם יופיעו בסדר כרונולוגי בפיד הביתי שלך. אל תפחד לעשות טעויות, אתה יכול לבטל את המעקב אחר אנשים באותה קלות בכל עת!", "follow_request.authorize": "קבלה", "follow_request.reject": "דחיה", - "forms.copy": "Copy", - "getting_started.open_source_notice": "מסטודון היא תוכנה חופשית (בקוד פתוח). ניתן לתרום או לדווח על בעיות בגיטהאב: {code_link} (v{code_version}).", - "group.detail.archived_group": "Archived group", - "group.members.empty": "This group does not has any members.", - "group.removed_accounts.empty": "This group does not has any removed accounts.", - "groups.card.join": "Join", - "groups.card.members": "Members", - "groups.card.roles.admin": "You're an admin", - "groups.card.roles.member": "You're a member", - "groups.card.view": "View", - "groups.create": "Create group", - "groups.detail.role_admin": "You're an admin", - "groups.edit": "Edit", - "groups.form.coverImage": "Upload new banner image (optional)", - "groups.form.coverImageChange": "Banner image selected", - "groups.form.create": "Create group", - "groups.form.description": "Description", - "groups.form.title": "Title", - "groups.form.update": "Update group", - "groups.join": "Join group", - "groups.leave": "Leave group", - "groups.removed_accounts": "Removed Accounts", - "groups.sidebar-panel.item.no_recent_activity": "No recent activity", - "groups.sidebar-panel.item.view": "new posts", - "groups.sidebar-panel.show_all": "Show all", - "groups.sidebar-panel.title": "Groups You're In", - "groups.tab_admin": "Manage", - "groups.tab_featured": "Featured", - "groups.tab_member": "Member", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "header.about.label": "About", - "header.back_to.label": "Back to {siteTitle}", - "header.home.label": "Home", - "header.login.label": "Log in", - "home.column_settings.show_direct": "Show direct messages", + "forms.copy": "העתקה", + "forms.hide_password": "הסתר סיסמא", + "forms.show_password": "הראה סיסמא", + "getting_started.open_source_notice": "סבוניה היא תוכנה חופשית (בקוד פתוח). ניתן לתרום או לדווח על בעיות בגיטהאב: {code_link} (v{code_version}).", + "group.detail.archived_group": "קבוצה שנשמרה בארכיון", + "group.members.empty": "לקבוצה זו אין חברים.", + "group.removed_accounts.empty": "לקבוצה הזו אין חשבונות שהוסרו.", + "groups.card.join": "הצטרף", + "groups.card.members": "חברים", + "groups.card.roles.admin": "אתה מנהל", + "groups.card.roles.member": "אתה חבר", + "groups.card.view": "לצפות", + "groups.create": "צור קבוצה", + "groups.detail.role_admin": "אתה מנהל", + "groups.edit": "ערוך", + "groups.form.coverImage": "העלה תמונת באנר חדשה (אופציונלי)", + "groups.form.coverImageChange": "נבחרה תמונת באנר", + "groups.form.create": "צור קבוצה", + "groups.form.description": "תיאור", + "groups.form.title": "כותרת", + "groups.form.update": "עדכן קבוצה", + "groups.join": "הצטרף לקבוצה", + "groups.leave": "עזוב קבוצה", + "groups.removed_accounts": "חשבונות שהוסרו", + "groups.sidebar-panel.item.no_recent_activity": "אין פעילות לאחרונה", + "groups.sidebar-panel.item.view": "פוסטים חדשים", + "groups.sidebar-panel.show_all": "תראה הכול", + "groups.sidebar-panel.title": "קבוצות שאתה נמצא בהן", + "groups.tab_admin": "נהל", + "groups.tab_featured": "מומלצים", + "groups.tab_member": "חבר", + "hashtag.column_header.tag_mode.all": "ו-{additional}", + "hashtag.column_header.tag_mode.any": "או {additional}", + "hashtag.column_header.tag_mode.none": "בלי {additional}", + "header.about.label": "אודות", + "header.back_to.label": "חזור ל-{siteTitle}", + "header.home.label": "בית", + "header.login.label": "התחברות", + "home.column_settings.show_direct": "הצג הודעות ישירות", "home.column_settings.show_reblogs": "הצגת הדהודים", "home.column_settings.show_replies": "הצגת תגובות", - "home.column_settings.title": "Home settings", - "home_column.lists": "Lists", - "home_column_header.all": "All", - "home_column_header.fediverse": "Fediverse", + "home.column_settings.title": "הגדרות ציר זמן ביתי", + "home_column.lists": "רשימותs", + "home_column_header.all": "הכל", + "home_column_header.fediverse": "ציר זמן פדרטיבי", "home_column_header.home": "בבית", - "icon_button.icons": "Icons", - "icon_button.label": "Select icon", - "icon_button.not_found": "No icons!! (╯°□°)╯︵ ┻━┻", - "import_data.actions.import": "Import", - "import_data.actions.import_blocks": "Import blocks", - "import_data.actions.import_follows": "Import follows", - "import_data.actions.import_mutes": "Import mutes", - "import_data.blocks_label": "Blocks", - "import_data.follows_label": "Follows", - "import_data.hints.blocks": "CSV file containing a list of blocked accounts", - "import_data.hints.follows": "CSV file containing a list of followed accounts", - "import_data.hints.mutes": "CSV file containing a list of muted accounts", - "import_data.mutes_label": "Mutes", - "import_data.success.blocks": "Blocks imported successfully", - "import_data.success.followers": "Followers imported successfully", - "import_data.success.mutes": "Mutes imported successfully", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favorite", - "introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.", - "introduction.interactions.reblog.headline": "Repost", - "introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "icon_button.icons": "סמלים", + "icon_button.label": "בחר סמל", + "icon_button.not_found": "אין סימנים!! (╯°□°)╯︵ ┻━┻", + "import_data.actions.import": "יבא", + "import_data.actions.import_blocks": "יבא חסימות", + "import_data.actions.import_follows": "יבא מעקבים", + "import_data.actions.import_mutes": "יבא השתקות", + "import_data.blocks_label": "חסימות", + "import_data.follows_label": "מעקבים", + "import_data.hints.blocks": "קובץ CSV המכיל רשימה של חשבונות חסומים", + "import_data.hints.follows": "קובץ CSV המכיל רשימה של חשבונות במעקב", + "import_data.hints.mutes": "קובץ CSV המכיל רשימה של חשבונות מושתקים", + "import_data.mutes_label": "השתקות", + "import_data.success.blocks": "חסימות יובאו בהצלחה", + "import_data.success.followers": "מעקבים יובאו בהצלחה", + "import_data.success.mutes": "השתקות יובאו בהצלחה", + "intervals.full.days": "{number, plural, one {# יום} other {# ימים}}", + "intervals.full.hours": "{number, plural, one {# שעה} other {# שעות}}", + "intervals.full.minutes": "{number, plural, one {# דקה} other {# דקות}}", + "introduction.federation.action": "הבא", + "introduction.federation.home.headline": "בית", + "introduction.federation.home.text": "פוסטים מאנשים שאתה עוקב אחריהם יופיעו בפיד הביתי שלך. אתה יכול לעקוב אחר כל אחד בכל שרת!", + "introduction.interactions.action": "סיים את ההדרכה!", + "introduction.interactions.favourite.headline": "לייק", + "introduction.interactions.favourite.text": "אתה יכול לשמור פוסט למועד מאוחר יותר, ולהודיע למחבר שאהבת אותואת הפוסט, על ידי .לחיצת לייק", + "introduction.interactions.reblog.headline": "להדהד", + "introduction.interactions.reblog.text": "אתה יכול לשתף פוסטים של אנשים אחרים עם העוקבים שלך על ידי הדהוד הפוסט שלהם.", + "introduction.interactions.reply.headline": "הגב", + "introduction.interactions.reply.text": "אתה יכול להשיב לפוסטים של אנשים אחרים ושלך, שיקשרו אותם יחדיו בשיחה.", + "introduction.welcome.action": "הבא נתחיל", + "introduction.welcome.headline": "צעדים ראשונים", + "introduction.welcome.text": "ברוכים הבאים ל-Fediverse! תוך כמה רגעים, תוכל לשדר הודעות ולדבר עם חבריך במגוון רחב של שרתים. אבל השרת הזה, {domain}, הוא מיוחד - הוא מארח את הפרופיל שלך, אז זכור את שמו.", "keyboard_shortcuts.back": "ניווט חזרה", - "keyboard_shortcuts.blocked": "to open blocked users list", + "keyboard_shortcuts.blocked": "לפתיחת רשימת משתמשים חסומים", "keyboard_shortcuts.boost": "להדהד", "keyboard_shortcuts.compose": "להתמקד בתיבת חיבור ההודעות", "keyboard_shortcuts.down": "לנוע במורד הרשימה", - "keyboard_shortcuts.enter": "to open post", - "keyboard_shortcuts.favourite": "לחבב", - "keyboard_shortcuts.favourites": "to open favorites list", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.enter": "לפתוח פוסט", + "keyboard_shortcuts.favourite": "לייק", + "keyboard_shortcuts.favourites": "לפתוח את רשימת הלייקים", + "keyboard_shortcuts.heading": "קיצורי דרך במקלדת", + "keyboard_shortcuts.home": "לפתוח את ציר הזמן הביתי", "keyboard_shortcuts.hotkey": "מקש קיצור", "keyboard_shortcuts.legend": "להציג את הפירוש", - "keyboard_shortcuts.mention": "לאזכר את המחבר(ת)", - "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", - "keyboard_shortcuts.notifications": "to open notifications column", - "keyboard_shortcuts.open_media": "to open media", - "keyboard_shortcuts.pinned": "to open pinned posts list", - "keyboard_shortcuts.profile": "to open author's profile", - "keyboard_shortcuts.react": "to react", + "keyboard_shortcuts.mention": "לאזכר את המחבר", + "keyboard_shortcuts.muted": "לפתוח את רשימת המשתמשים המושתקים", + "keyboard_shortcuts.my_profile": "לפתוח את הפרופיל שלך", + "keyboard_shortcuts.notifications": "לפתוח את עמודת ההתראות", + "keyboard_shortcuts.open_media": "לפתוח מדיה", + "keyboard_shortcuts.pinned": "לפתוח את רשימת הפוסטים המוצמדים", + "keyboard_shortcuts.profile": "לפתוח את פרופיל המחבר", + "keyboard_shortcuts.react": "להגיב", "keyboard_shortcuts.reply": "לענות", - "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.requests": "לפתוח את רשימת בקשות המעקב", "keyboard_shortcuts.search": "להתמקד בחלון החיפוש", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", - "keyboard_shortcuts.toot": "להתחיל חיצרוץ חדש", + "keyboard_shortcuts.toggle_hidden": "להציג/להסתיר טקסט מאחורי אזהרת תוכן", + "keyboard_shortcuts.toggle_sensitivity": "להציג/להסתיר מדיה", + "keyboard_shortcuts.toot": "להתחיל פוסט חדש", "keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש", "keyboard_shortcuts.up": "לנוע במעלה הרשימה", "lightbox.close": "סגירה", "lightbox.next": "הלאה", "lightbox.previous": "הקודם", - "lightbox.view_context": "View context", - "list.click_to_add": "Click here to add people", - "list_adder.header_title": "Add or Remove from Lists", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.create_title": "Create", - "lists.new.save_title": "Save Title", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lightbox.view_context": "הצג את ההקשר", + "list.click_to_add": "לחץ כאן כדי להוסיף אנשים", + "list.label": "בחר רשימה...", + "list.select": "בחר רשימה", + "list_adder.header_title": "הוסף או הסר מהרשימה", + "lists.account.add": "הוסף לרשימה", + "lists.account.remove": "הסר מהרשימה", + "lists.edit": "ערוך רשימה", + "lists.edit.submit": "שנה כותרת", + "lists.new.create": "הוסף רשימה", + "lists.new.create_title": "צור כותרת", + "lists.new.save_title": "שמור כותרת", + "lists.new.title_placeholder": "כותרת רשימה חדשה", + "lists.search": "חפש בין אנשים שאתה עוקב אחריהם", + "lists.subheading": "הרשימות שלך", "loading_indicator.label": "טוען...", - "login.fields.instance_label": "Instance", + "login.fields.instance_label": "שרת", "login.fields.instance_placeholder": "example.com", - "login.fields.otp_code_hint": "Enter the two-factor code generated by your phone app or use one of your recovery codes", - "login.fields.otp_code_label": "Two-factor code:", - "login.fields.password_placeholder": "Password", - "login.fields.username_placeholder": "Username", - "login.log_in": "Log in", - "login.otp_log_in": "OTP Login", - "login.otp_log_in.fail": "Invalid code, please try again.", - "login.reset_password_hint": "Trouble logging in?", + "login.fields.otp_code_hint": "הזן את קוד שני הגורמים שנוצר על ידי אפליקציות הטלפון שלך או השתמש באחד מקודי השחזור שלך", + "login.fields.otp_code_label": "קוד דו גורמי:", + "login.fields.password_placeholder": "סיסמא", + "login.fields.username_placeholder": "שם משתמש", + "login.log_in": "התחברות", + "login.otp_log_in": "התחברות OTP", + "login.otp_log_in.fail": "קוד לא חוקי, אנא נסה שוב.", + "login.reset_password_hint": "בעיה בהתחברות?", "media_gallery.toggle_visible": "נראה בלתי נראה", - "media_panel.empty_message": "No media found.", - "media_panel.title": "Media", - "mfa.mfa_disable_enter_password": "Enter your current password to disable two-factor auth:", - "mfa.mfa_setup_enter_password": "Enter your current password to confirm your identity:", - "mfa.mfa_setup_scan_description": "Using your two-factor app, scan this QR code or enter text key:", - "mfa.mfa_setup_scan_key": "Key:", - "mfa.mfa_setup_scan_title": "Scan", - "mfa.mfa_setup_verify_description": "To enable two-factor authentication, enter the code from your two-factor app:", - "mfa.mfa_setup_verify_title": "Verify", - "mfa.otp_enabled_description": "You have enabled two-factor authentication via OTP.", - "mfa.otp_enabled_title": "OTP Enabled", - "mfa.setup_hint": "Follow these steps to set up multi-factor authentication on your account with OTP", - "mfa.setup_otp_title": "OTP Disabled", - "mfa.setup_recoverycodes": "Recovery codes", - "mfa.setup_warning": "Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.", - "missing_description_modal.cancel": "Cancel", - "missing_description_modal.continue": "Post", - "missing_description_modal.text": "You have not entered a description for all attachments. Continue anyway?", + "media_panel.empty_message": "לא נמצאה מדיה.", + "media_panel.title": "מדיה", + "mfa.mfa_disable_enter_password": "הזן את הסיסמא הנוכחית שלך כדי להשבית אימות דו-גורמי:", + "mfa.mfa_setup_enter_password": "הזן את הסיסמא הנוכחית שלך כדי לאשר את זהותך:", + "mfa.mfa_setup_scan_description": "באמצעות אפליקציות שני הגורמים שלך, סרוק את קוד ה-QR הזה או הזן מפתח טקסט:", + "mfa.mfa_setup_scan_key": "מפתח:", + "mfa.mfa_setup_scan_title": "סריקה", + "mfa.mfa_setup_verify_description": "כדי להפעיל אימות דו-גורמי, הזן את הקוד מהאפליקציה הדו-גורמית שלך:", + "mfa.mfa_setup_verify_title": "אמת", + "mfa.otp_enabled_description": "הפעלת אימות דו-שלבי באמצעות OTP.", + "mfa.otp_enabled_title": "OTP מופעל", + "mfa.setup_hint": "בצע את השלבים הבאים כדי להגדיר אימות רב-גורמי בחשבון שלך באמצעות OTP", + "mfa.setup_otp_title": "OTP מושבת", + "mfa.setup_recoverycodes": "קודי שחזור", + "mfa.setup_warning": "רשום את הקודים האלה או שמור אותם במקום מאובטח - אחרת לא תראה אותם שוב. אם תאבד את הגישה לאפליקציית 2FA ולקודי השחזור שלך תינעל מחוץ לחשבון שלך.", + "missing_description_modal.cancel": "בטל", + "missing_description_modal.continue": "שלח", + "missing_description_modal.text": "לא הזנת תיאור עבור כל הקבצים המצורפים. המשך בכל זאת?", "missing_indicator.label": "לא נמצא", - "missing_indicator.sublabel": "This resource could not be found", - "morefollows.followers_label": "…and {count} more {count, plural, one {follower} other {followers}} on remote sites.", - "morefollows.following_label": "…and {count} more {count, plural, one {follow} other {follows}} on remote sites.", + "missing_indicator.sublabel": "משאב זה לא נמצא", + "morefollows.followers_label": "ו-{count} עוד {count, plural, one {עוקב} other {עוקבים}} באתרים מרוחקים.", + "morefollows.following_label": "ו-{count} עוד {count, plural, one {מעקב} other {מעקבים}} באתרים מרוחקים.", "mute_modal.hide_notifications": "להסתיר הודעות מחשבון זה?", - "navigation.chats": "Chats", - "navigation.dashboard": "Dashboard", - "navigation.direct_messages": "Messages", - "navigation.home": "Home", - "navigation.invites": "Invites", - "navigation.notifications": "Notifications", - "navigation.search": "Search", - "navigation_bar.account_aliases": "Account aliases", - "navigation_bar.admin_settings": "Admin settings", + "navigation.chats": "צ'אטים", + "navigation.dashboard": "לוח מחוונים", + "navigation.developers": "מפתחים", + "navigation.direct_messages": "הודעות", + "navigation.home": "בית", + "navigation.invites": "הזמנות", + "navigation.notifications": "התראות", + "navigation.search": "חיפוש", + "navigation_bar.account_aliases": "כיוניי חשבון", + "navigation_bar.admin_settings": "הגדרות אדמין", "navigation_bar.blocks": "חסימות", - "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.compose": "Compose new post", - "navigation_bar.compose_direct": "Direct message", - "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.export_data": "Export data", + "navigation_bar.bookmarks": "סימניות", + "navigation_bar.compose": "כתוב פוסט חדש", + "navigation_bar.compose_direct": "הודעה ישירה", + "navigation_bar.compose_reply": "השב לפוסט", + "navigation_bar.domain_blocks": "דומיינים נסתרים", + "navigation_bar.export_data": "יצא נתונים", "navigation_bar.favourites": "חיבובים", - "navigation_bar.filters": "Muted words", + "navigation_bar.filters": "מילים מושתקות", "navigation_bar.follow_requests": "בקשות מעקב", - "navigation_bar.import_data": "Import data", + "navigation_bar.import_data": "יבא נתונים", + "navigation_bar.in_reply_to": "בתשובה ל", "navigation_bar.info": "מידע נוסף", + "navigation_bar.invites": "הזמנות", "navigation_bar.keyboard_shortcuts": "קיצורי מקלדת", - "navigation_bar.lists": "Lists", + "navigation_bar.lists": "רשימות", "navigation_bar.logout": "יציאה", - "navigation_bar.messages": "Messages", + "navigation_bar.messages": "הודעות", "navigation_bar.mutes": "השתקות", - "navigation_bar.pins": "חיצרוצים מקובעים", + "navigation_bar.pins": "פוסטים נעוצים", "navigation_bar.preferences": "העדפות", - "navigation_bar.security": "Security", - "navigation_bar.soapbox_config": "Soapbox config", - "notification.chat_mention": "{name} sent you a message", - "notification.favourite": "חצרוצך חובב על ידי {name}", + "navigation_bar.profile_directory": "ספריית פרופילים", + "navigation_bar.security": "אבטחה", + "navigation_bar.soapbox_config": "תצורת סבוניה", + "notification.chat_mention": "{name} שלח לך הודעה", + "notification.favourite": "הפוסט שלך חובב על ידי {name}", "notification.follow": "{name} במעקב אחרייך", - "notification.follow_request": "{name} has requested to follow you", + "notification.follow_request": "{name} ביקש לעקוב אחריך", "notification.mention": "אוזכרת על ידי {name}", - "notification.move": "{name} moved to {targetName}", - "notification.pleroma:emoji_reaction": "{name} reacted to your post", - "notification.poll": "A poll you have voted in has ended", - "notification.reblog": "חצרוצך הודהד על ידי {name}", + "notification.move": "{name} הועבר אל {targetName}", + "notification.pleroma:emoji_reaction": "{name} הגיב לפוסט שלך", + "notification.poll": "סקר שהצבעת בו הסתיים", + "notification.reblog": "הפוסט שלך הודהד על ידי {name}", "notifications.clear": "הסרת התראות", "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?", "notifications.column_settings.alert": "התראות לשולחן העבודה", - "notifications.column_settings.emoji_react": "Emoji reacts:", + "notifications.column_settings.emoji_react": "הגבות אימוג'י:", "notifications.column_settings.favourite": "מחובבים:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.filter_bar.advanced": "הצג את כל הקטגוריות", + "notifications.column_settings.filter_bar.category": "סרגל סינון מהיר", + "notifications.column_settings.filter_bar.show": "הראה", "notifications.column_settings.follow": "עוקבים חדשים:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.follow_request": "בקשות מעקב חדשות:", "notifications.column_settings.mention": "פניות:", - "notifications.column_settings.move": "Moves:", - "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.move": "מעברים:", + "notifications.column_settings.poll": "תוצאות סקרים:", "notifications.column_settings.push": "הודעות בדחיפה", "notifications.column_settings.reblog": "הדהודים:", "notifications.column_settings.show": "הצגה בטור", "notifications.column_settings.sound": "שמע מופעל", - "notifications.column_settings.sounds": "Sounds", - "notifications.column_settings.sounds.all_sounds": "Play sound for all notifications", - "notifications.column_settings.title": "Notification settings", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Reposts", - "notifications.filter.emoji_reacts": "Emoji reacts", - "notifications.filter.favourites": "Favorites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", - "notifications.filter.moves": "Moves", - "notifications.filter.polls": "Poll results", - "notifications.group": "{count} notifications", - "notifications.queue_label": "Click to see {count} new {count, plural, one {notification} other {notifications}}", - "password_reset.confirmation": "Check your email for confirmation.", - "password_reset.fields.username_placeholder": "Email or username", - "password_reset.reset": "Reset password", - "pinned_statuses.none": "No pins to show.", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", - "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", - "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", - "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", - "preferences.fields.content_type_label": "Post format", - "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", - "preferences.fields.demetricator_label": "Use Demetricator", - "preferences.fields.display_media.default": "Hide media marked as sensitive", - "preferences.fields.display_media.hide_all": "Always hide media", - "preferences.fields.display_media.show_all": "Always show media", - "preferences.fields.dyslexic_font_label": "Dyslexic mode", - "preferences.fields.expand_spoilers_label": "Always expand posts marked with content warnings", - "preferences.fields.halloween_label": "Halloween mode", - "preferences.fields.language_label": "Language", - "preferences.fields.media_display_label": "Media display", - "preferences.fields.missing_description_modal_label": "Show confirmation dialog before sending a post without media descriptions", - "preferences.fields.privacy_label": "Post privacy", - "preferences.fields.reduce_motion_label": "Reduce motion in animations", - "preferences.fields.system_font_label": "Use system's default font", - "preferences.fields.underline_links_label": "Always underline links in posts", - "preferences.fields.unfollow_modal_label": "Show confirmation dialog before unfollowing someone", - "preferences.hints.content_type_markdown": "Warning: experimental!", - "preferences.hints.demetricator": "Decrease social media anxiety by hiding all numbers from the site.", - "preferences.hints.halloween": "Beware: SPOOKY! Supports light/dark toggle.", - "preferences.hints.privacy_followers_only": "Only show to followers", - "preferences.hints.privacy_public": "Everyone can see", - "preferences.hints.privacy_unlisted": "Everyone can see, but not listed on public timelines", - "preferences.options.content_type_markdown": "Markdown", - "preferences.options.content_type_plaintext": "Plain text", - "preferences.options.privacy_followers_only": "Followers-only", - "preferences.options.privacy_public": "Public", - "preferences.options.privacy_unlisted": "Unlisted", + "notifications.column_settings.sounds": "צלילים", + "notifications.column_settings.sounds.all_sounds": "הפעל צליל עבור כל ההתראות", + "notifications.column_settings.title": "הגדרות התראות", + "notifications.filter.all": "הכל", + "notifications.filter.boosts": "הדהודים", + "notifications.filter.emoji_reacts": "תגובות אימוג'י", + "notifications.filter.favourites": "לייקים", + "notifications.filter.follows": "מעקבים", + "notifications.filter.mentions": "אזכורים", + "notifications.filter.moves": "מעברים", + "notifications.filter.polls": "תוצאות סקרים", + "notifications.group": "{count} התראות", + "notifications.queue_label": "לחץ כדי לראות {count} חדשות {count, plural, one {התראה} other {התראות}}", + "password_reset.confirmation": "בדוק את האימייל שלך לאישור.", + "password_reset.fields.username_placeholder": "אימייל או שם משתמש", + "password_reset.reset": "אפס סיסמא", + "pinned_statuses.none": "אין נעוצים להראות.", + "poll.closed": "סגור", + "poll.refresh": "רענן", + "poll.total_votes": "{count, plural, one {# הצבעה} other {# הצבעות}}", + "poll.vote": "הצבע", + "poll.voted": "הצבעת בעד התשובה הזו", + "poll.votes": "{votes, plural, one {# הצבעה} other {# הצבעות}}", + "poll_button.add_poll": "הוסף סקר", + "poll_button.remove_poll": "הסר סקר", + "preferences.fields.auto_play_gif_label": "הפעל אוטומטית קובצי GIF מונפשים", + "preferences.fields.autoload_more_label": "טען אוטומטית יותר פריטים כאשר אתה מגיע לתחתית העמוד", + "preferences.fields.autoload_timelines_label": "טען אוטומטית פוסטים חדשים לאחר גלילה לראש העמוד", + "preferences.fields.boost_modal_label": "הצג תיבת אישור לפני הדהוד", + "preferences.fields.content_type_label": "פורמט פוסט", + "preferences.fields.delete_modal_label": "הצג תיבת אישור לפני מחיקת פוסט", + "preferences.fields.demetricator_label": "השתמש ב-Demetricator", + "preferences.fields.developer_label": "כלים למפתחים", + "preferences.fields.display_media.default": "הסתר מדיה שסומנה כרגישה", + "preferences.fields.display_media.hide_all": "תמיד הסתר מדיה", + "preferences.fields.display_media.show_all": "תמיד הצג מדיה", + "preferences.fields.dyslexic_font_label": "מצב דיסלקטי", + "preferences.fields.expand_spoilers_label": "הרחב תמיד פוסטים המסומנים באזהרות תוכן", + "preferences.fields.halloween_label": "מצב הלואין", + "preferences.fields.language_label": "שפה", + "preferences.fields.media_display_label": "תצוגת מדיה", + "preferences.fields.missing_description_modal_label": "הצג תיבת אישור לפני שליחת פוסט ללא תיאורי מדיה", + "preferences.fields.privacy_label": "פרטיות הפוסט", + "preferences.fields.reduce_motion_label": "הפחת תנועה באנימציות", + "preferences.fields.system_font_label": "השתמש בגופן ברירת המחדל של המערכת", + "preferences.fields.underline_links_label": "תמיד יש להדגיש קישורים בפוסטים", + "preferences.fields.unfollow_modal_label": "הצג תיבת אישור לפני ביטול המעקב אחר מישהו", + "preferences.hints.content_type_markdown": "אזהרה: ניסיוני!", + "preferences.hints.demetricator": "הפחת את חרדת המדיה החברתית על ידי הסתרת כל המספרים מהאתר.", + "preferences.hints.halloween": "היזהר: מפחיד! תומך בהחלפת אור/כהה.", + "preferences.hints.privacy_followers_only": "הצג רק לעוקבים", + "preferences.hints.privacy_public": "כולם יכולים לראות", + "preferences.hints.privacy_unlisted": "כולם יכולים לראות, אבל לא רשום על צירי זמן ציבוריים", + "preferences.options.content_type_markdown": "מארקדאון", + "preferences.options.content_type_plaintext": "טקסט רגיל", + "preferences.options.privacy_followers_only": "לעוקבים בלבד", + "preferences.options.privacy_public": "ציבורי", + "preferences.options.privacy_unlisted": "לא רשום", "privacy.change": "שינוי פרטיות ההודעה", "privacy.direct.long": "הצג רק למי שהודעה זו פונה אליו", "privacy.direct.short": "הודעה ישירה", @@ -669,231 +731,248 @@ "privacy.public.short": "פומבי", "privacy.unlisted.long": "לא יופיע בפידים הציבוריים המשותפים", "privacy.unlisted.short": "לא לפיד הכללי", - "profile_dropdown.add_account": "Add an existing account", - "profile_dropdown.logout": "Log out @{acct}", - "public.column_settings.title": "Fediverse timeline settings", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", - "register_invite.lead": "Complete the form below to create an account.", - "register_invite.title": "You've been invited to join {siteTitle}!", - "registration.agreement": "I agree to the {tos}.", - "registration.captcha.hint": "Click the image to get a new captcha", - "registration.closed_message": "{instance} is not accepting new members", - "registration.closed_title": "Registrations Closed", - "registration.confirmation_modal.close": "Close", - "registration.fields.confirm_placeholder": "Password (again)", - "registration.fields.email_placeholder": "E-Mail address", - "registration.fields.password_placeholder": "Password", - "registration.fields.username_hint": "Only letters, numbers, and underscores are allowed.", - "registration.fields.username_placeholder": "Username", - "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", - "registration.newsletter": "Subscribe to newsletter.", - "registration.reason": "Why do you want to join?", - "registration.reason_hint": "This will help us review your application", - "registration.sign_up": "Sign up", - "registration.tos": "Terms of Service", - "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", + "profile_dropdown.add_account": "הוסף חשבון קיים", + "profile_dropdown.logout": "התנתק מ-{account}", + "public.column_settings.title": "הגדרות ציר הזמן של Fediverse", + "reactions.all": "הכל", + "regeneration_indicator.label": "טוען...", + "regeneration_indicator.sublabel": "הפיד הביתי שלך נמצא בהכנה!", + "register_invite.lead": "מלא את הטופס למטה כדי ליצור חשבון.", + "register_invite.title": "הוזמנת להצטרף ל-{siteTitle}!", + "registration.agreement": "אני מסכים ל-{tos}.", + "registration.captcha.hint": "לחץ על התמונה כדי לקבל captcha חדש", + "registration.closed_message": "{instance} אינו מקבל חברים חדשים", + "registration.closed_title": "ההרשמות סגורות", + "registration.confirmation_modal.close": "סגור", + "registration.fields.confirm_placeholder": "סיסמא (שוב)", + "registration.fields.email_placeholder": "כתובת אימייל", + "registration.fields.password_placeholder": "סיסמא", + "registration.fields.username_hint": "רק אותיות, מספרים וקווים תחתונים מותרים.", + "registration.fields.username_placeholder": "שם משתמש", + "registration.lead": "עם חשבון ב-{instance} תוכל לעקוב אחר אנשים בכל שרת ב-fediverse.", + "registration.newsletter": "הירשם לעדכונים.", + "registration.password_mismatch": "הסיסמאות אינן תואמות.", + "registration.reason": "למה אתה רוצה להצטרף?", + "registration.reason_hint": "זה יעזור לנו לבדוק את הבקשה שלך", + "registration.sign_up": "הירשם", + "registration.tos": "תנאי השירות", + "registration.username_unavailable": "שם המשתמש תפוס.", + "relative_time.days": "ימים {number}", + "relative_time.hours": "שעות {number}", "relative_time.just_now": "כרגע", - "relative_time.minutes": "{number}m", - "relative_time.seconds": "{number}s", - "remote_instance.edit_federation": "Edit federation", - "remote_instance.federation_panel.heading": "Federation Restrictions", - "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} has placed no restrictions on {host}.", - "remote_instance.federation_panel.restricted_message": "{siteTitle} blocks all activities from {host}.", - "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", - "remote_instance.pin_host": "Pin {host}", - "remote_instance.unpin_host": "Unpin {host}", - "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", + "relative_time.minutes": "דקות {number}", + "relative_time.seconds": "שניות {number}", + "remote_instance.edit_federation": "ערוך פדרציה", + "remote_instance.federation_panel.heading": "הגבלות הפדרציה", + "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} לא הטיל הגבלות על {host}.", + "remote_instance.federation_panel.restricted_message": "{siteTitle} חוסם את כל הפעילויות של {host}.", + "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} הטיל כמה הגבלות על {host}.", + "remote_instance.pin_host": "הצמד {מארח}", + "remote_instance.unpin_host": "בטל הצמדה של {מארח}", + "remote_interaction.account_placeholder": "הזן את username@domain שממנו ברצונך לפעול", + "remote_interaction.divider": "או", + "remote_interaction.favourite": "המשך לסמן לייק", + "remote_interaction.favourite_title": "לעשות לייק לפוסט מרחוק", + "remote_interaction.follow": "המשך לעקוב", + "remote_interaction.follow_title": "עקוב אחר {user} מרחוק", + "remote_interaction.poll_vote": "המשך להצבעה", + "remote_interaction.poll_vote_title": "הצביע בסקר מרחוק", + "remote_interaction.reblog": "המשך להדהד", + "remote_interaction.reblog_title": "הדהד פוסט מרחוק", + "remote_interaction.reply": "המשך להשיב", + "remote_interaction.reply_title": "השב לפוסט מרחוק", + "remote_interaction.user_not_found_error": "לא ניתן היה למצוא את המשתמש הנתון", + "remote_timeline.filter_message": "אתה צופה בציר הזמן של {instance}.", "reply_indicator.cancel": "ביטול", - "report.block": "Block {target}", - "report.block_hint": "Do you also want to block this account?", - "report.forward": "Forward to {target}", - "report.forward_hint": "The account is from another server. Send a copy of the report there as well?", - "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "reply_mentions.account.add": "הוסף לאזכורים", + "reply_mentions.account.remove": "הסר מהאזכורים", + "reply_mentions.more": "ו-{count} עוד", + "reply_mentions.reply": "משיב ל-{accounts}{more}", + "reply_mentions.reply_empty": "משיב לפוסט", + "report.block": "חסום {target}", + "report.block_hint": "האם גם אתה רוצה לחסום את החשבון הזה?", + "report.forward": "העבר אל {target}", + "report.forward_hint": "החשבון הוא משרת אחר. לשלוח עותק של הדוח גם לשם?", + "report.hint": "הדוח יישלח למנהלי השרת שלך. תוכל לספק הסבר מדוע אתה מדווח על חשבון זה למטה:", "report.placeholder": "הערות נוספות", "report.submit": "שליחה", "report.target": "דיווח", - "schedule.post_time": "Post Date/Time", - "schedule.remove": "Remove schedule", - "schedule_button.add_schedule": "Schedule post for later", - "schedule_button.remove_schedule": "Post immediately", - "scheduled_status.cancel": "Cancel", + "schedule.post_time": "פרסום תאריך/שעה", + "schedule.remove": "הסר תזמון", + "schedule_button.add_schedule": "תזמן פוסט מאוחר יותר", + "schedule_button.remove_schedule": "פרסם מיד", + "scheduled_status.cancel": "בטל", + "search.action": "חפש “{query}”", "search.placeholder": "חיפוש", - "search_popout.search_format": "מבנה חיפוש מתקדם", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "האשתג", - "search_popout.tips.status": "post", - "search_popout.tips.user": "משתמש(ת)", - "search_results.accounts": "People", - "search_results.hashtags": "Hashtags", - "search_results.statuses": "Posts", - "search_results.top": "Top", - "security.codes.fail": "Failed to fetch backup codes", - "security.confirm.fail": "Incorrect code or password. Try again.", - "security.delete_account.fail": "Account deletion failed.", - "security.delete_account.success": "Account successfully deleted.", - "security.disable.fail": "Incorrect password. Try again.", - "security.disable_mfa": "Disable", - "security.fields.email.label": "Email address", - "security.fields.new_password.label": "New password", - "security.fields.old_password.label": "Current password", - "security.fields.password.label": "Password", - "security.fields.password_confirmation.label": "New password (again)", - "security.headers.delete": "Delete Account", - "security.headers.tokens": "Sessions", - "security.headers.update_email": "Change Email", - "security.headers.update_password": "Change Password", - "security.mfa": "Set up 2-Factor Auth", - "security.mfa_enabled": "You have multi-factor authentication set up with OTP.", - "security.mfa_header": "Authorization Methods", - "security.mfa_setup_hint": "Configure multi-factor authentication with OTP", - "security.qr.fail": "Failed to fetch setup key", - "security.submit": "Save changes", - "security.submit.delete": "Delete Account", - "security.text.delete": "To delete your account, enter your password then click Delete Account. This is a permanent action that cannot be undone. Your account will be destroyed from this server, and a deletion request will be sent to other servers. It's not guaranteed that all servers will purge your account.", - "security.tokens.revoke": "Revoke", - "security.update_email.fail": "Update email failed.", - "security.update_email.success": "Email successfully updated.", - "security.update_password.fail": "Update password failed.", - "security.update_password.success": "Password successfully updated.", - "signup_panel.subtitle": "Sign up now to discuss.", - "signup_panel.title": "New to {site_title}?", - "soapbox_config.authenticated_profile_hint": "Users must be logged-in to view replies and media on user profiles.", - "soapbox_config.authenticated_profile_label": "Profiles require authentication", - "soapbox_config.copyright_footer.meta_fields.label_placeholder": "Copyright footer", - "soapbox_config.crypto_address.meta_fields.address_placeholder": "Address", - "soapbox_config.crypto_address.meta_fields.note_placeholder": "Note (optional)", - "soapbox_config.crypto_address.meta_fields.ticker_placeholder": "Ticker", - "soapbox_config.crypto_donate_panel_limit.meta_fields.limit_placeholder": "Number of items to display in the crypto homepage widget", + "search_results.accounts": "אנשים", + "search_results.hashtags": "האשטאגס", + "search_results.statuses": "פוסטים", + "search_results.top": "עליון", + "security.codes.fail": "אחזור קודי גיבוי נכשל", + "security.confirm.fail": "קוד או סיסמא שגויים. נסה שוב.", + "security.delete_account.fail": "מחיקת החשבון נכשלה.", + "security.delete_account.success": "החשבון נמחק בהצלחה.", + "security.disable.fail": "סיסמא שגויה. נסה שוב.", + "security.disable_mfa": "השבת", + "security.fields.email.label": "אימייל", + "security.fields.new_password.label": "סיסמא חדשה", + "security.fields.old_password.label": "סיסמא נוכחית", + "security.fields.סיסמא.label": "סיסמא", + "security.fields.password_confirmation.label": "סיסמא חדשה (שוב)", + "security.headers.delete": "מחק חשבון", + "security.headers.tokens": "הפעלות", + "security.headers.update_email": "שנה אימייל", + "security.headers.update_password": "שנה סיסמא", + "security.mfa": "הגדר אימות דו-גורמי", + "security.mfa_enabled": "הגדרת אימות מרובה גורמים עם OTP.", + "security.mfa_header": "שיטות הרשאה", + "security.mfa_setup_hint": "הגדר אימות רב-גורמי עם OTP", + "security.qr.fail": "אחזור מפתח ההגדרה נכשל", + "security.submit": "שמור שינויים", + "security.submit.delete": "מחק חשבון", + "security.text.delete": "כדי למחוק את חשבונך, הזן את הסיסמה שלך ולאחר מכן לחץ על מחק חשבון. זוהי פעולה קבועה שלא ניתן לבטלה. החשבון שלך יושמד מהשרת הזה, ובקשת מחיקה תישלח לשרתים אחרים. לא מובטח שכל השרתים ינקו את חשבונך.", + "security.tokens.revoke": "בטל", + "security.update_email.fail": "עדכון האימייל נכשל.", + "security.update_email.success": "האימייל עודכן בהצלחה.", + "security.update_password.fail": "עדכון הסיסמא נכשל.", + "security.update_password.success": "הסיסמה עודכנה בהצלחה.", + "signup_panel.subtitle": "הירשם כעת כדי לדון.", + "signup_panel.title": "חדש ל{site_title}?", + "soapbox_config.authenticated_profile_hint": "משתמשים חייבים להיות מחוברים כדי לראות תגובות ומדיה בפרופילי משתמש.", + "soapbox_config.authenticated_profile_label": "פרופילים שדורשים אימות", + "soapbox_config.copyright_footer.meta_fields.label_placeholder": "כותרת תחתונה של זכויות יוצרים", + "soapbox_config.crypto_address.meta_fields.address_placeholder": "כתובת", + "soapbox_config.crypto_address.meta_fields.note_placeholder": "הערה (אפשרי)", + "soapbox_config.crypto_address.meta_fields.ticker_placeholder": "טיקר", + "soapbox_config.crypto_donate_panel_limit.meta_fields.limit_placeholder": "מספר הפריטים להצגה בווידג'ט דף הבית של קריפטו", "soapbox_config.custom_css.meta_fields.url_placeholder": "URL", - "soapbox_config.display_fqn_label": "Display domain (eg @user@domain) for local accounts.", - "soapbox_config.fields.brand_color_label": "Brand color", - "soapbox_config.fields.crypto_address.add": "Add new crypto address", - "soapbox_config.fields.crypto_addresses_label": "Cryptocurrency addresses", - "soapbox_config.fields.home_footer.add": "Add new Home Footer Item", - "soapbox_config.fields.home_footer_fields_label": "Home footer items", - "soapbox_config.fields.logo_label": "Logo", - "soapbox_config.fields.promo_panel.add": "Add new Promo panel item", - "soapbox_config.fields.promo_panel_fields_label": "Promo panel items", - "soapbox_config.fields.theme_label": "Default theme", - "soapbox_config.greentext_label": "Enable greentext support", - "soapbox_config.hints.crypto_addresses": "Add cryptocurrency addresses so users of your site can donate to you. Order matters, and you must use lowercase ticker values.", - "soapbox_config.hints.home_footer_fields": "You can have custom defined links displayed on the footer of your static pages", - "soapbox_config.hints.logo": "SVG. At most 2 MB. Will be displayed to 50px height, maintaining aspect ratio", - "soapbox_config.hints.promo_panel_fields": "You can have custom defined links displayed on the right panel of the timelines page.", + "soapbox_config.display_fqn_label": "הצג דומיין (למשל @user@domain) עבור חשבונות מקומיים.", + "soapbox_config.fields.brand_color_label": "צבע מותג", + "soapbox_config.fields.crypto_address.add": "הוסף כתובת קריפטו חדשה", + "soapbox_config.fields.crypto_addresses_label": "כתובות של מטבעות קריפטוגרפיים", + "soapbox_config.fields.home_footer.add": "הוסף פריט כותרת תחתונה חדש לבית", + "soapbox_config.fields.home_footer_fields_label": "פריטי כותרת תחתונה של הבית", + "soapbox_config.fields.logo_label": "לוגו", + "soapbox_config.fields.promo_panel.add": "הוסף פריטי פאנל פרומו חדשים", + "soapbox_config.fields.promo_panel_fields_label": "פריטי פאנל לפרומו", + "soapbox_config.fields.theme_label": "ערכת נושא המוגדרת כברירת מחדל", + "soapbox_config.greentext_label": "אפשר תמיכה ב-greentext", + "soapbox_config.hints.crypto_addresses": "הוסף כתובות של מטבעות קריפטוגרפיים כדי שמשתמשי האתר שלך יוכלו לתרום לך. יש חשיבות לסדר, ועליך להשתמש בערכי טיקרים קטנים.", + "soapbox_config.hints.home_footer_fields": "אתה יכול להציג קישורים מוגדרים בהתאמה אישית בכותרת התחתונה של הדפים הסטטיים שלך", + "soapbox_config.hints.logo": "SVG. לכל היותר 2 מגה-בייט. יוצג בגובה של 50 פיקסלים, תוך שמירה על יחס רוחב-גובה", + "soapbox_config.hints.promo_panel_fields": "אתה יכול להציג קישורים מוגדרים בהתאמה אישית בחלונית לצד דף ציר הזמן.", "soapbox_config.hints.promo_panel_icons": "{ link }", - "soapbox_config.hints.promo_panel_icons.link": "Soapbox Icons List", - "soapbox_config.home_footer.meta_fields.label_placeholder": "Label", + "soapbox_config.hints.promo_panel_icons.link": "רשימת אייקוני סבוניה", + "soapbox_config.home_footer.meta_fields.label_placeholder": "תווית", "soapbox_config.home_footer.meta_fields.url_placeholder": "URL", - "soapbox_config.promo_panel.meta_fields.icon_placeholder": "Icon", - "soapbox_config.promo_panel.meta_fields.label_placeholder": "Label", + "soapbox_config.promo_panel.meta_fields.icon_placeholder": "סמל", + "soapbox_config.promo_panel.meta_fields.label_placeholder": "תווית", "soapbox_config.promo_panel.meta_fields.url_placeholder": "URL", - "soapbox_config.raw_json_hint": "Edit the settings data directly. Changes made directly to the JSON file will override the form fields above. Click Save to apply your changes.", - "soapbox_config.raw_json_label": "Advanced: Edit raw JSON data", - "soapbox_config.save": "Save", - "soapbox_config.saved": "Soapbox config saved!", - "soapbox_config.verified_can_edit_name_label": "Allow verified users to edit their own display name.", - "status.admin_account": "Open moderation interface for @{name}", - "status.admin_status": "Open this post in the moderation interface", - "status.block": "Block @{name}", - "status.bookmark": "Bookmark", - "status.bookmarked": "Bookmark added.", - "status.cancel_reblog_private": "Un-repost", + "soapbox_config.raw_json_hint": "ערוך את נתוני ההגדרות ישירות. שינויים שנעשו ישירות בקובץ JSON יעקפו את שדות הטופס שלמעלה. לחץ על שמור כדי להחיל את השינויים שלך.", + "soapbox_config.raw_json_label": "מתקדם: ערוך נתוני JSON גולמיים", + "soapbox_config.save": "שמור", + "soapbox_config.saved": "תצורת סבוניה נשמרה!", + "soapbox_config.verified_can_edit_name_label": "אפשר למשתמשים מאומתים לערוך את שם התצוגה שלהם.", + "status.admin_account": "פתח ממשק ניהול ל@{name}", + "status.admin_status": "פתח את הפוסט הזה בממשק הניהול", + "status.block": "חסום @{name}", + "status.bookmark": "סימניה", + "status.bookmarked": "סימניה נוספה.", + "status.cancel_reblog_private": "הסר הדהוד", "status.cannot_reblog": "לא ניתן להדהד הודעה זו", - "status.chat": "Chat with @{name}", - "status.copy": "Copy link to post", + "status.chat": "שוחח עם @{name}", + "status.copy": "העתק קישור לפוסט", "status.delete": "מחיקה", - "status.detailed_status": "Detailed conversation view", - "status.direct": "Direct message @{name}", + "status.detailed_status": "תצוגת שיחה מפורטת", + "status.direct": "הודעה ישירה @{name}", "status.embed": "הטמעה", "status.favourite": "חיבוב", - "status.filtered": "Filtered", + "status.filtered": "מסונן", "status.load_more": "עוד", "status.media_hidden": "מדיה מוסתרת", "status.mention": "פניה אל @{name}", "status.more": "עוד", - "status.mute": "Mute @{name}", + "status.mute": "השתק @{name}", "status.mute_conversation": "השתקת שיחה", "status.open": "הרחבת הודעה", "status.pin": "לקבע באודות", - "status.pinned": "Pinned post", - "status.reactions.cry": "Sad", - "status.reactions.empty": "No one has reacted to this post yet. When someone does, they will show up here.", - "status.reactions.heart": "Love", - "status.reactions.laughing": "Haha", - "status.reactions.like": "Like", - "status.reactions.open_mouth": "Wow", - "status.reactions.weary": "Weary", - "status.reactions_expand": "Select emoji", - "status.read_more": "Read more", + "status.pinned": "פוסט נעוץ", + "status.reactions.cry": "עצוב", + "status.reactions.empty": "אף אחד עדיין לא הגיב לפוסט הזה. כשמישהו יעשה זאת, הוא יופיע כאן.", + "status.reactions.heart": "אהבה", + "status.reactions.laughing": "חחח", + "status.reactions.like": "לייק", + "status.reactions.open_mouth": "ואו!", + "status.reactions.weary": "מיוגע", + "status.reactions_expand": "בחר אימוג'י", + "status.read_more": "קרא עוד", "status.reblog": "הדהוד", - "status.reblog_private": "Repost to original audience", + "status.reblog_private": "הדהוד לקהל המקורי", "status.reblogged_by": "הודהד על ידי {name}", - "status.reblogs.empty": "No one has reposted this post yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.remove_account_from_group": "Remove account from group", - "status.remove_post_from_group": "Remove post from group", + "status.reblogs.empty": "אף אחד עדיין לא פרסם מחדש את הפוסט הזה. כשמישהו יעשה זאת, הוא יופיע כאן.", + "status.redraft": "מחק וכתוב מחדש", + "status.remove_account_from_group": "הסר חשבון מהקבוצה", + "status.remove_post_from_group": "הסר פוסט מהקבוצה", "status.reply": "תגובה", "status.replyAll": "תגובה לכולם", "status.report": "דיווח על @{name}", "status.sensitive_warning": "תוכן רגיש", "status.share": "שיתוף", "status.show_less": "הראה פחות", - "status.show_less_all": "Show less for all", + "status.show_less_all": "הצג פחות לכולם", "status.show_more": "הראה יותר", - "status.show_more_all": "Show more for all", - "status.show_thread": "Show thread", - "status.title": "Post", - "status.title_direct": "Direct message", - "status.unbookmark": "Remove bookmark", - "status.unbookmarked": "Bookmark removed.", + "status.show_more_all": "הראה יותר לכולם", + "status.show_thread": "הצג שרשור", + "status.title": "פוסט", + "status.title_direct": "הודעה ישירה", + "status.unbookmark": "הסר סימניה", + "status.unbookmarked": "סימניה הוסרה.", "status.unmute_conversation": "הסרת השתקת שיחה", "status.unpin": "לשחרר מקיבוע באודות", - "status_list.queue_label": "Click to see {count} new {count, plural, one {post} other {posts}}", - "statuses.tombstone": "One or more posts is unavailable.", - "suggestions.dismiss": "Dismiss suggestion", - "tabs_bar.all": "All", - "tabs_bar.apps": "Apps", - "tabs_bar.chats": "Chats", - "tabs_bar.dashboard": "Dashboard", - "tabs_bar.fediverse": "Fediverse", - "tabs_bar.header": "Account Info", - "tabs_bar.home": "בבית", - "tabs_bar.news": "News", + "status_list.queue_label": "לחץ כדי לראות {count} חדשים {count, plural, one {פוסט} other {פוסטים}}", + "statuses.tombstone": "פוסט אחד או יותר אינו זמין.", + "suggestions.dismiss": "דחה את ההצעה", + "tabs_bar.all": "הכל", + "tabs_bar.apps": "אפליקציות", + "tabs_bar.chats": "צ'אטים", + "tabs_bar.dashboard": "לוח מחוונים", + "tabs_bar.fediverse": "פדרציה", + "tabs_bar.header": "פרטי חשבון", + "tabs_bar.home": "בית", + "tabs_bar.news": "חדשות", "tabs_bar.notifications": "התראות", - "tabs_bar.post": "Post", - "tabs_bar.search": "Search", - "tabs_bar.theme_toggle_dark": "Switch to dark theme", - "tabs_bar.theme_toggle_light": "Switch to light theme", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", - "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.title": "Trends", - "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.", - "unauthorized_modal.footer": "Already have an account? {login}.", - "unauthorized_modal.text": "You need to be logged in to do that.", - "unauthorized_modal.title": "Sign up for {site_title}", + "tabs_bar.post": "פוסט", + "tabs_bar.search": "חיפוש", + "tabs_bar.theme_toggle_dark": "עבור לערכת נושא כהה", + "tabs_bar.theme_toggle_light": "עבור לערכת נושא בהירה", + "time_remaining.days": "{number, plural, one {# יום} other {# ימים}} נותרו", + "time_remaining.hours": "{number, plural, one {# שעה} other {# שעות}} נותרו", + "time_remaining.minutes": "{number, plural, one {# דקה} other {# דקות}} נותרו", + "time_remaining.moments": "נותרו רגעים", + "time_remaining.seconds": "{number, plural, one {# שנייה} other {# שניות}} נותרו", + "trends.count_by_accounts": "{count} {rawCount, plural, one {אדם} other {אנשים}} מדברים", + "trends.title": "טרנדים", + "ui.beforeunload": "הטיוטא תאבד אם תעזבו את סבוניה.", + "unauthorized_modal.footer": "כבר יש לך חשבון? {login}.", + "unauthorized_modal.text": "אתה צריך להיות מחובר כדי לעשות זאת.", + "unauthorized_modal.title": "להירשם ל{site_title}", "upload_area.title": "ניתן להעלות על ידי Drag & drop", "upload_button.label": "הוספת מדיה", - "upload_error.limit": "File upload limit exceeded.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.limit": "חרגת ממגבלת העלאת הקבצים.", + "upload_error.poll": "העלאת קבצים אסורה ביחד עם סקרים.", "upload_form.description": "תיאור לכבדי ראיה", - "upload_form.preview": "Preview", + "upload_form.preview": "תצוגה מקדימה", "upload_form.undo": "ביטול", "upload_progress.label": "עולה...", "video.close": "סגירת וידאו", - "video.download": "Download file", + "video.download": "הורד קובץ", "video.exit_fullscreen": "יציאה ממסך מלא", "video.expand": "להרחיב וידאו", - "video.fullscreen": "Full screen", + "video.fullscreen": "מסך מלא", "video.hide": "להסתיר וידאו", "video.mute": "השתקת צליל", - "video.pause": "Pause", + "video.pause": "השהיה", "video.play": "ניגון", "video.unmute": "החזרת צליל", - "who_to_follow.title": "Who To Follow" + "who_to_follow.title": "מי לעקוב" } diff --git a/app/soapbox/locales/hi.json b/app/soapbox/locales/hi.json index 36622d3a5..b0324e7f1 100644 --- a/app/soapbox/locales/hi.json +++ b/app/soapbox/locales/hi.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/hr.json b/app/soapbox/locales/hr.json index 3a5ea60bc..a852d25fc 100644 --- a/app/soapbox/locales/hr.json +++ b/app/soapbox/locales/hr.json @@ -8,6 +8,7 @@ "account.block_domain": "Sakrij sve sa {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "te slijedi", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Utišaj @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Postovi", "account.posts_with_replies": "Toots with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokirani korisnici", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokalni timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Zahtjevi za slijeđenje", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Dom", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Utišani korisnici", "column.notifications": "Notifikacije", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federalni timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Natrag", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokiraj", "confirmations.block.message": "Želiš li sigurno blokirati {name}?", "confirmations.delete.confirm": "Obriši", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Želiš li stvarno obrisati ovaj status?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autoriziraj", "follow_request.reject": "Odbij", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} je softver otvorenog koda. Možeš pridonijeti ili prijaviti probleme na GitLabu {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoriti", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Zahtjevi za slijeđenje", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Više informacija", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Odjavi se", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Utišani korisnici", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Postavke", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Otkaži", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Traži", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/hu.json b/app/soapbox/locales/hu.json index e372db310..47ff489bd 100644 --- a/app/soapbox/locales/hu.json +++ b/app/soapbox/locales/hu.json @@ -8,6 +8,7 @@ "account.block_domain": "Minden elrejtése innen: {domain}", "account.blocked": "Letiltva", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Ez a felhasználó még senkit sem követ.", "account.follows_you": "Követ téged", "account.hide_reblogs": "@{name} megtolásainak némítása", + "account.last_status": "Last active", "account.link_verified_on": "A linket ellenőriztük: {date}", "account.locked_info": "Ez a fiók zárt. A tulaj engedélyezi, ki követheti őt.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} átköltözött:", "account.mute": "@{name} némítása", "account.muted": "Némítva", + "account.never_active": "Never", "account.posts": "Tülkölés", "account.posts_with_replies": "Tülkölés válaszokkal", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Bezárás", "bundle_modal_error.message": "Hiba történt a komponens betöltésekor.", "bundle_modal_error.retry": "Próbáld újra", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Letiltott felhasználók", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Helyi idővonal", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Közvetlen üzenetek", + "column.directory": "Browse profiles", "column.domain_blocks": "Rejtett domainek", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Követési kérelmek", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Kezdőlap", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listák", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Némított felhasználók", "column.notifications": "Értesítések", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Nyilvános idővonal", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Vissza", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Beállítások elrejtése", "column_header.show_settings": "Beállítások mutatása", "community.column_settings.media_only": "Csak média", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Szavazás időtartama", "compose_form.poll.option_placeholder": "Lehetőség {number}", "compose_form.poll.remove_option": "Lehetőség törlése", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tülk", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Letiltás és Bejelentés", "confirmations.block.confirm": "Letiltás", "confirmations.block.message": "Biztos, hogy le szeretnéd tiltani {name}?", "confirmations.delete.confirm": "Törlés", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Biztos, hogy törölni szeretnéd ezt a tülkölést?", "confirmations.delete_list.confirm": "Törlés", "confirmations.delete_list.message": "Biztos, hogy véglegesen törölni szeretnéd ezt a listát?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Engedélyezés", "follow_request.reject": "Visszautasítás", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "A {code_name} nyílt forráskódú szoftver. Csatlakozhatsz a fejlesztéshez vagy jelenthetsz problémákat GitLab-on {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Előző", "lightbox.view_context": "Kontextus megtekintése", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Hozzáadás a listához", "lists.account.remove": "Eltávolítás a listából", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Rejtsük el a felhasználótól származó értesítéseket?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Új tülk írása", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Rejtett domainek", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Kedvencek", "navigation_bar.filters": "Némított szavak", "navigation_bar.follow_requests": "Követési kérelmek", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Erről a szerverről", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Gyorsbillentyűk", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Kijelentkezés", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Némított felhasználók", "navigation_bar.pins": "Kitűzött tülkök", "navigation_bar.preferences": "Beállítások", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Biztonság", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Frissítés", "poll.total_votes": "{count, plural, one {# szavazat} other {# szavazat}}", "poll.vote": "Szavazás", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Új szavazás", "poll_button.remove_poll": "Szavazás törlése", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Töltődik…", "regeneration_indicator.sublabel": "A saját idővonalad épp készül!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}nap", "relative_time.hours": "{number}ó", "relative_time.just_now": "most", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Mégsem", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Továbbítás neki {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Keresés", - "search_popout.search_format": "Haladó keresés", - "search_popout.tips.full_text": "Egyszerű szöveg. Illeszkedő, általad írt tülköket, kedvencnek jelöléseket, megtolást, megemlítést, felhasználói nevet, megjelenített nevet, hashtageket ad majd vissza.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "tülk", - "search_popout.tips.user": "felhasználó", "search_results.accounts": "Emberek", "search_results.hashtags": "Hashtagek", "search_results.statuses": "Tülkök", diff --git a/app/soapbox/locales/hy.json b/app/soapbox/locales/hy.json index 7a7a6c8d4..550666218 100644 --- a/app/soapbox/locales/hy.json +++ b/app/soapbox/locales/hy.json @@ -8,6 +8,7 @@ "account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Հետեւում է քեզ", "account.hide_reblogs": "Թաքցնել @{name}֊ի տարածածները", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name}֊ը տեղափոխվել է՝", "account.mute": "Լռեցնել @{name}֊ին", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Գրառումներ", "account.posts_with_replies": "Toots with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Փակել", "bundle_modal_error.message": "Այս բաղադրիչը բեռնելու ընթացքում ինչ֊որ բան խափանվեց։", "bundle_modal_error.retry": "Կրկին փորձել", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Արգելափակված օգտատերեր", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Տեղական հոսք", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Հետեւելու հայցեր", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Հիմնական", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Ցանկեր", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Լռեցրած օգտատերեր", "column.notifications": "Ծանուցումներ", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Դաշնային հոսք", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Ետ", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Թաքցնել կարգավորումները", "column_header.show_settings": "Ցուցադրել կարգավորումները", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Թթել", "compose_form.publish_loud": "Թթե՜լ", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Արգելափակել", "confirmations.block.message": "Վստա՞հ ես, որ ուզում ես արգելափակել {name}֊ին։", "confirmations.delete.confirm": "Ջնջել", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Վստա՞հ ես, որ ուզում ես ջնջել այս թութը։", "confirmations.delete_list.confirm": "Ջնջել", "confirmations.delete_list.message": "Վստա՞հ ես, որ ուզում ես մշտապես ջնջել այս ցանկը։", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Վավերացնել", "follow_request.reject": "Մերժել", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "Մաստոդոնը բաց ելատեքստով ծրագրակազմ է։ Կարող ես ներդրում անել կամ վրեպներ զեկուցել ԳիթՀաբում՝ {code_link} (v{code_version})։", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Նախորդ", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Ավելացնել ցանկին", "lists.account.remove": "Հանել ցանկից", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Թաքցնե՞լ ցանուցումներն այս օգտատիրոջից։", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Հավանածներ", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Հետեւելու հայցեր", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Այս հանգույցի մասին", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Ստեղնաշարի կարճատներ", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Դուրս գալ", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Լռեցրած օգտատերեր", "navigation_bar.pins": "Ամրացված թթեր", "navigation_bar.preferences": "Նախապատվություններ", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Անվտանգություն", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}օր", "relative_time.hours": "{number}ժ", "relative_time.just_now": "նոր", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Չեղարկել", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Փնտրել", - "search_popout.search_format": "Փնտրելու առաջադեմ ձեւ", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "պիտակ", - "search_popout.tips.status": "թութ", - "search_popout.tips.user": "օգտատեր", "search_results.accounts": "Մարդիկ", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/id.json b/app/soapbox/locales/id.json index 0e8a5d034..fbffecc35 100644 --- a/app/soapbox/locales/id.json +++ b/app/soapbox/locales/id.json @@ -8,6 +8,7 @@ "account.block_domain": "Sembunyikan segalanya dari {domain}", "account.blocked": "Terblokir", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Pengguna ini belum mengikuti siapapun.", "account.follows_you": "Mengikuti anda", "account.hide_reblogs": "Sembunyikan boosts dari @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Kepemilikan tautan ini telah dicek pada {date}", "account.locked_info": "Status privasi akun ini disetel untuk dikunci. Pemilik secara manual meninjau siapa yang dapat mengikuti mereka.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} telah pindah ke:", "account.mute": "Bisukan @{name}", "account.muted": "Dibisukan", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Postingan dengan balasan", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Tutup", "bundle_modal_error.message": "Kesalahan terjadi saat memuat komponen ini.", "bundle_modal_error.retry": "Coba lagi", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Pengguna diblokir", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Linimasa Lokal", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Pesan langsung", + "column.directory": "Browse profiles", "column.domain_blocks": "Topik tersembunyi", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Permintaan mengikuti", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Beranda", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "List", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Pengguna yang dibisukan", "column.notifications": "Notifikasi", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Linimasa gabungan", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Kembali", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Sembunyikan pengaturan", "column_header.show_settings": "Tampilkan pengaturan", "community.column_settings.media_only": "Hanya media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durasi jajak pendapat", "compose_form.poll.option_placeholder": "Pilihan {number}", "compose_form.poll.remove_option": "Hapus opsi ini", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokir & Laporkan", "confirmations.block.confirm": "Blokir", "confirmations.block.message": "Apa anda yakin ingin memblokir {name}?", "confirmations.delete.confirm": "Hapus", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Apa anda yakin untuk menghapus status ini?", "confirmations.delete_list.confirm": "Hapus", "confirmations.delete_list.message": "Apakah anda yakin untuk menghapus daftar ini secara permanen?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Izinkan", "follow_request.reject": "Tolak", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} adalah perangkat lunak yang bersifat terbuka. Anda dapat berkontribusi atau melaporkan permasalahan/bug di Gitlab {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Sebelumnya", "lightbox.view_context": "Lihat konteks", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Tambah ke daftar", "lists.account.remove": "Hapus dari daftar", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Sembunyikan notifikasi dari pengguna ini?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Tulis toot baru", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domain tersembunyi", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorit", "navigation_bar.filters": "Kata yang dibisukan", "navigation_bar.follow_requests": "Permintaan mengikuti", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Informasi selengkapnya", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Keluar", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Pengguna dibisukan", "navigation_bar.pins": "Toot tersemat", "navigation_bar.preferences": "Pengaturan", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Keamanan", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Segarkan", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Linimasa anda sedang disiapkan!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Batal", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Pencarian", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "tagar", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/io.json b/app/soapbox/locales/io.json index dcebc9a25..3cbbb920d 100644 --- a/app/soapbox/locales/io.json +++ b/app/soapbox/locales/io.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Sequas tu", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Celar @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Mesaji", "account.posts_with_replies": "Toots with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokusita uzeri", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokala tempolineo", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Demandi di sequado", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hemo", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Celita uzeri", "column.notifications": "Savigi", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federata tempolineo", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Retro", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Siflar", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Yurizar", "follow_request.reject": "Refuzar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} esas programaro kun apertita kodexo. Tu povas kontributar o signalar problemi en GitLab ye {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorati", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Demandi di sequado", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Detaloza informi", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Ekirar", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Celita uzeri", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferi", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Nihiligar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Serchez", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/it.json b/app/soapbox/locales/it.json index 809f44196..4cd1f75f0 100644 --- a/app/soapbox/locales/it.json +++ b/app/soapbox/locales/it.json @@ -8,6 +8,7 @@ "account.block_domain": "Nascondi tutto da {domain}", "account.blocked": "Bloccato", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Questo utente non segue ancora nessuno.", "account.follows_you": "Ti segue", "account.hide_reblogs": "Nascondi condivisioni da @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La proprietà di questo link è stata controllata il {date}", "account.locked_info": "Il livello di privacy di questo account è impostato a \"bloccato\". Il proprietario esamina manualmente le richieste di seguirlo.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} si è trasferito su:", "account.mute": "Silenzia @{name}", "account.muted": "Silenziato", + "account.never_active": "Never", "account.posts": "Toot", "account.posts_with_replies": "Toot e risposte", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Chiudi", "bundle_modal_error.message": "C'è stato un errore mentre questo componente veniva caricato.", "bundle_modal_error.retry": "Riprova", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Utenti bloccati", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Timeline locale", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Messaggi diretti", + "column.directory": "Browse profiles", "column.domain_blocks": "Domini nascosti", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Richieste di amicizia", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Liste", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Utenti silenziati", "column.notifications": "Notifiche", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Timeline federata", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Indietro", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Nascondi impostazioni", "column_header.show_settings": "Mostra impostazioni", "community.column_settings.media_only": "Solo media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durata del sondaggio", "compose_form.poll.option_placeholder": "Scelta {number}", "compose_form.poll.remove_option": "Rimuovi questa scelta", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blocca & Segnala", "confirmations.block.confirm": "Blocca", "confirmations.block.message": "Sei sicuro di voler bloccare {name}?", "confirmations.delete.confirm": "Cancella", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Sei sicuro di voler cancellare questo status?", "confirmations.delete_list.confirm": "Cancella", "confirmations.delete_list.message": "Sei sicuro di voler cancellare definitivamente questa lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizza", "follow_request.reject": "Rifiuta", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} è un software open source. Puoi contribuire o segnalare errori su GitLab all'indirizzo {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Precedente", "lightbox.view_context": "Mostra contesto", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Aggiungi alla lista", "lists.account.remove": "Togli dalla lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Nascondere le notifiche da quest'utente?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Componi nuovo toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domini nascosti", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Apprezzati", "navigation_bar.filters": "Parole silenziate", "navigation_bar.follow_requests": "Richieste di amicizia", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Informazioni su questo server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Tasti di scelta rapida", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Esci", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Utenti silenziati", "navigation_bar.pins": "Toot fissati in cima", "navigation_bar.preferences": "Impostazioni", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sicurezza", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Aggiorna", "poll.total_votes": "{count, plural, one {# voto} other {# voti}}", "poll.vote": "Vota", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Aggiungi un sondaggio", "poll_button.remove_poll": "Rimuovi sondaggio", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Caricamento in corso…", "regeneration_indicator.sublabel": "Stiamo preparando il tuo home feed!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}g", "relative_time.hours": "{number}o", "relative_time.just_now": "ora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Annulla", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Inoltra a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Cerca", - "search_popout.search_format": "Formato di ricerca avanzato", - "search_popout.tips.full_text": "Testo semplice per trovare gli status che hai scritto, segnato come apprezzati, condiviso o in cui sei stato citato, e inoltre i nomi utente, nomi visualizzati e hashtag che lo contengono.", - "search_popout.tips.hashtag": "etichetta", - "search_popout.tips.status": "stato", - "search_popout.tips.user": "utente", "search_results.accounts": "Gente", "search_results.hashtags": "Hashtag", "search_results.statuses": "Toot", diff --git a/app/soapbox/locales/ja.json b/app/soapbox/locales/ja.json index 2b6234e2d..6588f10c6 100644 --- a/app/soapbox/locales/ja.json +++ b/app/soapbox/locales/ja.json @@ -8,6 +8,7 @@ "account.block_domain": "{domain}全体を非表示", "account.blocked": "ブロック済み", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "まだ誰もフォローしていません。", "account.follows_you": "フォローされています", "account.hide_reblogs": "@{name}さんからのリピートを非表示", + "account.last_status": "Last active", "account.link_verified_on": "このリンクの所有権は{date}に確認されました", "account.locked_info": "このアカウントは承認制アカウントです。相手が承認するまでフォローは完了しません。", "account.login": "ログイン", @@ -31,6 +33,7 @@ "account.moved_to": "{name}さんは引っ越しました:", "account.mute": "@{name}さんをミュート", "account.muted": "ミュート済み", + "account.never_active": "Never", "account.posts": "投稿", "account.posts_with_replies": "投稿と返信", "account.profile": "プロフィール", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "閉じる", "bundle_modal_error.message": "コンポーネントの読み込み中に問題が発生しました。", "bundle_modal_error.retry": "再試行", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "送信", "chat_box.input.placeholder": "メッセージを送信……", "chat_panels.main_window.empty": "チャットがありません。始めるにはユーザのプロフィール画面へ移動してください。", @@ -137,6 +156,8 @@ "chats.actions.delete": "メッセージを削除", "chats.actions.more": "もっと", "chats.actions.report": "ユーザを通報", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "音声通知をOFF", "chats.audio_toggle_on": "音声通知をON", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "ブロックしたユーザー", "column.bookmarks": "ブックマーク", "column.chats": "チャット", "column.community": "公開タイムライン", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "ダイレクトメッセージ", + "column.directory": "Browse profiles", "column.domain_blocks": "非表示にしたドメイン", "column.edit_profile": "プロフィール編集", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "ミュートした単語", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "全体一致", "column.filters.whole_word_hint": "単語もしくは成句が英数字のみの場合、単語全体に一致する場合のみ適用されます", "column.follow_requests": "フォローリクエスト", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "ホーム", "column.import_data": "インポートデータ", "column.info": "Server information", "column.lists": "リスト", + "column.mentions": "Mentions", "column.mfa": "多要素認証", "column.mfa_cancel": "取消", "column.mfa_confirm_button": "確認", @@ -195,8 +224,11 @@ "column.mfa_setup": "設定を開始", "column.mutes": "ミュートしたユーザー", "column.notifications": "通知", + "column.pins": "Pinned posts", "column.preferences": "環境設定", + "column.profile_directory": "Profile directory", "column.public": "接続しているすべてのネットワーク", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "セキュリティ", "column.soapbox_config": "Soapbox設定", "column_back_button.label": "戻る", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "設定を隠す", "column_header.show_settings": "設定を表示", "community.column_settings.media_only": "メディアのみ表示", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "アンケート期間", "compose_form.poll.option_placeholder": "項目 {number}", "compose_form.poll.remove_option": "この項目を削除", - "compose_form.poll.type.hint": "クリックして投票方式を切り替えます。ラジオボタン(デフォルト)は単一選択。チェックボックスは複数選択。", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "投稿", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "ブロックし通報", "confirmations.block.confirm": "ブロック", "confirmations.block.message": "本当に{name}さんをブロックしますか?", "confirmations.delete.confirm": "削除", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "本当に削除しますか?", "confirmations.delete_list.confirm": "削除", "confirmations.delete_list.message": "本当にこのリストを完全に削除しますか?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "自己紹介", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "これはBOTアカウントです", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "表示名", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "ヘッダー", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF もしくは JPG. 最大 2 MB. 400x400pxへ縮小されます", "edit_profile.hints.bot": "このアカウントは主に自動で行動し、監視されていない場合があります", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF もしくは JPG. 最大 2 MB. 1500x500pxへ縮小されます", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "フォロワーを手動で承認する必要があります", @@ -397,6 +443,8 @@ "follow_request.authorize": "許可", "follow_request.reject": "拒否", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name}はオープンソースソフトウェアです。誰でもGitLab ( {code_link} (v{code_version}) ) から開発に参加したり、問題を報告したりできます。", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "前", "lightbox.view_context": "投稿を表示", "list.click_to_add": "クリックして追加", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "リストから追加もしくは外す", "lists.account.add": "リストに追加", "lists.account.remove": "リストから外す", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "このユーザーからの通知を隠しますか?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "投稿の新規作成", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "非表示にしたドメイン", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "お気に入り", "navigation_bar.filters": "フィルター設定", "navigation_bar.follow_requests": "フォローリクエスト", "navigation_bar.import_data": "データのインポート", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "このサーバーについて", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "ホットキー", "navigation_bar.lists": "Lists", "navigation_bar.logout": "ログアウト", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "ミュートしたユーザー", "navigation_bar.pins": "固定した投稿", "navigation_bar.preferences": "ユーザー設定", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "セキュリティ", "navigation_bar.soapbox_config": "Soapbox設定", "notification.chat_mention": "{name}さんがあなたにメッセージを送りました", @@ -627,14 +682,18 @@ "poll.refresh": "更新", "poll.total_votes": "{count}票", "poll.vote": "投票", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "アンケートを追加", "poll_button.remove_poll": "アンケートを削除", "preferences.fields.auto_play_gif_label": "アニメGIFを自動再生する", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "リピートする前に確認ダイアログを表示する", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "投稿を削除する前に確認ダイアログを表示する", "preferences.fields.demetricator_label": "指標隠蔽器を使う", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "読み込み中…", "regeneration_indicator.sublabel": "ホームタイムラインは準備中です!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "ユーザ名", "registration.lead": "{instance}のアカウントひとつでFediverseのすべてのサーバにいる人をフォローできます。", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "なぜ参加したいのですか?", "registration.reason_hint": "これはあなたの申請を評価する助けになります", "registration.sign_up": "新規登録", "registration.tos": "利用規約", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}日前", "relative_time.hours": "{number}時間前", "relative_time.just_now": "今", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "キャンセル", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "{target}さんをブロック", "report.block_hint": "このアカウントをブロックしますか?", "report.forward": "{target}に転送する", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "検索", - "search_popout.search_format": "高度な検索フォーマット", - "search_popout.tips.full_text": "表示名やユーザー名、ハッシュタグのほか、あなたの投稿やお気に入り、リピートした投稿、返信に一致する単純なテキスト。", - "search_popout.tips.hashtag": "ハッシュタグ", - "search_popout.tips.status": "投稿", - "search_popout.tips.user": "ユーザー", "search_results.accounts": "人々", "search_results.hashtags": "ハッシュタグ", "search_results.statuses": "投稿", diff --git a/app/soapbox/locales/ka.json b/app/soapbox/locales/ka.json index ab8554be1..b2127682e 100644 --- a/app/soapbox/locales/ka.json +++ b/app/soapbox/locales/ka.json @@ -8,6 +8,7 @@ "account.block_domain": "დაიმალოს ყველაფერი დომენიდან {domain}", "account.blocked": "დაიბლოკა", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "მოგყვებათ", "account.hide_reblogs": "დაიმალოს ბუსტები @{name}-სგან", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} გადავიდა:", "account.mute": "გააჩუმე @{name}", "account.muted": "გაჩუმებული", + "account.never_active": "Never", "account.posts": "ტუტები", "account.posts_with_replies": "ტუტები და პასუხები", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "დახურვა", "bundle_modal_error.message": "ამ კომპონენტის ჩატვირთვისას რაღაც აირია.", "bundle_modal_error.retry": "სცადეთ კიდევ ერთხელ", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "დაბლოკილი მომხმარებლები", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "ლოკალური თაიმლაინი", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "პირდაპირი წერილები", + "column.directory": "Browse profiles", "column.domain_blocks": "დამალული დომენები", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "დადევნების მოთხოვნები", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "სახლი", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "სიები", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "გაჩუმებული მომხმარებლები", "column.notifications": "შეტყობინებები", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "ფედერალური თაიმლაინი", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "უკან", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "პარამეტრების დამალვა", "column_header.show_settings": "პარამეტრების ჩვენება", "community.column_settings.media_only": "მხოლოდ მედია", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "ტუტი", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "ბლოკი", "confirmations.block.message": "დარწმუნებული ხართ, გსურთ დაბლოკოთ {name}?", "confirmations.delete.confirm": "გაუქმება", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "დარწმუნებული ხართ, გსურთ გააუქმოთ ეს სტატუსი?", "confirmations.delete_list.confirm": "გაუქმება", "confirmations.delete_list.message": "დარწმუნებული ხართ, გსურთ სამუდამოდ გააუქმოთ ეს სია?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "ავტორიზაცია", "follow_request.reject": "უარყოფა", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "მასტოდონი ღია პროგრამაა. შეგიძლიათ შეუწყოთ ხელი ან შექმნათ პრობემის რეპორტი {code_link} (v{code_version})-ზე.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "წინა", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "სიაში დამატება", "lists.account.remove": "სიიდან ამოშლა", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "დავმალოთ შეტყობინებები ამ მომხმარებლისგან?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "დამალული დომენები", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "ფავორიტები", "navigation_bar.filters": "გაჩუმებული სიტყვები", "navigation_bar.follow_requests": "დადევნების მოთხოვნები", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "ამ ინსტანციის შესახებ", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "ცხელი კლავიშები", "navigation_bar.lists": "Lists", "navigation_bar.logout": "გასვლა", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "გაჩუმებული მომხმარებლები", "navigation_bar.pins": "აპინული ტუტები", "navigation_bar.preferences": "პრეფერენსიები", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "უსაფრთხოება", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "იტვირთება…", "regeneration_indicator.sublabel": "თქვენი სახლის ლენტა მზადდება!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}დღ", "relative_time.hours": "{number}სთ", "relative_time.just_now": "ახლა", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "უარყოფა", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "ფორვარდი {target}-ს", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "ძებნა", - "search_popout.search_format": "დეტალური ძებნის ფორმა", - "search_popout.tips.full_text": "მარტივი ტექსტი აბრუნებს სტატუსებს რომლებიც შექმენით, აქციეთ ფავორიტად, დაბუსტეთ, ან რაშიც ასახელეთ, ასევე ემთხვევა მომხმარებლის სახელებს, დისპლეი სახელებს, და ჰეშტეგებს.", - "search_popout.tips.hashtag": "ჰეშტეგი", - "search_popout.tips.status": "სტატუსი", - "search_popout.tips.user": "მომხმარებელი", "search_results.accounts": "ხალხი", "search_results.hashtags": "ჰეშტეგები", "search_results.statuses": "ტუტები", diff --git a/app/soapbox/locales/kk.json b/app/soapbox/locales/kk.json index f0d5b1d33..2eef8353e 100644 --- a/app/soapbox/locales/kk.json +++ b/app/soapbox/locales/kk.json @@ -8,6 +8,7 @@ "account.block_domain": "Домендегі барлығын бұғатта {domain}", "account.blocked": "Бұғатталды", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Ешкімге жазылмапты.", "account.follows_you": "Сізге жазылыпты", "account.hide_reblogs": "@{name} атты қолданушының әрекеттерін жасыру", + "account.last_status": "Last active", "account.link_verified_on": "Сілтеме меншігі расталған күн {date}", "account.locked_info": "Бұл қолданушы өзі туралы мәліметтерді жасырған. Тек жазылғандар ғана көре алады.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} көшіп кетті:", "account.mute": "Үнсіз қылу @{name}", "account.muted": "Үнсіз", + "account.never_active": "Never", "account.posts": "Жазбалар", "account.posts_with_replies": "Жазбалар мен жауаптар", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Жабу", "bundle_modal_error.message": "Бұл компонентті жүктеген кезде бір қате пайда болды.", "bundle_modal_error.retry": "Қайтадан көріңіз", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Бұғатталғандар", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Жергілікті желі", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Жеке хаттар", + "column.directory": "Browse profiles", "column.domain_blocks": "Жасырылған домендер", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Жазылу сұранымдары", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Басты бет", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Тізімдер", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Үнсіз қолданушылар", "column.notifications": "Ескертпелер", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Жаһандық желі", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Артқа", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Баптауларды жасыр", "column_header.show_settings": "Баптауларды көрсет", "community.column_settings.media_only": "Тек медиа", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Сауалнама мерзімі", "compose_form.poll.option_placeholder": "Жауап {number}", "compose_form.poll.remove_option": "Бұл жауапты өшір", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Түрт", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Бұғаттау", "confirmations.block.message": "{name} атты қолданушыны бұғаттайтыныңызға сенімдісіз бе?", "confirmations.delete.confirm": "Өшіру", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Бұл жазбаны өшіресіз бе?", "confirmations.delete_list.confirm": "Өшіру", "confirmations.delete_list.message": "Бұл тізімді жоясыз ба шынымен?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Авторизация", "follow_request.reject": "Қабылдамау", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} - ашық кодты құрылым. Түзету енгізу немесе ұсыныстарды GitLab арқылы жасаңыз {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Алдыңғы", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Тізімге қосу", "lists.account.remove": "Тізімнен шығару", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Бұл қолданушы ескертпелерін жасырамыз ба?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Жаңа жазба бастау", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Жабық домендер", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Таңдаулылар", "navigation_bar.filters": "Үнсіз сөздер", "navigation_bar.follow_requests": "Жазылуға сұранғандар", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Сервер туралы", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Ыстық пернелер", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Шығу", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Үнсіз қолданушылар", "navigation_bar.pins": "Жабыстырылғандар", "navigation_bar.preferences": "Басымдықтар", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Қауіпсіздік", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Жаңарту", "poll.total_votes": "{count, plural, one {# дауыс} other {# дауыс}}", "poll.vote": "Дауыс беру", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Сауалнама қосу", "poll_button.remove_poll": "Сауалнаманы өшіру", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Жүктеу…", "regeneration_indicator.sublabel": "Жергілікті желі құрылуда!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}күн", "relative_time.hours": "{number}сағ", "relative_time.just_now": "жаңа", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Қайтып алу", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Жіберу {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Іздеу", - "search_popout.search_format": "Кеңейтілген іздеу форматы", - "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, bоosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "хэштег", - "search_popout.tips.status": "статус", - "search_popout.tips.user": "қолданушы", "search_results.accounts": "Адамдар", "search_results.hashtags": "Хэштегтер", "search_results.statuses": "Жазбалар", diff --git a/app/soapbox/locales/ko.json b/app/soapbox/locales/ko.json index 54ed206ab..afeeec7fb 100644 --- a/app/soapbox/locales/ko.json +++ b/app/soapbox/locales/ko.json @@ -8,6 +8,7 @@ "account.block_domain": "{domain} 전체를 숨김", "account.blocked": "차단 됨", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "이 유저는 아직 아무도 팔로우 하고 있지 않습니다.", "account.follows_you": "날 팔로우합니다", "account.hide_reblogs": "@{name}의 부스트를 숨기기", + "account.last_status": "Last active", "account.link_verified_on": "{date}에 이 링크의 소유권이 확인 됨", "account.locked_info": "이 계정의 프라이버시 설정은 잠금으로 설정되어 있습니다. 계정 소유자가 수동으로 팔로어를 승인합니다.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name}는 계정을 이동했습니다:", "account.mute": "@{name} 뮤트", "account.muted": "뮤트 됨", + "account.never_active": "Never", "account.posts": "툿", "account.posts_with_replies": "툿과 답장", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "닫기", "bundle_modal_error.message": "컴포넌트를 불러오는 과정에서 문제가 발생했습니다.", "bundle_modal_error.retry": "다시 시도", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "차단 중인 사용자", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "로컬 타임라인", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "다이렉트 메시지", + "column.directory": "Browse profiles", "column.domain_blocks": "숨겨진 도메인", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "팔로우 요청", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "홈", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "리스트", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "뮤트 중인 사용자", "column.notifications": "알림", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "연합 타임라인", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "돌아가기", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "설정 숨기기", "column_header.show_settings": "설정 보이기", "community.column_settings.media_only": "미디어만", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "투표 기간", "compose_form.poll.option_placeholder": "{number}번 항목", "compose_form.poll.remove_option": "이 항목 삭제", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "툿", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "차단하고 신고하기", "confirmations.block.confirm": "차단", "confirmations.block.message": "정말로 {name}를 차단하시겠습니까?", "confirmations.delete.confirm": "삭제", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "정말로 삭제하시겠습니까?", "confirmations.delete_list.confirm": "삭제", "confirmations.delete_list.message": "정말로 이 리스트를 삭제하시겠습니까?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "허가", "follow_request.reject": "거부", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name}은 오픈 소스 소프트웨어입니다. 누구나 GitLab({code_link} (v{code_version}))에서 개발에 참여하거나, 문제를 보고할 수 있습니다.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "이전", "lightbox.view_context": "게시물 보기", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "리스트에 추가", "lists.account.remove": "리스트에서 제거", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "이 사용자로부터의 알림을 뮤트하시겠습니까?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "새 툿 작성", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "숨겨진 도메인", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "즐겨찾기", "navigation_bar.filters": "뮤트", "navigation_bar.follow_requests": "팔로우 요청", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "이 서버에 대해서", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "단축키", "navigation_bar.lists": "Lists", "navigation_bar.logout": "로그아웃", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "뮤트 중인 사용자", "navigation_bar.pins": "고정된 툿", "navigation_bar.preferences": "사용자 설정", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "보안", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "새로고침", "poll.total_votes": "{count} 표", "poll.vote": "투표", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "투표 추가", "poll_button.remove_poll": "투표 삭제", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "불러오는 중…", "regeneration_indicator.sublabel": "당신의 홈 피드가 준비되는 중입니다!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}일 전", "relative_time.hours": "{number}시간 전", "relative_time.just_now": "방금", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "취소", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "{target}에 포워드 됨", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "검색", - "search_popout.search_format": "고급 검색 방법", - "search_popout.tips.full_text": "단순한 텍스트 검색은 당신이 작성했거나, 관심글로 지정했거나, 부스트했거나, 멘션을 받은 게시글, 그리고 유저네임, 디스플레이네임, 해시태그를 반환합니다.", - "search_popout.tips.hashtag": "해시태그", - "search_popout.tips.status": "툿", - "search_popout.tips.user": "유저", "search_results.accounts": "사람", "search_results.hashtags": "해시태그", "search_results.statuses": "툿", diff --git a/app/soapbox/locales/lt.json b/app/soapbox/locales/lt.json index a8cd841d2..93e7fd5b7 100644 --- a/app/soapbox/locales/lt.json +++ b/app/soapbox/locales/lt.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/lv.json b/app/soapbox/locales/lv.json index 337950ba6..7a9f39d78 100644 --- a/app/soapbox/locales/lv.json +++ b/app/soapbox/locales/lv.json @@ -8,6 +8,7 @@ "account.block_domain": "Slēpt visu no {domain}", "account.blocked": "Bloķēts", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.follows_you": "Seko tev", "account.hide_reblogs": "Paslēpt paceltos ierakstus no lietotāja @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Šīs saites piederība ir pārbaudīta {date}", "account.locked_info": "Šī konta privātuma status ir iestatīts slēgts. Īpašnieks izskatīs un izvēlēsies kas viņam drīkst sekot.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} ir pārvācies uz:", "account.mute": "Apklusināt @{name}", "account.muted": "Apklusināts", + "account.never_active": "Never", "account.posts": "Ieraksti", "account.posts_with_replies": "Ieraksti un atbildes", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Aizvērt", "bundle_modal_error.message": "Kaut kas nogāja greizi ielādējot šo komponenti.", "bundle_modal_error.retry": "Mēģini vēlreiz", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Bloķētie lietotāji", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokālā laika līnija", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Privātās ziņas", + "column.directory": "Browse profiles", "column.domain_blocks": "Paslēptie domēni", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Sekotāju pieprasījumi", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Sākums", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Saraksti", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Apklusinātie lietotāji", "column.notifications": "Paziņojumi", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federatīvā laika līnija", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Atpakaļ", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Paslēpt iestatījumus", "column_header.show_settings": "Rādīt iestatījumus", "community.column_settings.media_only": "Tikai mēdiji", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publicēt", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bloķēt", "confirmations.block.message": "Vai tiešām vēlies bloķēt lietotāju {name}?", "confirmations.delete.confirm": "Dzēst", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Vai tiešām vēlies dzēst šo ierakstu?", "confirmations.delete_list.confirm": "Dzēst", "confirmations.delete_list.message": "Vai tiešam vēlies neatgriezeniski dzēst šo sarakstu?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizēt", "follow_request.reject": "Noraidīt", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this instance", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/messages.js b/app/soapbox/locales/messages.js index 4118776cd..feaf780a7 100644 --- a/app/soapbox/locales/messages.js +++ b/app/soapbox/locales/messages.js @@ -12,6 +12,7 @@ export default { 'de': () => import(/* webpackChunkName: "locale_de" */'./de.json'), 'el': () => import(/* webpackChunkName: "locale_el" */'./el.json'), 'en': () => import(/* webpackChunkName: "locale_en" */'./en.json'), + 'en-Shaw': () => import(/* webpackChunkName: "locale_en-Shaw" */'./en-Shaw.json'), 'eo': () => import(/* webpackChunkName: "locale_eo" */'./eo.json'), 'es-AR': () => import(/* webpackChunkName: "locale_es-AR" */'./es-AR.json'), 'es': () => import(/* webpackChunkName: "locale_es" */'./es.json'), diff --git a/app/soapbox/locales/mk.json b/app/soapbox/locales/mk.json index 3f5c1fb57..ebebc91fc 100644 --- a/app/soapbox/locales/mk.json +++ b/app/soapbox/locales/mk.json @@ -8,6 +8,7 @@ "account.block_domain": "Сокријај се од {domain}", "account.blocked": "Блокиран", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Корисникот не следи никој сеуште.", "account.follows_you": "Те следи тебе", "account.hide_reblogs": "Сокриј буст од @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Сопстевноста на овај линк беше проверен на {date}", "account.locked_info": "Статусот на приватност на овај корисник е сетиран како заклучен. Корисникот одлучува кој можи да го следи него.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} се пресели во:", "account.mute": "Зачути го @{name}", "account.muted": "Зачутено", + "account.never_active": "Never", "account.posts": "Тутови", "account.posts_with_replies": "Тутови и реплики", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Затвори", "bundle_modal_error.message": "Настана грешка при прикажувањето на оваа веб-страница.", "bundle_modal_error.retry": "Обидете се повторно", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Блокирани корисници", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Директна порака", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Дома", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Листа", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Известувања", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Назад", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Блокирај", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/ms.json b/app/soapbox/locales/ms.json index 58e751e16..489f6500f 100644 --- a/app/soapbox/locales/ms.json +++ b/app/soapbox/locales/ms.json @@ -8,6 +8,7 @@ "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Follows you", "account.hide_reblogs": "Hide reposts from @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} has moved to:", "account.mute": "Mute @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Posts and replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Close", "bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.retry": "Try again", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blocked users", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local timeline", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Follow requests", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lists", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Muted users", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federated timeline", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Back", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Hide settings", "column_header.show_settings": "Show settings", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,15 +282,18 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "Are you sure you want to block {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Are you sure you want to delete this post?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.", "confirmations.mute.confirm": "Mute", "confirmations.mute.message": "Are you sure you want to mute {name}?", "confirmations.redraft.confirm": "Delete & redraft", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Authorize", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Previous", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Add to list", "lists.account.remove": "Remove from list", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this instance", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Muted users", "navigation_bar.pins": "Pinned posts", "navigation_bar.preferences": "Preferences", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/nl.json b/app/soapbox/locales/nl.json index bc11e542b..56135f986 100644 --- a/app/soapbox/locales/nl.json +++ b/app/soapbox/locales/nl.json @@ -8,6 +8,7 @@ "account.block_domain": "Verberg alles van {domain}", "account.blocked": "Geblokkeerd", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Deze gebruiker volgt nog niemand.", "account.follows_you": "Volgt jou", "account.hide_reblogs": "Verberg reposts van @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Eigendom van deze link is gecontroleerd op {date}", "account.locked_info": "De privacystatus van dit account is op besloten gezet. De eigenaar bepaalt handmatig wie hen kan volgen.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} is verhuisd naar:", "account.mute": "Negeer @{name}", "account.muted": "Genegeerd", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots en reacties", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Sluiten", "bundle_modal_error.message": "Tijdens het laden van dit onderdeel is er iets fout gegaan.", "bundle_modal_error.retry": "Opnieuw proberen", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Geblokkeerde gebruikers", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokale tijdlijn", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Directe berichten", + "column.directory": "Browse profiles", "column.domain_blocks": "Genegeerde servers", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Volgverzoeken", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Start", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lijsten", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Genegeerde gebruikers", "column.notifications": "Meldingen", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Globale tijdlijn", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Terug", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Instellingen verbergen", "column_header.show_settings": "Instellingen tonen", "community.column_settings.media_only": "Alleen media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duur van de poll", "compose_form.poll.option_placeholder": "Keuze {number}", "compose_form.poll.remove_option": "Deze keuze verwijderen", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokkeren en rapporteren", "confirmations.block.confirm": "Blokkeren", "confirmations.block.message": "Weet je het zeker dat je {name} wilt blokkeren?", "confirmations.delete.confirm": "Verwijderen", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Weet je het zeker dat je deze toot wilt verwijderen?", "confirmations.delete_list.confirm": "Verwijderen", "confirmations.delete_list.message": "Weet je zeker dat je deze lijst definitief wilt verwijderen?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Goedkeuren", "follow_request.reject": "Afkeuren", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} is vrije software. Je kunt bijdragen of problemen melden op GitLab via {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Vorige", "lightbox.view_context": "Context tonen", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Aan lijst toevoegen", "lists.account.remove": "Uit lijst verwijderen", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Verberg meldingen van deze persoon?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Nieuw toot schrijven", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Genegeerde servers", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorieten", "navigation_bar.filters": "Filters", "navigation_bar.follow_requests": "Volgverzoeken", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Over deze server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Sneltoetsen", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Uitloggen", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Genegeerde gebruikers", "navigation_bar.pins": "Vastgezette toots", "navigation_bar.preferences": "Instellingen", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Beveiliging", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Vernieuwen", "poll.total_votes": "{count, plural, one {# stem} other {# stemmen}}", "poll.vote": "Stemmen", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Poll toevoegen", "poll_button.remove_poll": "Poll verwijderen", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Aan het laden…", "regeneration_indicator.sublabel": "Jouw tijdlijn wordt aangemaakt!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}u", "relative_time.just_now": "nu", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Annuleren", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Doorsturen naar {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Zoeken", - "search_popout.search_format": "Geavanceerd zoeken", - "search_popout.tips.full_text": "Gebruik gewone tekst om te zoeken in jouw toots, gebooste toots, favorieten en in toots waarin jij bent vermeldt, en tevens naar gebruikersnamen, weergavenamen en hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "toot", - "search_popout.tips.user": "gebruiker", "search_results.accounts": "Gebruikers", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/nn.json b/app/soapbox/locales/nn.json index 3d1f1095b..12b2e64ae 100644 --- a/app/soapbox/locales/nn.json +++ b/app/soapbox/locales/nn.json @@ -8,6 +8,7 @@ "account.block_domain": "Gøyme alt innhald for domenet {domain}", "account.blocked": "Blokkert", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Denne brukaren foljer ikkje nokon ennå.", "account.follows_you": "Føljar deg", "account.hide_reblogs": "Gøym fremhevingar for @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Eigerskap for denne linken er sist sjekket den {date}", "account.locked_info": "Brukarens privat-status er satt til lukka. Eigaren må manuelt døme kvem som kan følje honom.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} har flytta til:", "account.mute": "Målbind @{name}", "account.muted": "Målbindt", + "account.never_active": "Never", "account.posts": "Tutar", "account.posts_with_replies": "Tutar og svar", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Lukk", "bundle_modal_error.message": "Noko gikk gale mens komponent var i ferd med å bli nedlasta.", "bundle_modal_error.retry": "Prøv igjen", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokka brukare", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokal samtid", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direkte meldingar", + "column.directory": "Browse profiles", "column.domain_blocks": "Gøymte domener", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Føljarførespurnad", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Heim", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lister", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Målbindte brukare", "column.notifications": "Varslingar", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federert samtid", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tilbake", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Skjul innstillingar", "column_header.show_settings": "Vis innstillingar", "community.column_settings.media_only": "Kun medie", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Varigheit for spørring", "compose_form.poll.option_placeholder": "Val {number}", "compose_form.poll.remove_option": "Ta burt dette valet", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokk & rapportér", "confirmations.block.confirm": "Blokkér", "confirmations.block.message": "Er du sikker på at du vill blokke {name}?", "confirmations.delete.confirm": "Slett", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Er du sikker på at du vill slette denne statusen?", "confirmations.delete_list.confirm": "Slett", "confirmations.delete_list.message": "Er du sikker på at du vill slette denne listen for alltid?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autoriser", "follow_request.reject": "Reject", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} har åpen kilde kode. Du kan hjelpe til med problemar på GitLab gjennom {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Forrige", "lightbox.view_context": "Sjå kontekst", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Legg til i liste", "lists.account.remove": "Ta burt fra liste", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Hide notifications from this user?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorites", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Follow requests", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "About this server", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hotkeys", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logg ut", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Dempa brukare", "navigation_bar.pins": "Festa tuter", "navigation_bar.preferences": "Preferanser", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Sikkerheit", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "now", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancel", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Search", - "search_popout.search_format": "Advanced search format", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/no.json b/app/soapbox/locales/no.json index 55aad435f..e3272cc76 100644 --- a/app/soapbox/locales/no.json +++ b/app/soapbox/locales/no.json @@ -8,6 +8,7 @@ "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Følger deg", "account.hide_reblogs": "Skjul fremhevinger fra @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} har flyttet til:", "account.mute": "Demp @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Innlegg", "account.posts_with_replies": "Toots with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Lukk", "bundle_modal_error.message": "Noe gikk galt da denne komponenten lastet.", "bundle_modal_error.retry": "Prøv igjen", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokkerte brukere", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokal tidslinje", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Følgeforespørsler", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hjem", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lister", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Dempede brukere", "column.notifications": "Varsler", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Felles tidslinje", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tilbake", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Gjem innstillinger", "column_header.show_settings": "Vis innstillinger", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokkèr", "confirmations.block.message": "Er du sikker på at du vil blokkere {name}?", "confirmations.delete.confirm": "Slett", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Er du sikker på at du vil slette denne statusen?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "Er du sikker på at du vil slette denne listen permanent?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorisér", "follow_request.reject": "Avvis", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} er fri programvare. Du kan bidra eller rapportere problemer på GitLab på {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Forrige", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Legg til i listen", "lists.account.remove": "Fjern fra listen", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Skjul varslinger fra denne brukeren?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritter", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Følgeforespørsler", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Utvidet informasjon", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Tastatursnarveier", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logg ut", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Dempede brukere", "navigation_bar.pins": "Festa tuter", "navigation_bar.preferences": "Preferanser", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Laster…", "regeneration_indicator.sublabel": "Dine startside forberedes!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "nå", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Avbryt", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Søk", - "search_popout.search_format": "Avansert søkeformat", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "emneknagg", - "search_popout.tips.status": "post", - "search_popout.tips.user": "bruker", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/oc.json b/app/soapbox/locales/oc.json index c9720677d..cd11328a9 100644 --- a/app/soapbox/locales/oc.json +++ b/app/soapbox/locales/oc.json @@ -8,6 +8,7 @@ "account.block_domain": "Tot amagar del domeni {domain}", "account.blocked": "Blocat", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Aqueste utilizaire sèc pas degun pel moment.", "account.follows_you": "Vos sèc", "account.hide_reblogs": "Rescondre los partatges de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "La proprietat d’aqueste ligam foguèt verificada lo {date}", "account.locked_info": "L’estatut de privacitat del compte es configurat sus clavat. Lo proprietari causís qual pòt sègre son compte.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} a mudat los catons a :", "account.mute": "Rescondre @{name}", "account.muted": "Mes en silenci", + "account.never_active": "Never", "account.posts": "Tuts", "account.posts_with_replies": "Tuts e responsas", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Tampar", "bundle_modal_error.message": "Quicòm a fach mèuca pendent lo cargament d’aqueste compausant.", "bundle_modal_error.retry": "Tornar ensajar", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Personas blocadas", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Flux public local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Messatges dirèctes", + "column.directory": "Browse profiles", "column.domain_blocks": "Domenis resconduts", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Demandas d’abonament", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Acuèlh", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Personas rescondudas", "column.notifications": "Notificacions", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Flux public global", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tornar", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Amagar los paramètres", "column_header.show_settings": "Mostrar los paramètres", "community.column_settings.media_only": "Solament los mèdias", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Durada del sondatge", "compose_form.poll.option_placeholder": "Opcion {number}", "compose_form.poll.remove_option": "Levar aquesta opcion", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish} !", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blocar e senhalar", "confirmations.block.confirm": "Blocar", "confirmations.block.message": "Volètz vertadièrament blocar {name} ?", "confirmations.delete.confirm": "Escafar", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Volètz vertadièrament escafar l’estatut ?", "confirmations.delete_list.confirm": "Suprimir", "confirmations.delete_list.message": "Volètz vertadièrament suprimir aquesta lista per totjorn ?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Acceptar", "follow_request.reject": "Regetar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {code_link} (v{code_version}) sus GitLab.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Precedent", "lightbox.view_context": "Veire lo contèxt", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Ajustar a la lista", "lists.account.remove": "Levar de la lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Escriure un nòu tut", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domenis resconduts", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorits", "navigation_bar.filters": "Mots ignorats", "navigation_bar.follow_requests": "Demandas d’abonament", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Tocant aqueste servidor", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Acorchis clavièr", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Desconnexion", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Personas rescondudas", "navigation_bar.pins": "Tuts penjats", "navigation_bar.preferences": "Preferéncias", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Seguretat", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Actualizar", "poll.total_votes": "{count, plural, one {# vòte} other {# vòtes}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Ajustar un sondatge", "poll_button.remove_poll": "Levar lo sondatge", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Cargament…", "regeneration_indicator.sublabel": "Sèm a preparar vòstre flux d’acuèlh !", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "fa {number}d", "relative_time.hours": "fa {number}h", "relative_time.just_now": "ara", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Anullar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Far sègre a {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Recercar", - "search_popout.search_format": "Format recèrca avançada", - "search_popout.tips.full_text": "Un tèxte simple que tòrna los estatuts qu’avètz escriches, mes en favorits, partejats, o ont sètz mencionat, e tanben los noms d’utilizaires, escais-noms e etiquetas que correspondonas.", - "search_popout.tips.hashtag": "etiqueta", - "search_popout.tips.status": "estatut", - "search_popout.tips.user": "utilizaire", "search_results.accounts": "Gents", "search_results.hashtags": "Etiquetas", "search_results.statuses": "Tuts", diff --git a/app/soapbox/locales/pl.json b/app/soapbox/locales/pl.json index 3a2325769..470bac41b 100644 --- a/app/soapbox/locales/pl.json +++ b/app/soapbox/locales/pl.json @@ -4,12 +4,12 @@ "accordion.expand": "Rozwiń", "account.add_or_remove_from_list": "Dodaj lub usuń z list", "account.badges.bot": "Bot", + "account.birthday": "Urodzony(-a) {date}", + "account.birthday_today": "Ma dziś urodziny!", "account.block": "Blokuj @{name}", "account.block_domain": "Blokuj wszystko z {domain}", "account.blocked": "Zablokowany(-a)", "account.chat": "Napisz do @{name}", - "account.column_settings.description": "Te ustawienia stosowane są do osi czasu wszystkich kont.", - "account.column_settings.title": "Ustawienia osi czasu konta", "account.deactivated": "Dezaktywowany(-a)", "account.deactivated_description": "To konto zostało zdezaktywowane.", "account.direct": "Wyślij wiadomość bezpośrednią do @{name}", @@ -23,6 +23,7 @@ "account.follows.empty": "Ten użytkownik nie śledzi jeszcze nikogo.", "account.follows_you": "Śledzi Cię", "account.hide_reblogs": "Ukryj podbicia od @{name}", + "account.last_status": "Ostatnia aktywność", "account.link_verified_on": "Własność tego odnośnika została potwierdzona {date}", "account.locked_info": "To konto jest prywatne. Właściciel ręcznie wybiera kto może go śledzić.", "account.login": "Zaloguj się", @@ -32,6 +33,7 @@ "account.moved_to": "{name} przeniósł(-osła) się do:", "account.mute": "Wycisz @{name}", "account.muted": "Wyciszony", + "account.never_active": "Nigdy", "account.posts": "Wpisy", "account.posts_with_replies": "Wpisy i odpowiedzi", "account.profile": "Profil", @@ -43,8 +45,8 @@ "account.share": "Udostępnij profil @{name}", "account.show_reblogs": "Pokazuj podbicia od @{name}", "account.subscribe": "Subskrybuj wpisy @{name}", - "account.subscribed": "Subscribed", - "account.unblock": "Zasubskrybowano", + "account.subscribed": "Subskrybujesz", + "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenę {domain}", "account.unendorse": "Przestań polecać", "account.unfollow": "Przestań śledzić", @@ -52,7 +54,6 @@ "account.unsubscribe": "Przestań subskrybować wpisy @{name}", "account_gallery.none": "Brak zawartości multimedialnej do wyświetlenia.", "account_search.placeholder": "Szukaj konta", - "account_timeline.column_settings.show_pinned": "Pokazuj przypięte wpisy", "admin.awaiting_approval.approved_message": "Przyjęto {acct}!", "admin.awaiting_approval.empty_message": "Nikt nie oczekuje przyjęcia. Gdy zarejestruje się nowy użytkownik, możesz zatwierdzić go tutaj.", "admin.awaiting_approval.rejected_message": "Odrzucono {acct}!", @@ -97,10 +98,14 @@ "admin.users.actions.promote_to_admin_message": "Mianowano @{acct} administratorem", "admin.users.actions.promote_to_moderator": "Mianuj @{name} moderatorem", "admin.users.actions.promote_to_moderator_message": "Mianowano @{acct} moderatorem", + "admin.users.actions.suggest_user": "Polecaj @{name}", + "admin.users.actions.unsuggest_user": "Przestań polecać @{name}", "admin.users.actions.unverify_user": "Cofnij weryfikację @{name}", "admin.users.actions.verify_user": "Weryfikuj @{name}", "admin.users.user_deactivated_message": "Zdezaktywowano @{acct}", "admin.users.user_deleted_message": "Usunięto @{acct}", + "admin.users.user_suggested_message": "Zaczęto polecać @{acct}", + "admin.users.user_unsuggested_message": "Przestano polecać @{acct}", "admin.users.user_unverified_message": "Cofnięto weryfikację @{acct}", "admin.users.user_verified_message": "Zweryfikowano @{acct}", "admin_nav.awaiting_approval": "Oczekujące zgłoszenia", @@ -117,9 +122,20 @@ "aliases.search": "Szukaj swojego starego konta", "aliases.success.add": "Pomyślnie utworzono alias konta", "aliases.success.remove": "Pomyślnie usunięto alias konta", + "app_create.name_label": "Nazwa aplikacji", + "app_create.name_placeholder": "np. „Soapbox”", + "app_create.redirect_uri_label": "Adresy przekeirowania", + "app_create.restart": "Utwórz kolejną", + "app_create.results.app_label": "Aplikacja", + "app_create.results.explanation_text": "Utworzyłeś(-aś) nową aplikację i token! Skopiuj gdzieś te dane, nie zobaczysz ich po opuszczeniu tej strony.", + "app_create.results.explanation_title": "Pomyślnie utworzono aplikację", + "app_create.results.token_label": "Token OAuth", + "app_create.scopes_label": "Zakresy", + "app_create.scopes_placeholder": "np. „read write follow”", + "app_create.submit": "Utwórz aplikację", + "app_create.website_label": "Strona", "auth.invalid_credentials": "Nieprawidłowa nazwa użytkownika lub hasło", "auth.logged_out": "Wylogowano.", - "autosuggest_account_input.default_placeholder": "Szukaj konta", "backups.actions.create": "Utwórz kopię zapasową", "backups.empty_message": "Nie znaleziono kopii zapasowych. {action}", "backups.empty_message.action": "Chcesz utworzyć?", @@ -138,6 +154,8 @@ "chats.actions.delete": "Usuń wiadomość", "chats.actions.more": "Więcej", "chats.actions.report": "Zgłoś użytkownika", + "chats.attachment": "Załącznik", + "chats.attachment_image": "Zdjęcie", "chats.audio_toggle_off": "Wyłączono dźwięk powiadomień", "chats.audio_toggle_on": "Włączono dźwięk powiadomień", "chats.dividers.today": "Dzisiaj", @@ -147,22 +165,28 @@ "column.admin.moderation_log": "Dziennik moderacyjny", "column.admin.reports": "Zgłoszenia", "column.admin.reports.menu.moderation_log": "Dziennik moderacji", + "column.admin.users": "Użytkownicy", "column.aliases": "Aliasy kont", "column.aliases.create_error": "Błąd tworzenia aliasu", "column.aliases.delete": "Usuń", "column.aliases.delete_error": "Błąd usuwania aliasu", "column.aliases.subheading_add_new": "Dodaj nowy alias", "column.aliases.subheading_aliases": "Istniejące aliasy", + "column.app_create": "Utwórz aplikację", "column.backups": "Kopie zapasowe", + "column.birthdays": "Urodziny", "column.blocks": "Zablokowani użytkownicy", - "column.bookmarks": "Załadki", + "column.bookmarks": "Zakładki", "column.chats": "Rozmowy", "column.community": "Lokalna oś czasu", "column.crypto_donate": "Przekaż kryptowalutę", + "column.developers": "Programiści", "column.direct": "Wiadomości bezpośrednie", + "column.directory": "Przeglądaj profile", "column.domain_blocks": "Ukryte domeny", "column.edit_profile": "Edytuj profil", "column.export_data": "Eksportuj dane", + "column.favourited_statuses": "Polubione wpisy", "column.favourites": "Polubienia", "column.federation_restrictions": "Ograniczenia federacji", "column.filters": "Wyciszone słowa", @@ -184,11 +208,14 @@ "column.filters.whole_word_header": "Całe słowo", "column.filters.whole_word_hint": "Jeżeli słowo kluczowe lub fraza składa się tylko ze znaków alfanumerycznych, zostanie to zastosowane tylko gdy pasuje do całego słowa", "column.follow_requests": "Prośby o śledzenie", + "column.followers": "Śledzący", + "column.following": "Śledzeni", "column.groups": "Grupy", "column.home": "Strona główna", "column.import_data": "Importuj dane", "column.info": "Informacje o serwerze", "column.lists": "Listy", + "column.mentions": "W odpowiedzi do", "column.mfa": "Uwierzytelnianie wieloetapowe", "column.mfa_cancel": "Anuluj", "column.mfa_confirm_button": "Potwierdź", @@ -196,16 +223,21 @@ "column.mfa_setup": "Przejdź do konfiguracji", "column.mutes": "Wyciszeni użytkownicy", "column.notifications": "Powiadomienia", + "column.pins": "Przypięte wpisy", "column.preferences": "Preferencje", + "column.profile_directory": "Katalog profilów", "column.public": "Globalna oś czasu", + "column.reactions": "Reakcje", "column.reblogs": "Podbicia", "column.remote": "Sfederowana oś czasu", "column.scheduled_statuses": "Zaplanowane wpisy", "column.search": "Szukaj", "column.security": "Bezpieczeństwo", + "column.settings_store": "Settings store", "column.soapbox_config": "Konfiguracja Soapbox", "column_back_button.label": "Wróć", - "column_header.hide_settings": "Ukryj ustawienia", + "column_forbidden.body": "Nie masz uprawnień, aby odwiedzić tę stronę.", + "column_forbidden.title": "Niedozwolone", "column_header.show_settings": "Pokaż ustawienia", "community.column_settings.media_only": "Tylko zawartość multimedialna", "community.column_settings.title": "Ustawienia lokalnej osi czasu", @@ -226,7 +258,6 @@ "compose_form.poll.remove_option": "Usuń tę opcję", "compose_form.poll.switch_to_multiple": "Przełącz ankietę na pozwalającą wybrać wiele opcji", "compose_form.poll.switch_to_single": "Przełącz ankietę na pozwalającą wybrać jedną opcję", - "compose_form.poll.type.hint": "Naciśnij aby przełączyć rodzaj ankiety. Przycisk radio (domyślny) to ankieta jednokrotnego wyboru. Pole wyboru – wielokrotnego.", "compose_form.publish": "Wyślij", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Zaplanuj", @@ -240,34 +271,54 @@ "compose_form.spoiler_placeholder": "Wprowadź swoje ostrzeżenie o zawartości", "confirmation_modal.cancel": "Anuluj", "confirmations.admin.deactivate_user.confirm": "Dezaktywuj @{name}", + "confirmations.admin.deactivate_user.heading": "Dezaktywuj @{acct}", "confirmations.admin.deactivate_user.message": "Zamierzasz zdezaktywować @{acct}. Dezaktywacja konta może zostać cofnięta.", "confirmations.admin.delete_local_user.checkbox": "Wiem, że właśnie usuwam lokalnego użytkownika.", "confirmations.admin.delete_status.confirm": "Usuń wpis", + "confirmations.admin.delete_status.heading": "Usuń wpis", "confirmations.admin.delete_status.message": "Zamierzasz usunąć wpis użytkownika @{acct}. To działanie nie może zostać cofnięte.", "confirmations.admin.delete_user.confirm": "Usuń @{name}", + "confirmations.admin.delete_user.heading": "Usuń @{acct}", "confirmations.admin.delete_user.message": "Zamierzasz usunąć @{acct}. TO DZIAŁANIE NIE MOŻE ZOSTAĆ COFNIĘTE.", "confirmations.admin.mark_status_not_sensitive.confirm": "Oznacz wpis jako niewrażliwy", + "confirmations.admin.mark_status_not_sensitive.heading": "Oznacz wpis jako niewrażliwy.", "confirmations.admin.mark_status_not_sensitive.message": "Zamierzasz oznaczyć wpis {acct} jako niewrażliwy.", "confirmations.admin.mark_status_sensitive.confirm": "Oznacz wpis jako wrażliwy", + "confirmations.admin.mark_status_sensitive.heading": "Oznacz wpis jako wrażliwy", "confirmations.admin.mark_status_sensitive.message": "Zamierzasz oznaczyć wpis {acct} jako wrażliwy.", + "confirmations.admin.reject_user.confirm": "Odrzuć @{name}", + "confirmations.admin.reject_user.heading": "Odrzuć @{acct}", + "confirmations.admin.reject_user.message": "Zamierzasz odrzucić prośbę o rejestrację @{acct}. To działanie nie może zostać cofnięte.", "confirmations.block.block_and_report": "Zablokuj i zgłoś", "confirmations.block.confirm": "Zablokuj", + "confirmations.block.heading": "Zablokuj @{name}", "confirmations.block.message": "Czy na pewno chcesz zablokować {name}?", "confirmations.delete.confirm": "Usuń", + "confirmations.delete.heading": "Usuń wpis", "confirmations.delete.message": "Czy na pewno chcesz usunąć ten wpis?", "confirmations.delete_list.confirm": "Usuń", + "confirmations.delete_list.heading": "Usuń listę", "confirmations.delete_list.message": "Czy na pewno chcesz bezpowrotnie usunąć tą listę?", "confirmations.domain_block.confirm": "Ukryj wszysyko z domeny", + "confirmations.domain_block.heading": "Zablokuj {domain}", "confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.", "confirmations.mute.confirm": "Wycisz", + "confirmations.mute.heading": "Wycisz @{name}", "confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?", "confirmations.redraft.confirm": "Usuń i przeredaguj", + "confirmations.redraft.heading": "Usuń i przeredaguj", "confirmations.redraft.message": "Czy na pewno chcesz usunąć i przeredagować ten wpis? Polubienia i podbicia zostaną utracone, a odpowiedzi do oryginalnego wpisu zostaną osierocone.", "confirmations.register.needs_approval": "Twoje konto musi zostać ręcznie zatwierdzone przez administratora. Zachowaj cierpliwość, a my sprawdzimy szczegóły Twojej rejestracji.", + "confirmations.register.needs_approval.header": "Wymagane zatwierdzenie", "confirmations.register.needs_confirmation": "Sprawdź swoją skrzynkę na {email}, aby znaleźć instrukcje potwierdzania. Musisz zweryfikować swój adres e-mail, aby kontynuować.", + "confirmations.register.needs_confirmation.header": "Wymagane potwierdzenie", "confirmations.reply.confirm": "Odpowiedz", "confirmations.reply.message": "W ten sposób utracisz wpis który obecnie tworzysz. Czy na pewno chcesz to zrobić?", + "confirmations.scheduled_status_delete.confirm": "Anuluj", + "confirmations.scheduled_status_delete.heading": "Anuluj zaplanowany wpis", + "confirmations.scheduled_status_delete.message": "Czy na pewno chcesz anulować ten zaplanowany wpis?", "confirmations.unfollow.confirm": "Przestań śledzić", + "confirmations.unfollow.heading": "Przestań śledzić {name}", "confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?", "crypto_donate.explanation_box.message": "{siteTitle} przyjmuje darowizny w kryptowalutach. Możesz wysłać darowiznę na jeden z poniższych adresów. Dziękujemy za Wasze wsparcie!", "crypto_donate.explanation_box.title": "Przekaż darowiznę w kryptowalutach", @@ -275,7 +326,27 @@ "crypto_donate_panel.heading": "Przekaż kryptowalutę", "crypto_donate_panel.intro.message": "{siteTitle} przyjmuje darowizny w kryptowalutach, aby utrzymać naszą usługę. Dziękujemy za Wasze wsparcie!", "datepicker.hint": "Zaplanowano publikację na…", + "datepicker.next_month": "Następny miesiąc", + "datepicker.next_year": "Następny rok", + "datepicker.previous_month": "Poprzedni miesiąc", + "datepicker.previous_year": "Poprzedni rok", + "developers.challenge.answer_label": "Odpowiedź", + "developers.challenge.answer_placeholder": "Twoja odpowiedź", + "developers.challenge.fail": "Nieprawidłowa odpowiedź", + "developers.challenge.message": "Jaki jest wynik wywołania {function}?", + "developers.challenge.submit": "Zostań programistą", + "developers.challenge.success": "Jesteś teraz programistą", + "developers.leave": "Nie jesteś już programistą", + "developers.navigation.app_create_label": "Utwórz aplikację", + "developers.navigation.intentional_error_label": "Wywołaj błąd", + "developers.navigation.leave_developers_label": "Opuść programistów", + "developers.navigation.settings_store_label": "Settings store", + "developers.settings_store.hint": "Możesz tu bezpośrednio edytować swoje ustawienia. UWAŻAJ! Edytowanie tej sekcji może uszkodzić Twoje konto, co może zostać naprawione tylko przez API.", "direct.search_placeholder": "Wyślij wiadomość do…", + "directory.federated": "Z całego znanego Fediwersum", + "directory.local": "Tylko z {domain}", + "directory.new_arrivals": "Nowi użytkownicy", + "directory.recently_active": "Ostatnio aktywni", "donate": "Przekaż darowiznę", "donate_crypto": "Przekaż kryptowalutę", "edit_federation.followers_only": "Ukryj wpisy z wyjątkiem obserwowanych", @@ -285,12 +356,15 @@ "edit_federation.save": "Zapisz", "edit_federation.success": "Zaktualizowano federację {host}", "edit_federation.unlisted": "Wymuś oznaczanie wpisów jako niewypisane", - "edit_profile.error": "Akktualizacja profilu nie powiodła się", + "edit_profile.error": "Aktualizacja profilu nie powiodła się", "edit_profile.fields.accepts_email_list_label": "Zasubskrybuj newsletter", "edit_profile.fields.avatar_label": "Awatar", "edit_profile.fields.bio_label": "Opis", "edit_profile.fields.bio_placeholder": "Powiedz nam coś o sobie.", + "edit_profile.fields.birthday_label": "Urodziny", + "edit_profile.fields.birthday_placeholder": "Twoje urodziny", "edit_profile.fields.bot_label": "To jest konto bota", + "edit_profile.fields.discoverable_label": "Pozwól na odkrywanie konta", "edit_profile.fields.display_name_label": "Nazwa wyświetlana", "edit_profile.fields.display_name_placeholder": "Nazwa", "edit_profile.fields.header_label": "Nagłówek", @@ -299,15 +373,18 @@ "edit_profile.fields.meta_fields.content_placeholder": "Treść", "edit_profile.fields.meta_fields.label_placeholder": "Podpis", "edit_profile.fields.meta_fields_label": "Metadane profilu", + "edit_profile.fields.show_birthday_label": "Pokazuj moje urodziny", "edit_profile.fields.stranger_notifications_label": "Blokuj powiadomienia od nieznajomych", "edit_profile.fields.verified_display_name": "Zweryfikowani użytkownicy nie mogą zmieniać nazwy wyświetlanej", "edit_profile.hints.accepts_email_list": "Otrzymuj wiadomości i nowości marketingowe.", - "edit_profile.hints.avatar": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 400x400px", + "edit_profile.hints.avatar": "PNG, GIF lub JPG. Zostanie zmniejszony do {size}", "edit_profile.hints.bot": "To konto podejmuje głównie zautomatyzowane działania i może nie być nadzorowane", - "edit_profile.hints.header": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 1500x500px", + "edit_profile.hints.discoverable": "Wyświetlaj konto w katalogu profilów i pozwalaj na indeksowanie przez zewnętrzne usługi", + "edit_profile.hints.header": "PNG, GIF lub JPG. Zostanie zmniejszony do {size}", "edit_profile.hints.hide_network": "To, kogo obserwujesz i kto Cię obserwuje nie będzie wyświetlane na Twoim profilu", "edit_profile.hints.locked": "Wymaga ręcznego zatwierdzania obserwacji", "edit_profile.hints.meta_fields": "Możesz mieć maksymalnie {count, plural, one {# element} few {# elemeny} many {# elementów} other {# elementy}} wyświetlane w formie tabeli na swoim profilu", + "edit_profile.hints.show_birthday": "Twoja data urodzenia będzie widoczna na Twoim profilu.", "edit_profile.hints.stranger_notifications": "Wyświetlaj tylko powiadomienia od osób, które obserwujesz", "edit_profile.meta_fields.add": "Dodaj element", "edit_profile.save": "Zapisz", @@ -344,10 +421,10 @@ "empty_column.filters": "Nie wyciszyłeś(-aś) jeszcze żadnego słowa.", "empty_column.follow_recommendations": "Wygląda na to, że nie można wygenerować dla Ciebie sugestii kont do obserwacji. Możesz spróbować użyć wyszukiwania aby odnaleźć ciekawe profile, lub przejrzeć trendujące hashtagi.", "empty_column.follow_requests": "Nie masz żadnych próśb o możliwość śledzenia. Kiedy ktoś utworzy ją, pojawi się tutaj.", - "empty_column.group": "There is nothing in this group yet. When members of this group make new posts, they will appear here.", + "empty_column.group": "Nie ma żadnych wpisów w tej grupie. Gdy członkowie tej grupy utworzą wpisy, pojawią się one tutaj.", "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy(-a)!", - "empty_column.home": "Nie śledzisz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.", - "empty_column.home.local_tab": "zakładka {site_title}", + "empty_column.home": "Nie śledzisz nikogo. Odwiedź {public}, aby znaleźć innych użytkowników.", + "empty_column.home.local_tab": "zakładkę {site_title}", "empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.", "empty_column.lists": "Nie masz żadnych list. Kiedy utworzysz jedną, pojawi się tutaj.", "empty_column.mutes": "Nie wyciszyłeś(-aś) jeszcze żadnego użytkownika.", @@ -400,8 +477,9 @@ "follow_request.authorize": "Autoryzuj", "follow_request.reject": "Odrzuć", "forms.copy": "Kopiuj", + "forms.hide_password": "Ukryj hasło", + "forms.show_password": "Pokaż hasło", "getting_started.open_source_notice": "{code_name} jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitLabie tutaj: {code_link} (v{code_version}).", - "group.detail.archived_group": "Zarchiwizowana grupa", "group.members.empty": "Ta grupa nie ma żadnych członków.", "group.removed_accounts.empty": "Ta grupa nie ma żadnych usuniętych kont.", "groups.card.join": "Dołącz", @@ -410,21 +488,13 @@ "groups.card.roles.member": "Jesteś członkiem", "groups.card.view": "Zobacz", "groups.create": "Utwórz grupę", - "groups.detail.role_admin": "Jesteś administratorem", - "groups.edit": "Edytuj", "groups.form.coverImage": "Wyślij obraz baneru (nieobowiązkowe)", "groups.form.coverImageChange": "Wybrano obraz baneru", "groups.form.create": "Utwórz grupę", "groups.form.description": "Opis", "groups.form.title": "Tytuł", "groups.form.update": "Aktualizuj grupę", - "groups.join": "Dołącz do grupy", - "groups.leave": "Opuść grupę", "groups.removed_accounts": "Usunięte konta", - "groups.sidebar-panel.item.no_recent_activity": "Brak ostatniej aktywności", - "groups.sidebar-panel.item.view": "nowe wpisy", - "groups.sidebar-panel.show_all": "Pokaż wszystkie", - "groups.sidebar-panel.title": "Grupy do których należysz", "groups.tab_admin": "Zarządzaj", "groups.tab_featured": "Wyróżnione", "groups.tab_member": "Członek", @@ -439,14 +509,10 @@ "home.column_settings.show_reblogs": "Pokazuj podbicia", "home.column_settings.show_replies": "Pokazuj odpowiedzi", "home.column_settings.title": "Ustawienia strony głównej", - "home_column.lists": "Listy", - "home_column_header.all": "Wszystkie", - "home_column_header.fediverse": "Fediwersum", - "home_column_header.home": "Strona główna", "icon_button.icons": "Ikony", "icon_button.label": "Wybierz ikonę", "icon_button.not_found": "Brak ikon!! (╯°□°)╯︵ ┻━┻", - "import_data.actions.import": "Import", + "import_data.actions.import": "Importuj", "import_data.actions.import_blocks": "Importuj blokady", "import_data.actions.import_follows": "Importuj obserwacje", "import_data.actions.import_mutes": "Importuj wyciszenia", @@ -462,19 +528,6 @@ "intervals.full.days": "{number, plural, one {# dzień} few {# dni} many {# dni} other {# dni}}", "intervals.full.hours": "{number, plural, one {# godzina} few {# godziny} many {# godzin} other {# godzin}}", "intervals.full.minutes": "{number, plural, one {# minuta} few {# minuty} many {# minut} other {# minut}}", - "introduction.federation.action": "Next", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favorite", - "introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.", - "introduction.interactions.reblog.headline": "Repost", - "introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", "keyboard_shortcuts.back": "aby cofnąć się", "keyboard_shortcuts.blocked": "aby przejść do listy zablokowanych użytkowników", "keyboard_shortcuts.boost": "aby podbić wpis", @@ -533,12 +586,15 @@ "media_gallery.toggle_visible": "Przełącz widoczność", "media_panel.empty_message": "Nie znaleziono mediów.", "media_panel.title": "Media", + "mfa.confirm.success_message": "Potwierdzono MFA", + "mfa.disable.success_message": "Wyłączono MFA", "mfa.mfa_disable_enter_password": "Wprowadź obecne hasło, aby wyłączyć uwierzytelnianie dwuetapowe:", - "mfa.mfa_setup_enter_password": "Wprowadź obecne hasło, aby potwierdzić swoją tożsamość:", + "mfa.mfa_setup.code_hint": "Wprowadź kod z aplikacji do uwierzytelniania dwuskładnikowego.", + "mfa.mfa_setup.code_placeholder": "Kod", + "mfa.mfa_setup.password_hint": "Wprowadź obecne hasło, aby potwierdzić swoją tożsamość.", + "mfa.mfa_setup.password_placeholder": "Hasło", "mfa.mfa_setup_scan_description": "Korzystając z aplikacji do uwierzytelniania dwuetapowego, zeskanuj ten kod QR lub wprowadź klucz tekstowy:", - "mfa.mfa_setup_scan_key": "Klucz:", "mfa.mfa_setup_scan_title": "Skanuj", - "mfa.mfa_setup_verify_description": "Aby aktywować uwierzytelnianie dwuetapowe, wprowadź kod ze swojej aplikacji do uwierzytelniania dwuetapowego:", "mfa.mfa_setup_verify_title": "Weryfikuj", "mfa.otp_enabled_description": "Masz włączone uwierzytelnianie dwuetapowe przez OTP.", "mfa.otp_enabled_title": "Włączono OTP", @@ -556,6 +612,7 @@ "mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?", "navigation.chats": "Czaty", "navigation.dashboard": "Administracja", + "navigation.developers": "Programiści", "navigation.direct_messages": "Wiadomości", "navigation.home": "Główna", "navigation.invites": "Zaproszenia", @@ -564,25 +621,30 @@ "navigation_bar.account_aliases": "Aliasy kont", "navigation_bar.admin_settings": "Ustawienia administracyjne", "navigation_bar.blocks": "Zablokowani użytkownicy", - "navigation_bar.bookmarks": "Zakładki", "navigation_bar.compose": "Utwórz nowy wpis", "navigation_bar.compose_direct": "Wiadomość bezpośrednia", + "navigation_bar.compose_quote": "Cytuj wpis", + "navigation_bar.compose_reply": "Odpowiedz na wpis", "navigation_bar.domain_blocks": "Ukryte domeny", "navigation_bar.export_data": "Eksportuj dane", "navigation_bar.favourites": "Ulubione", "navigation_bar.filters": "Wyciszone słowa", "navigation_bar.follow_requests": "Prośby o śledzenie", "navigation_bar.import_data": "Importuj dane", + "navigation_bar.in_reply_to": "W odpowiedzi do", "navigation_bar.info": "Szczegółowe informacje", + "navigation_bar.invites": "Zaproszenia", "navigation_bar.keyboard_shortcuts": "Skróty klawiszowe", - "navigation_bar.lists": "Lists", "navigation_bar.logout": "Wyloguj", - "navigation_bar.messages": "Messages", "navigation_bar.mutes": "Wyciszeni użytkownicy", "navigation_bar.pins": "Przypięte wpisy", "navigation_bar.preferences": "Preferencje", + "navigation_bar.profile_directory": "Katalog profilów", "navigation_bar.security": "Bezpieczeństwo", "navigation_bar.soapbox_config": "Konfiguracja Soapbox", + "notification.birthday": "{name} ma dziś urodziny", + "notification.birthday.more": "{count} {count, plural, one {znajomy} other {więcej znajomych}}", + "notification.birthday_plural": "{name} i {more} mają dziś urodziny", "notification.chat_mention": "{name} wysłał(a) Ci wiadomośść", "notification.favourite": "{name} dodał(a) Twój wpis do ulubionych", "notification.follow": "{name} zaczął(-ęła) Cię śledzić", @@ -594,7 +656,10 @@ "notification.reblog": "{name} podbił(a) Twój wpis", "notifications.clear": "Wyczyść powiadomienia", "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", + "notifications.clear_heading": "Wyczyść powiadomienia", "notifications.column_settings.alert": "Powiadomienia na pulpicie", + "notifications.column_settings.birthdays.category": "Urodziny", + "notifications.column_settings.birthdays.show": "Pokazuj przypomnienia o urodzinach", "notifications.column_settings.emoji_react": "Reakcje emoji:", "notifications.column_settings.favourite": "Dodanie do ulubionych:", "notifications.column_settings.filter_bar.advanced": "Wyświetl wszystkie kategorie", @@ -625,6 +690,7 @@ "password_reset.confirmation": "Sprawdź swoją pocztę e-mail, aby potwierdzić.", "password_reset.fields.username_placeholder": "Adres e-mail lub nazwa użytkownika", "password_reset.reset": "Resetuj hasło", + "pinned_accounts.title": "Polecani przez {name}", "pinned_statuses.none": "Brak przypięć do pokazania.", "poll.closed": "Zamknięte", "poll.refresh": "Odśwież", @@ -678,6 +744,7 @@ "profile_dropdown.add_account": "Dodaj istniejące konto", "profile_dropdown.logout": "Wyloguj @{acct}", "public.column_settings.title": "Ustawienia osi czasu Fediwersum", + "reactions.all": "Wszystkie", "regeneration_indicator.label": "Ładuję…", "regeneration_indicator.sublabel": "Twoja oś czasu jest przygotowywana!", "register_invite.lead": "Wypełnij poniższy formularz, aby utworzyć konto.", @@ -692,26 +759,45 @@ "registration.fields.password_placeholder": "Hasło", "registration.fields.username_hint": "Możesz używać tylko liter, cyfr i podkreślników.", "registration.fields.username_placeholder": "Nazwa użytkownika", - "registration.lead": "Z kontem na {instance}, możesz obserwować ludzi z dowolnego serwera w całym Fediwersum.", "registration.newsletter": "Zasubskrybuj newsletter.", + "registration.password_mismatch": "Hasła nie pasują do siebie.", "registration.reason": "Dlaczego chcesz dołączyć?", "registration.reason_hint": "To pomoże nam rozpatrzyć Twoje zgłoszenie", "registration.sign_up": "Zarejestruj się", "registration.tos": "Zasady użytkowania", + "registration.username_unavailable": "Nazwa użytkownika jest już zajęta.", "relative_time.days": "{number} dni", "relative_time.hours": "{number} godz.", "relative_time.just_now": "teraz", "relative_time.minutes": "{number} min.", "relative_time.seconds": "{number} s.", "remote_instance.edit_federation": "Edytuj federację", - "remote_instance.federation_panel.heading": "Federation Restrictions", + "remote_instance.federation_panel.heading": "Ograniczenia federacji", "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} nie nakłada ograniczeń na {host}.", "remote_instance.federation_panel.restricted_message": "{siteTitle} blokuje wszystkie aktywności z {host}.", "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} nakłada pewne ograniczenia na {host}.", - "remote_instance.pin_host": "Przypnij {instance}", - "remote_instance.unpin_host": "Odepnij {instance}", + "remote_instance.pin_host": "Przypnij {host}", + "remote_instance.unpin_host": "Odepnij {host}", + "remote_interaction.account_placeholder": "Wprowadź nazwę@domenę użytkownika, z którego chcesz wykonać działanie", + "remote_interaction.divider": "lub", + "remote_interaction.favourite": "Przejdź do polubienia", + "remote_interaction.favourite_title": "Polub wpis zdalnie", + "remote_interaction.follow": "Przejdź do obserwacji", + "remote_interaction.follow_title": "Obserwuj {user} zdalnie", + "remote_interaction.poll_vote": "Przejdź do ankiety", + "remote_interaction.poll_vote_title": "Zagłosuj w ankiecie zdalnie", + "remote_interaction.reblog": "Przejdź do wpisu", + "remote_interaction.reblog_title": "Udostępnij wpis zdalnie", + "remote_interaction.reply": "Przejdź do odpowiedzi", + "remote_interaction.reply_title": "Odpowiedz na wpis zdalnie", + "remote_interaction.user_not_found_error": "Nie można odnaleźć podanego użytkownika", "remote_timeline.filter_message": "Przeglądasz oś czasu {instance}", "reply_indicator.cancel": "Anuluj", + "reply_mentions.account.add": "Dodaj do wspomnianych", + "reply_mentions.account.remove": "Usuń z wspomnianych", + "reply_mentions.more": "i {count} więcej", + "reply_mentions.reply": "W odpowiedzi do {accounts}{more}", + "reply_mentions.reply_empty": "W odpowiedzi na wpis", "report.block": "Zablokuj {target}", "report.block_hint": "Czy chcesz też zablokować to konto?", "report.forward": "Przekaż na {target}", @@ -725,16 +811,11 @@ "schedule_button.add_schedule": "Zaplanuj wpis na później", "schedule_button.remove_schedule": "Opublikuj natychmiastowo", "scheduled_status.cancel": "Anuluj", + "search.action": "Szukaj „{query}”", "search.placeholder": "Szukaj", - "search_popout.search_format": "Zaawansowane wyszukiwanie", - "search_popout.tips.full_text": "Pozwala na wyszukiwanie wpisów które napisałeś(-aś), dodałeś(-aś) do ulubionych lub podbiłeś(-aś), w których o Tobie wspomniano, oraz pasujące nazwy użytkowników, pełne nazwy i hashtagi.", - "search_popout.tips.hashtag": "hasztag", - "search_popout.tips.status": "wpis", - "search_popout.tips.user": "użytkownik", "search_results.accounts": "Ludzie", "search_results.hashtags": "Hashtagi", "search_results.statuses": "Wpisy", - "search_results.top": "Góra", "security.codes.fail": "Nie udało się uzyskać zapasowych kodów", "security.confirm.fail": "Nieprawidłowy kod lub hasło. Spróbuj ponownie.", "security.delete_account.fail": "Nie udało się usunąć konta.", @@ -765,6 +846,7 @@ "security.update_password.success": "Pomyślnie zmieniono hasło.", "signup_panel.subtitle": "Zarejestruj się, aby przyłączyć się do dyskusji.", "signup_panel.title": "Nowi na {site_title}?", + "snackbar.view": "Wyświetl", "soapbox_config.authenticated_profile_hint": "Użytkownicy muszą być zalogowani, aby zobaczyć odpowiedzi i media na profilach użytkowników.", "soapbox_config.authenticated_profile_label": "Profile wymagają uwierzytelniania", "soapbox_config.copyright_footer.meta_fields.label_placeholder": "Stopka praw autorskich", @@ -824,6 +906,7 @@ "status.open": "Rozwiń ten wpis", "status.pin": "Przypnij do profilu", "status.pinned": "Przypięty wpis", + "status.quote": "Cytuj wpis", "status.reactions.cry": "Przykro mi", "status.reactions.empty": "Nikt nie zareagował na ten wpis. Gdy ktoś to zrobi, pojawi się tutaj.", "status.reactions.heart": "Super", @@ -849,7 +932,6 @@ "status.show_less_all": "Zwiń wszystkie", "status.show_more": "Rozwiń", "status.show_more_all": "Rozwiń wszystkie", - "status.show_thread": "Pokaż wątek", "status.title": "Wpis", "status.title_direct": "Wiadomość bezpośrednia", "status.unbookmark": "Usuń z zakładek", @@ -857,6 +939,7 @@ "status.unmute_conversation": "Cofnij wyciszenie konwersacji", "status.unpin": "Odepnij z profilu", "status_list.queue_label": "Naciśnij aby zobaczyć {count} {count, plural, one {nowy wpis} few {nowe wpisy} many {nowych wpisów} other {nowe wpisy}}", + "statuses.quote_tombstone": "Wpis jest niedostępny.", "statuses.tombstone": "Jeden lub więcej z wpisów jest już niedostępny.", "suggestions.dismiss": "Odrzuć sugestię", "tabs_bar.all": "Wszystkie", diff --git a/app/soapbox/locales/pt-BR.json b/app/soapbox/locales/pt-BR.json index e47fbb0c3..4fac771aa 100644 --- a/app/soapbox/locales/pt-BR.json +++ b/app/soapbox/locales/pt-BR.json @@ -8,6 +8,7 @@ "account.block_domain": "Esconder tudo de {domain}", "account.blocked": "Bloqueado", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Esse usuário não segue ninguém no momento.", "account.follows_you": "Segue você", "account.hide_reblogs": "Esconder compartilhamentos de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "A posse desse link foi verificada em {date}", "account.locked_info": "Essa conta está trancada. Se você a seguir sua solicitação será revisada manualmente.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se mudou para:", "account.mute": "Silenciar @{name}", "account.muted": "Silenciado", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots e respostas", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Fechar", "bundle_modal_error.message": "Algo de errado aconteceu enquanto este componente era carregado.", "bundle_modal_error.retry": "Tente novamente", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Usuários bloqueados", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mensagens diretas", + "column.directory": "Browse profiles", "column.domain_blocks": "Domínios escondidos", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Seguidores pendentes", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Página inicial", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Usuários silenciados", "column.notifications": "Notificações", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Global", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Voltar", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Esconder configurações", "column_header.show_settings": "Mostrar configurações", "community.column_settings.media_only": "Apenas mídia", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duração da enquete", "compose_form.poll.option_placeholder": "Opção {number}", "compose_form.poll.remove_option": "Remover essa opção", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publicar", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquear e denunciar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "Você tem certeza de que quer bloquear {name}?", "confirmations.delete.confirm": "Excluir", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Você tem certeza de que quer excluir esta postagem?", "confirmations.delete_list.confirm": "Excluir", "confirmations.delete_list.message": "Você tem certeza que quer deletar permanentemente a lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Rejeitar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} é um software de código aberto. Você pode contribuir ou reportar problemas na página do GitLab do projeto: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Ver contexto", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Adicionar a listas", "lists.account.remove": "Remover da lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Esconder notificações deste usuário?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compor um novo toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domínios escondidos", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoritos", "navigation_bar.filters": "Palavras silenciadas", "navigation_bar.follow_requests": "Seguidores pendentes", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Mais informações", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atalhos de teclado", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Sair", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Usuários silenciados", "navigation_bar.pins": "Postagens fixadas", "navigation_bar.preferences": "Preferências", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Segurança", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Atualizar", "poll.total_votes": "{count, plural, one {# voto} other {# votos}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Adicionar uma enquete", "poll_button.remove_poll": "Remover enquete", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Carregando…", "regeneration_indicator.sublabel": "Sua página inicial está sendo preparada!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "agora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Cancelar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Encaminhar para {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Pesquisar", - "search_popout.search_format": "Formato de busca avançado", - "search_popout.tips.full_text": "Texto simples retorna status que você escreveu, favoritou, compartilhou ou em que tenha sido mencionado; também retorna nomes de exibição, usuários e hashtags correspondentes.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "usuário", "search_results.accounts": "Pessoas", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/pt.json b/app/soapbox/locales/pt.json index 25f15b8a0..b8c30f1bd 100644 --- a/app/soapbox/locales/pt.json +++ b/app/soapbox/locales/pt.json @@ -8,6 +8,7 @@ "account.block_domain": "Esconder tudo do domínio {domain}", "account.blocked": "Bloqueado", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Desativada", "account.deactivated_description": "Esta conta foi desativada.", @@ -22,6 +23,7 @@ "account.follows.empty": "Este utilizador ainda não segue alguém.", "account.follows_you": "É teu seguidor", "account.hide_reblogs": "Esconder partilhas de @{name}", + "account.last_status": "Last active", "account.link_verified_on": "A posse deste link foi verificada em {date}", "account.locked_info": "O estatuto de privacidade desta conta é fechado. O dono revê manualmente que a pode seguir.", "account.login": "Iniciar sessão", @@ -31,6 +33,7 @@ "account.moved_to": "{name} mudou a sua conta para:", "account.mute": "Silenciar @{name}", "account.muted": "Silenciada", + "account.never_active": "Never", "account.posts": "Publicações", "account.posts_with_replies": "Publicações e respostas", "account.profile": "Perfil", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Tirar verificação de @{name}", "admin.users.actions.verify_user": "Verificar @{name}", "admin.users.user_deactivated_message": "@{acct} foi desativada", "admin.users.user_deleted_message": "@{acct} foi apagada", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} já não está mais verificada", "admin.users.user_verified_message": "@{acct} foi verificada", "admin_nav.awaiting_approval": "Aguardando Aprovação", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Criar backup", "backups.empty_message": "Nenhum backup encontrado. {action}", "backups.empty_message.action": "Criar um agora?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Fechar", "bundle_modal_error.message": "Ocorreu algo inesperado enquanto este componente era carregado.", "bundle_modal_error.retry": "Tentar novamente", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Enviar", "chat_box.input.placeholder": "Enviar uma mensagem…", "chat_panels.main_window.empty": "Sem chats encontrados. Para iniciar um chat, visita o perfil de algum utilizador.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Apagar mensagem", "chats.actions.more": "Mais", "chats.actions.report": "Denunciar utilizador", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Notificação de Som desligada", "chats.audio_toggle_on": "Notificação de Som ligada", "chats.dividers.today": "Hoje", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Histórico de moderação", "column.admin.reports": "Denúncias", "column.admin.reports.menu.moderation_log": "Histórico de moderação", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Utilizadores Bloqueados", "column.bookmarks": "Items Guardados", "column.chats": "Chats", "column.community": "Cronologia local", "column.crypto_donate": "Doar Cryptomoedas", + "column.developers": "Developers", "column.direct": "Mensagens diretas", + "column.directory": "Browse profiles", "column.domain_blocks": "Domínios escondidos", "column.edit_profile": "Editar perfil", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Palavras silenciadas", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Toda a palavra", "column.filters.whole_word_hint": "Quando uma palavra-chave ou frase é apenas alfanumérica, será apenas aplicado se corresponder à palavra completa", "column.follow_requests": "Seguidores pendentes", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Grupos", "column.home": "Início", "column.import_data": "Importar dados", "column.info": "Informação do servidor", "column.lists": "Listas", + "column.mentions": "Mentions", "column.mfa": "Autenticação Multifator", "column.mfa_cancel": "Cancelar", "column.mfa_confirm_button": "Confirmar", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceder à ativação", "column.mutes": "Utilizadores silenciados", "column.notifications": "Notificações", + "column.pins": "Pinned posts", "column.preferences": "Preferências", + "column.profile_directory": "Profile directory", "column.public": "Cronologia da Federação", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Segurança", "column.soapbox_config": "Config. do Soapbox", "column_back_button.label": "Voltar", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Esconder configurações", "column_header.show_settings": "Mostrar configurações", "community.column_settings.media_only": "Somente multimédia", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Duração da sondagem", "compose_form.poll.option_placeholder": "Opção {number}", "compose_form.poll.remove_option": "Apagar esta opção", - "compose_form.poll.type.hint": "Clica para alterar o tipo de sondagem. O círculo (por defeito) é única. Caixa de seleção é múltipla.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publicar", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "Está prestes a desmarcar uma publicação por @{acct} como sensível.", "confirmations.admin.mark_status_sensitive.confirm": "Marcar publicação como sensível", "confirmations.admin.mark_status_sensitive.message": "Está prestes a marcar uma publicação por @{acct} como sensível.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Bloquear e denunciar", "confirmations.block.confirm": "Bloquear", "confirmations.block.message": "De certeza que queres bloquear {name}?", "confirmations.delete.confirm": "Apagar", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "De certeza que queres apagar esta publicação?", "confirmations.delete_list.confirm": "Apagar", "confirmations.delete_list.message": "Tens a certeza de que desejas apagar permanentemente esta lista?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} aceita doações em cryptomoedas para financiar o nosso serviço. Obrigado pelo vosso apoio!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Doar", "donate_crypto": "Doar Cryptomoedas", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Biografia", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "Esta é uma conta robô", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Nome de exibição", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Cabeçalho", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF ou JPG. Pelo menos 2 MB. Será reduzido para 400x400px", "edit_profile.hints.bot": "Esta conta principalmente realiza ações automatizadas e podem não ser monitorizadas", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF ou JPG. Pelo menos 2 MB. Será reduzido para 1500x500px", "edit_profile.hints.hide_network": "Quem segues e quem te segue não será apresentado no teu perfil", "edit_profile.hints.locked": "Requer que aproves manualmente seguidores", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizar", "follow_request.reject": "Rejeitar", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} é software de código aberto (open source). Podes contribuir ou reportar problemas no GitLab do projecto: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "Este grupo não contém nenhum membro.", @@ -505,6 +553,8 @@ "lightbox.previous": "Anterior", "lightbox.view_context": "Ver contexto", "list.click_to_add": "Clica aqui para adicionares pessoas", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Adicionar ou Remover das Listas", "lists.account.add": "Adicionar à lista", "lists.account.remove": "Remover da lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Esconder notificações deste utilizador?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Escrever uma nova publicação", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domínios escondidos", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Gostos", "navigation_bar.filters": "Filtros", "navigation_bar.follow_requests": "Pedidos de seguimento", "navigation_bar.import_data": "Importar dados", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Sobre este servidor", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Atalhos de teclado", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Terminar sessão", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Silenciados", "navigation_bar.pins": "Afixados", "navigation_bar.preferences": "Preferências", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Segurança", "navigation_bar.soapbox_config": "Config. do Soapbox", "notification.chat_mention": "{name} enviou-te uma mensagem", @@ -627,14 +682,18 @@ "poll.refresh": "Recarregar", "poll.total_votes": "{count, plural, one {# voto} other {# votos}}", "poll.vote": "Votar", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Adicionar sondagem", "poll_button.remove_poll": "Remover sondagem", "preferences.fields.auto_play_gif_label": "Reproduzir automaticamente GIFs animados", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Exibir caixa de diálogo de confirmação antes de partilhar uma publicação", "preferences.fields.content_type_label": "Formato da publicação", "preferences.fields.delete_modal_label": "Exibir caixa de diálogo de confirmação antes de apagar uma publicação", "preferences.fields.demetricator_label": "Usar o Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Ocultar media marcada como sensível", "preferences.fields.display_media.hide_all": "Ocultar sempre", "preferences.fields.display_media.show_all": "Mostrar sempre", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Adicionar uma conta existente", "profile_dropdown.logout": "Sair de @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "A carregar…", "regeneration_indicator.sublabel": "A tua home está a ser preparada!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Nome de Utilizador", "registration.lead": "Com uma conta no {instance} serás capaz de seguir pessoas em qualquer servidor do Fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Porque te desejas juntar?", "registration.reason_hint": "Isto ajudará a rever a tua aplicação", "registration.sign_up": "Registo", "registration.tos": "Termos de Serviço", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "agora", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "Estás a ver a linha do tempo do domínio {instance}.", "reply_indicator.cancel": "Cancelar", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Bloquear {target}", "report.block_hint": "Desejas também bloquear esta conta?", "report.forward": "Encaminhar para {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Pesquisar", - "search_popout.search_format": "Formato avançado de pesquisa", - "search_popout.tips.full_text": "Texto simples devolve publicações que tu escreveste, marcaste com um gosto, partilhaste ou em que foste mencionado, tal como nomes de utilizador correspondentes, alcunhas e hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "estado", - "search_popout.tips.user": "utilizador", "search_results.accounts": "Pessoas", "search_results.hashtags": "Hashtags", "search_results.statuses": "Publicações", diff --git a/app/soapbox/locales/ro.json b/app/soapbox/locales/ro.json index cf2e1aabc..951b7782e 100644 --- a/app/soapbox/locales/ro.json +++ b/app/soapbox/locales/ro.json @@ -8,6 +8,7 @@ "account.block_domain": "Ascunde tot de la {domain}", "account.blocked": "Blocat", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Acest utilizator nu urmărește pe nimeni incă.", "account.follows_you": "Te urmărește", "account.hide_reblogs": "Ascunde redistribuirile de la @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Deținerea acestui link a fost verificată la {date}", "account.locked_info": "Acest profil este privat. Această persoană gestioneaz manual cine o urmărește.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} a fost mutat la:", "account.mute": "Oprește @{name}", "account.muted": "Oprit", + "account.never_active": "Never", "account.posts": "Postări", "account.posts_with_replies": "Postări și replici", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Închide", "bundle_modal_error.message": "Ceva nu a funcționat în timupul încărcării acestui component.", "bundle_modal_error.retry": "Încearcă din nou", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Utilizatori blocați", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Fluxul Local", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mesaje directe", + "column.directory": "Browse profiles", "column.domain_blocks": "Domenii ascunse", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Cereri de urmărire", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Acasă", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Liste", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Utilizatori opriți", "column.notifications": "Notificări", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Flux global", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Înapoi", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Ascunde setările", "column_header.show_settings": "Arată setările", "community.column_settings.media_only": "Doar media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Postează", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blochează", "confirmations.block.message": "Ești sigur că vrei să blochezi {name}?", "confirmations.delete.confirm": "Șterge", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ești șigur că vrei să ștergi asta?", "confirmations.delete_list.confirm": "Șterge", "confirmations.delete_list.message": "Ești sigur că vrei să ștergi permanent această listă?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizează", "follow_request.reject": "Respinge", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} este o rețea de socializare de tip open source. Puteți contribuii la dezvoltarea ei sau să semnalați erorile pe GitLab la {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Precedentul", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Adaugă în listă", "lists.account.remove": "Elimină din listă", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Ascunzi notificările de la acest utilizator?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compune o nouă postare", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Domenii ascunse", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favorite", "navigation_bar.filters": "Cuvinte oprite", "navigation_bar.follow_requests": "Cereri de urmărire", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Despre această instanță", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Prescurtări", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Deconectare", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Utilizatori opriți", "navigation_bar.pins": "Postări fixate", "navigation_bar.preferences": "Preferințe", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Securitate", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Încărcare…", "regeneration_indicator.sublabel": "Fluxul tău este în preparare!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}z", "relative_time.hours": "{number}h", "relative_time.just_now": "acum", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Anulează", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Redirecționează catre {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Caută", - "search_popout.search_format": "Formate pentru căutare avansată", - "search_popout.tips.full_text": "Textele simple returnează statusuri pe care le-ai scris, favorizat, redistribuit, sau în care sunt menționate , deasmenea și utilizatorii sau hastagurile care se potrivesc.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "utilizator", "search_results.accounts": "Oameni", "search_results.hashtags": "Hashtaguri", "search_results.statuses": "Postări", diff --git a/app/soapbox/locales/ru.json b/app/soapbox/locales/ru.json index d41b5c5a6..c82de3ef6 100644 --- a/app/soapbox/locales/ru.json +++ b/app/soapbox/locales/ru.json @@ -8,6 +8,7 @@ "account.block_domain": "Блокировать все с {domain}", "account.blocked": "Заблокирован(а)", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Отключение Аккаунта", "account.deactivated_description": "Этот аккаунт был отключен.", @@ -22,6 +23,7 @@ "account.follows.empty": "Этот пользователь ни на кого не подписан.", "account.follows_you": "Подписан(а) на вас", "account.hide_reblogs": "Скрыть реблоги от @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Владение этой ссылкой было проверено {date}", "account.locked_info": "Это закрытый аккаунт. Его владелец вручную одобряет подписчиков.", "account.login": "Войти", @@ -31,6 +33,7 @@ "account.moved_to": "Ищите {name} здесь:", "account.mute": "Скрыть @{name}", "account.muted": "Скрыт", + "account.never_active": "Never", "account.posts": "Посты", "account.posts_with_replies": "Посты с ответами", "account.profile": "Профиль", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Отменить подтверждение @{name}", "admin.users.actions.verify_user": "Подтвердить @{name}", "admin.users.user_deactivated_message": "@{acct} деактивирован", "admin.users.user_deleted_message": "@{acct} удалён", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "Подтверждение @{acct} отменено", "admin.users.user_verified_message": "@{acct} подтверждён", "admin_nav.awaiting_approval": "Ожидает одобрения", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Создать резервную копию", "backups.empty_message": "Резервных копий не найдено. {action}", "backups.empty_message.action": "Создать?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Закрыть", "bundle_modal_error.message": "Что-то пошло не так при загрузке этого компонента.", "bundle_modal_error.retry": "Попробовать снова", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Отправить", "chat_box.input.placeholder": "Отправить сообщение…", "chat_panels.main_window.empty": "Чатов не найдено. Откройте профиль пользователя, чтобы начать новый.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Удалить Сообщение", "chats.actions.more": "Ещё", "chats.actions.report": "Пожаловаться на пользователя", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Отключить аудио увидомление", "chats.audio_toggle_on": "Включить аудио увидомление", "chats.dividers.today": "Сегодня", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Лог модерации", "column.admin.reports": "Репорты", "column.admin.reports.menu.moderation_log": "Лог модерации", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Резервные копии", "column.blocks": "Список блокировки", "column.bookmarks": "Закладки", "column.chats": "Чаты", "column.community": "Локальная лента", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Личные сообщения", + "column.directory": "Browse profiles", "column.domain_blocks": "Скрытые домены", "column.edit_profile": "Редактирование профиля", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Скрытые слова", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Всё слово", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Запросы на подписку", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Группы", "column.home": "Главная", "column.import_data": "Дата импорта", "column.info": "Информация о сервере", "column.lists": "Списки", + "column.mentions": "Mentions", "column.mfa": "Мультифакторная аутентификация", "column.mfa_cancel": "Отменить", "column.mfa_confirm_button": "Принять", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Список скрытых пользователей", "column.notifications": "Уведомления", + "column.pins": "Pinned posts", "column.preferences": "Настройки", + "column.profile_directory": "Profile directory", "column.public": "Глобальная лента", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Федеративная лента", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Настройки безопастности.", "column.soapbox_config": "Настройка Soapbox", "column_back_button.label": "Назад", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Скрыть настройки", "column_header.show_settings": "Показать настройки", "community.column_settings.media_only": "Только с медиа", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Длительность опроса", "compose_form.poll.option_placeholder": "Вариант {number}", "compose_form.poll.remove_option": "Удалить этот вариант", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Запостить", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Заблокировать и пожаловаться", "confirmations.block.confirm": "Заблокировать", "confirmations.block.message": "Вы уверены, что хотите заблокировать {name}?", "confirmations.delete.confirm": "Удалить", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Вы уверены, что хотите удалить этот статус?", "confirmations.delete_list.confirm": "Удалить", "confirmations.delete_list.message": "Вы действительно хотите навсегда удалить этот список?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Описание профиля", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "Отметить аккаунт как бот.", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Отображаемое имя(Можно на русском)", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Авторизовать", "follow_request.reject": "Отказать", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} — сервис с открытым исходным кодом. Вы можете внести вклад или сообщить о проблемах на GitLab: {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Назад", "lightbox.view_context": "Контекст", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Добавить в список", "lists.account.remove": "Убрать из списка", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Убрать уведомления от этого пользователя?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Создать новый статус", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Скрытые домены", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Понравившееся", "navigation_bar.filters": "Заглушенные слова", "navigation_bar.follow_requests": "Запросы на подписку", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Об узле", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Сочетания клавиш", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Выйти", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Список скрытых пользователей", "navigation_bar.pins": "Закреплённые посты", "navigation_bar.preferences": "Настройки", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Безопасность", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Обновить", "poll.total_votes": "{count, plural, one {# голос} few {# голоса} many {# голосов} other {# голосов}}", "poll.vote": "Голосовать", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Добавить опрос", "poll_button.remove_poll": "Удалить опрос", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Загрузка…", "regeneration_indicator.sublabel": "Ваша домашняя лента готовится!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}д", "relative_time.hours": "{number}ч", "relative_time.just_now": "только что", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Отмена", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Переслать в {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Поиск", - "search_popout.search_format": "Продвинутый формат поиска", - "search_popout.tips.full_text": "Возвращает посты, которые Вы написали, отметили как 'избранное', продвинули или в которых были упомянуты, а также содержащие юзернейм, имя и хэштеги.", - "search_popout.tips.hashtag": "хэштег", - "search_popout.tips.status": "статус", - "search_popout.tips.user": "пользователь", "search_results.accounts": "Люди", "search_results.hashtags": "Хэштеги", "search_results.statuses": "Посты", diff --git a/app/soapbox/locales/sk.json b/app/soapbox/locales/sk.json index c451b5817..b80d5411f 100644 --- a/app/soapbox/locales/sk.json +++ b/app/soapbox/locales/sk.json @@ -8,6 +8,7 @@ "account.block_domain": "Ukry všetko z {domain}", "account.blocked": "Blokovaný/á", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Tento užívateľ ešte nikoho nenásleduje.", "account.follows_you": "Následuje ťa", "account.hide_reblogs": "Skry vyzdvihnutia od @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Vlastníctvo tohto odkazu bolo skontrolované {date}", "account.locked_info": "Stav súkromia pre tento účet je nastavený na zamknutý. Jeho vlastník sám prehodnocuje, kto ho môže sledovať.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} sa presunul/a na:", "account.mute": "Nevšímaj si @{name}", "account.muted": "Utíšený/á", + "account.never_active": "Never", "account.posts": "Príspevkov", "account.posts_with_replies": "Príspevky aj s odpoveďami", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Zatvor", "bundle_modal_error.message": "Nastala chyba pri načítaní tohto komponentu.", "bundle_modal_error.retry": "Skúsiť znova", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokovaní užívatelia", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Miestna časová os", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Súkromné správy", + "column.directory": "Browse profiles", "column.domain_blocks": "Skryté domény", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Žiadosti o sledovanie", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Domov", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Zoznamy", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Ignorovaní užívatelia", "column.notifications": "Oboznámenia", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federovaná časová os", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Späť", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Skryť nastavenia", "column_header.show_settings": "Ukáž nastavenia", "community.column_settings.media_only": "Iba médiá", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Trvanie ankety", "compose_form.poll.option_placeholder": "Voľba {number}", "compose_form.poll.remove_option": "Odstráň túto voľbu", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Pošli", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Zablokuj a nahlás", "confirmations.block.confirm": "Blokuj", "confirmations.block.message": "Si si istý/á, že chceš blokovať {name}?", "confirmations.delete.confirm": "Vymaž", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Si si istý/á, že chceš vymazať túto správu?", "confirmations.delete_list.confirm": "Vymaž", "confirmations.delete_list.message": "Si si istý/á, že chceš natrvalo vymazať tento zoznam?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Povoľ prístup", "follow_request.reject": "Odmietni", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} je softvér s otvoreným kódom. Nahlásiť chyby, alebo prispievať môžeš na GitLabe v {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Predchádzajúci", "lightbox.view_context": "Ukáž kontext", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Pridaj do zoznamu", "lists.account.remove": "Odober zo zoznamu", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Skry oznámenia od tohto používateľa?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Napíš nový príspevok", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Skryté domény", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Obľúbené", "navigation_bar.filters": "Filtrované slová", "navigation_bar.follow_requests": "Žiadosti o sledovanie", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "O tomto serveri", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Klávesové skratky", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Odhlás sa", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Ignorovaní užívatelia", "navigation_bar.pins": "Pripnuté príspevky", "navigation_bar.preferences": "Voľby", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Zabezbečenie", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Občerstvi", "poll.total_votes": "{count, plural, one {# hlas} few {# hlasov} many {# hlasov} other {# hlasov}}", "poll.vote": "Hlasuj", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Pridaj anketu", "poll_button.remove_poll": "Odstráň anketu", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Načítava sa…", "regeneration_indicator.sublabel": "Vaša domovská nástenka sa pripravuje!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}dní", "relative_time.hours": "{number}hod", "relative_time.just_now": "teraz", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Zrušiť", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Posuň ku {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Hľadaj", - "search_popout.search_format": "Pokročilé vyhľadávanie", - "search_popout.tips.full_text": "Vráti jednoduchý textový výpis príspevkov ktoré si napísal/a, ktoré si obľúbil/a, povýšil/a, alebo aj tých, v ktorých si bol/a spomenutý/á, a potom všetky zadaniu odpovedajúce prezívky, mená a haštagy.", - "search_popout.tips.hashtag": "haštag", - "search_popout.tips.status": "príspevok", - "search_popout.tips.user": "užívateľ", "search_results.accounts": "Ľudia", "search_results.hashtags": "Haštagy", "search_results.statuses": "Príspevky", diff --git a/app/soapbox/locales/sl.json b/app/soapbox/locales/sl.json index 7284b0e42..bdc41af55 100644 --- a/app/soapbox/locales/sl.json +++ b/app/soapbox/locales/sl.json @@ -8,6 +8,7 @@ "account.block_domain": "Skrij vse iz {domain}", "account.blocked": "Blokirano", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Ta uporabnik še ne sledi nikomur.", "account.follows_you": "Sledi tebi", "account.hide_reblogs": "Skrij spodbude od @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Lastništvo te povezave je bilo preverjeno {date}", "account.locked_info": "Stanje zasebnosti računa je nastavljeno na zaklenjeno. Lastnik ročno pregleda, kdo ga lahko spremlja.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se je premaknil na:", "account.mute": "Utišaj @{name}", "account.muted": "Utišan", + "account.never_active": "Never", "account.posts": "Tuti", "account.posts_with_replies": "Tuti in odgovori", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Zapri", "bundle_modal_error.message": "Med nalaganjem te komponente je prišlo do napake.", "bundle_modal_error.retry": "Poskusi ponovno", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokirani uporabniki", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokalna časovnica", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Neposredna sporočila", + "column.directory": "Browse profiles", "column.domain_blocks": "Skrite domene", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Sledi prošnjam", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Domov", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Seznami", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Utišani uporabniki", "column.notifications": "Obvestila", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Združena časovnica", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Nazaj", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Skrij nastavitve", "column_header.show_settings": "Prikaži nastavitve", "community.column_settings.media_only": "Samo mediji", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Trajanje ankete", "compose_form.poll.option_placeholder": "Izbira {number}", "compose_form.poll.remove_option": "Odstrani to izbiro", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tutni", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blokiraj in Prijavi", "confirmations.block.confirm": "Blokiraj", "confirmations.block.message": "Ali ste prepričani, da želite blokirati {name}?", "confirmations.delete.confirm": "Izbriši", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ali ste prepričani, da želite izbrisati to stanje?", "confirmations.delete_list.confirm": "Izbriši", "confirmations.delete_list.message": "Ali ste prepričani, da želite trajno izbrisati ta seznam?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Overi", "follow_request.reject": "Zavrni", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} je odprtokodna programska oprema. Na GitLabu na {code_link} (v{code_version}) lahko prispevate ali poročate o napakah.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Prejšnji", "lightbox.view_context": "Poglej kontekst", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Dodaj na seznam", "lists.account.remove": "Odstrani s seznama", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Skrij obvestila tega uporabnika?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Sestavi nov tut", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Skrite domene", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Priljubljeni", "navigation_bar.filters": "Utišane besede", "navigation_bar.follow_requests": "Prošnje za sledenje", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "O tem strežniku", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Hitre tipke", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Odjava", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Utišani uporabniki", "navigation_bar.pins": "Pripeti tuti", "navigation_bar.preferences": "Nastavitve", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Varnost", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Osveži", "poll.total_votes": "{count, plural,one {# glas} other {# glasov}}", "poll.vote": "Glasuj", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Dodaj anketo", "poll_button.remove_poll": "Odstrani anketo", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Nalaganje…", "regeneration_indicator.sublabel": "Vaš domači vir se pripravlja!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "zdaj", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Prekliči", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Posreduj do {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Iskanje", - "search_popout.search_format": "Napredna oblika iskanja", - "search_popout.tips.full_text": "Enostavno besedilo vrne statuse, ki ste jih napisali, vzljubili, spodbudili ali ste bili v njih omenjeni, kot tudi ujemajoča se uporabniška imena, prikazna imena in ključnike.", - "search_popout.tips.hashtag": "ključnik", - "search_popout.tips.status": "stanje", - "search_popout.tips.user": "uporabnik", "search_results.accounts": "Ljudje", "search_results.hashtags": "Ključniki", "search_results.statuses": "Tuti", diff --git a/app/soapbox/locales/sq.json b/app/soapbox/locales/sq.json index 064d4f287..3e388b56f 100644 --- a/app/soapbox/locales/sq.json +++ b/app/soapbox/locales/sq.json @@ -8,6 +8,7 @@ "account.block_domain": "Fshih gjithçka prej {domain}", "account.blocked": "E bllokuar", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Ky përdorues ende s’ndjek njeri.", "account.follows_you": "Ju ndjek", "account.hide_reblogs": "Fshih përforcime nga @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Pronësia e kësaj lidhjeje qe kontrolluar më {date}", "account.locked_info": "Gjendja e privatësisë së kësaj llogarie është caktuar si e kyçur. I zoti merr dorazi në shqyrtim cilët mund ta ndjekin.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} ka kaluar te:", "account.mute": "Heshtoni @{name}", "account.muted": "Heshtuar", + "account.never_active": "Never", "account.posts": "Mesazhe", "account.posts_with_replies": "Mesazhe dhe përgjigje", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Mbylle", "bundle_modal_error.message": "Diç shkoi ters teksa ngarkohej ky përbërës.", "bundle_modal_error.retry": "Riprovoni", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Përdorues të bllokuar", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Rrjedhë kohore vendore", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Mesazhe të drejtpërdrejta", + "column.directory": "Browse profiles", "column.domain_blocks": "Përkatësi të fshehura", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Kërkesa për ndjekje", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Kreu", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Lista", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Përdorues të heshtuar", "column.notifications": "Njoftime", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Rrjedhë kohore e federuar", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Mbrapsht", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Fshihi rregullimet", "column_header.show_settings": "Shfaq rregullime", "community.column_settings.media_only": "Vetëm Media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Mesazh", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Bllokoje", "confirmations.block.message": "Jeni i sigurt se doni të bllokohet {name}?", "confirmations.delete.confirm": "Fshije", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Jeni i sigurt se doni të fshihet kjo gjendje?", "confirmations.delete_list.confirm": "Fshije", "confirmations.delete_list.message": "Jeni i sigurt që doni të fshihet përgjithmonë kjo listë?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Autorizoje", "follow_request.reject": "Hidhe tej", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name}-i është software me burim të hapur. Mund të jepni ndihmesë ose të njoftoni probleme në GitLab, te {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "E mëparshmja", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Shto në listë", "lists.account.remove": "Hiqe nga lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Të fshihen njoftimet prej këtij përdoruesi?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Hartoni mesazh të ri", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Përkatësi të fshehura", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Të parapëlqyer", "navigation_bar.filters": "Fjalë të heshtuara", "navigation_bar.follow_requests": "Kërkesa për ndjekje", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Mbi këtë shërbyes", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Taste përkatës", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Dalje", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Përdorues të heshtuar", "navigation_bar.pins": "Mesazhe të fiksuar", "navigation_bar.preferences": "Parapëlqime", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Siguri", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Po ngarkohet…", "regeneration_indicator.sublabel": "Prurja juaj vetjake po përgatiteet!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "tani", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Anuloje", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Përcillja {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Kërkoni", - "search_popout.search_format": "Format kërkimi të përparuar", - "search_popout.tips.full_text": "Kërkimi për tekst të thjeshtë përgjigjet me gjendje që keni shkruar, parapëlqyer, përforcuar, ose ku jeni përmendur, si dhe emra përdoruesish, emra ekrani dhe hashtagë që kanë përputhje me termin e kërkimit.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "gjendje", - "search_popout.tips.user": "përdorues", "search_results.accounts": "Persona", "search_results.hashtags": "Hashtagë", "search_results.statuses": "Mesazhe", diff --git a/app/soapbox/locales/sr-Latn.json b/app/soapbox/locales/sr-Latn.json index b46f5efb0..b2e33e062 100644 --- a/app/soapbox/locales/sr-Latn.json +++ b/app/soapbox/locales/sr-Latn.json @@ -8,6 +8,7 @@ "account.block_domain": "Sakrij sve sa domena {domain}", "account.blocked": "Blocked", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "Prati Vas", "account.hide_reblogs": "Sakrij podrške koje daje korisnika @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} se pomerio na:", "account.mute": "Ućutkaj korisnika @{name}", "account.muted": "Muted", + "account.never_active": "Never", "account.posts": "Statusa", "account.posts_with_replies": "Toots with replies", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Zatvori", "bundle_modal_error.message": "Nešto nije bilo u redu pri učitavanju ove komponente.", "bundle_modal_error.retry": "Pokušajte ponovo", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blokirani korisnici", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokalna lajna", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direct messages", + "column.directory": "Browse profiles", "column.domain_blocks": "Hidden domains", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Zahtevi za praćenje", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Početna", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Liste", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Ućutkani korisnici", "column.notifications": "Obaveštenja", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federisana lajna", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Nazad", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Sakrij postavke", "column_header.show_settings": "Prikaži postavke", "community.column_settings.media_only": "Media Only", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tutni", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Blokiraj", "confirmations.block.message": "Da li ste sigurni da želite da blokirate korisnika {name}?", "confirmations.delete.confirm": "Obriši", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Da li ste sigurni da želite obrišete ovaj status?", "confirmations.delete_list.confirm": "Obriši", "confirmations.delete_list.message": "Da li ste sigurni da želite da bespovratno obrišete ovu listu?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Odobri", "follow_request.reject": "Odbij", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} je softver otvorenog koda. Možete mu doprineti ili prijaviti probleme preko GitLab-a na {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Prethodni", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Dodaj na listu", "lists.account.remove": "Ukloni sa liste", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Sakrij obaveštenja od ovog korisnika?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Omiljeni", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "Zahtevi za praćenje", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "O ovoj instanci", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Prečice na tastaturi", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Odjava", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Ućutkani korisnici", "navigation_bar.pins": "Prikačeni tutovi", "navigation_bar.preferences": "Podešavanja", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Security", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Loading…", "regeneration_indicator.sublabel": "Your home feed is being prepared!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "sada", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Poništi", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Forward to {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Pretraga", - "search_popout.search_format": "Napredni format pretrage", - "search_popout.tips.full_text": "Simple text returns posts you have written, favorited, reposted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", - "search_popout.tips.hashtag": "hešteg", - "search_popout.tips.status": "post", - "search_popout.tips.user": "korisnik", "search_results.accounts": "People", "search_results.hashtags": "Hashtags", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/sr.json b/app/soapbox/locales/sr.json index 7406c4082..5e6fc48b8 100644 --- a/app/soapbox/locales/sr.json +++ b/app/soapbox/locales/sr.json @@ -8,6 +8,7 @@ "account.block_domain": "Сакриј све са домена {domain}", "account.blocked": "Блокиран", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Корисник тренутно не прати никога.", "account.follows_you": "Прати Вас", "account.hide_reblogs": "Сакриј подршке које даје корисника @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} се померио на:", "account.mute": "Ућуткај корисника @{name}", "account.muted": "Ућуткан", + "account.never_active": "Never", "account.posts": "Трубе", "account.posts_with_replies": "Трубе и одговори", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Затвори", "bundle_modal_error.message": "Нешто није било у реду при учитавању ове компоненте.", "bundle_modal_error.retry": "Покушајте поново", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Блокирани корисници", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Локална временска линија", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Директне поруке", + "column.directory": "Browse profiles", "column.domain_blocks": "Скривени домени", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Захтеви за праћење", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Почетна", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Листе", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Ућуткани корисници", "column.notifications": "Обавештења", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Здружена временска линија", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Назад", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Сакриј поставке", "column_header.show_settings": "Прикажи поставке", "community.column_settings.media_only": "Само Медији", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Труби", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Блокирај", "confirmations.block.message": "Да ли сте сигурни да желите да блокирате корисника {name}?", "confirmations.delete.confirm": "Обриши", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Да ли сте сигурни да желите обришете овај статус?", "confirmations.delete_list.confirm": "Обриши", "confirmations.delete_list.message": "Да ли сте сигурни да желите да бесповратно обришете ову листу?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Одобри", "follow_request.reject": "Одбиј", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} је софтвер отвореног кода. Можете му допринети или пријавити проблеме преко ГитХаба на {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Претходни", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Додај на листу", "lists.account.remove": "Уклони са листе", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Сакриј обавештења од овог корисника?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Саставите нову трубу", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Сакривени домени", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Омиљене", "navigation_bar.filters": "Пригушене речи", "navigation_bar.follow_requests": "Захтеви за праћење", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "О овој инстанци", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Пречице на тастатури", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Одјава", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Ућуткани корисници", "navigation_bar.pins": "Прикачене трубе", "navigation_bar.preferences": "Подешавања", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Безбедност", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Учитавање…", "regeneration_indicator.sublabel": "Ваша почетна страница се припрема!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "сада", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Поништи", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Проследити {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Претрага", - "search_popout.search_format": "Напредни формат претраге", - "search_popout.tips.full_text": "Једноставан текст враћа статусе које сте написали, фаворизовали, подржали или били поменути, као и подударање корисничких имена, приказаних имена, и тараба.", - "search_popout.tips.hashtag": "хештег", - "search_popout.tips.status": "статус", - "search_popout.tips.user": "корисник", "search_results.accounts": "Људи", "search_results.hashtags": "Тарабе", "search_results.statuses": "Трубе", diff --git a/app/soapbox/locales/sv.json b/app/soapbox/locales/sv.json index 47274a9fa..bad296144 100644 --- a/app/soapbox/locales/sv.json +++ b/app/soapbox/locales/sv.json @@ -8,6 +8,7 @@ "account.block_domain": "Dölj allt från {domain}", "account.blocked": "Blockerad", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Den här användaren följer inte någon ännu.", "account.follows_you": "Följer dig", "account.hide_reblogs": "Dölj knuffar från @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Ägarskapet för det här kontot kontrollerades den {date}", "account.locked_info": "Detta konto har en låst integritetsstatus. Ägaren väljer manuellt vem som kan följa.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} har flyttat till:", "account.mute": "Tysta @{name}", "account.muted": "Tystad", + "account.never_active": "Never", "account.posts": "Inlägg", "account.posts_with_replies": "Posts och svar", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Stäng", "bundle_modal_error.message": "Något gick fel när denna komponent laddades.", "bundle_modal_error.retry": "Försök igen", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Blockerade användare", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Lokal tidslinje", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Direktmeddelanden", + "column.directory": "Browse profiles", "column.domain_blocks": "Dolda domäner", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Följförfrågningar", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Hem", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listor", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Tystade användare", "column.notifications": "Meddelanden", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Förenad tidslinje", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Tillbaka", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Dölj inställningar", "column_header.show_settings": "Visa inställningar", "community.column_settings.media_only": "Enbart media", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Varaktighet för omröstning", "compose_form.poll.option_placeholder": "Alternativ {number}", "compose_form.poll.remove_option": "Ta bort alternativ", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Tut", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Blockera & rapportera", "confirmations.block.confirm": "Blockera", "confirmations.block.message": "Är du säker att du vill blockera {name}?", "confirmations.delete.confirm": "Ta bort", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Är du säker att du vill ta bort denna status?", "confirmations.delete_list.confirm": "Ta bort", "confirmations.delete_list.message": "Är du säker på att du vill radera denna lista permanent?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Godkänn", "follow_request.reject": "Avvisa", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} är programvara med öppen källkod. Du kan bidra eller rapportera problem via GitLab på {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Tidigare", "lightbox.view_context": "Visa kontext", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Lägg till i lista", "lists.account.remove": "Ta bort från lista", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Dölj notifikationer från denna användare?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Författa ny toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Dolda domäner", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoriter", "navigation_bar.filters": "Tystade ord", "navigation_bar.follow_requests": "Följförfrågningar", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Om denna instans", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Kortkommandon", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logga ut", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Tystade användare", "navigation_bar.pins": "Nålade inlägg (toots)", "navigation_bar.preferences": "Inställningar", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Säkerhet", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Ladda om", "poll.total_votes": "{count, plural, one {1 röst} other {# röster}}", "poll.vote": "Rösta", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Lägg till en omröstning", "poll_button.remove_poll": "Ta bort omröstning", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Laddar…", "regeneration_indicator.sublabel": "Ditt hemmaflöde förbereds!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}tim", "relative_time.just_now": "nu", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Ångra", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Vidarebefordra till {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Sök", - "search_popout.search_format": "Avancerat sökformat", - "search_popout.tips.full_text": "Enkel text returnerar statusar där du har skrivit, favoriserat, knuffat eller nämnts samt med matchande användarnamn, visningsnamn och hashtags.", - "search_popout.tips.hashtag": "hashtag", - "search_popout.tips.status": "post", - "search_popout.tips.user": "användare", "search_results.accounts": "Människor", "search_results.hashtags": "Hashtaggar", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/ta.json b/app/soapbox/locales/ta.json index e4a3bc692..a7b673734 100644 --- a/app/soapbox/locales/ta.json +++ b/app/soapbox/locales/ta.json @@ -8,6 +8,7 @@ "account.block_domain": "எல்லாவற்றையும் மறைக்க {domain}", "account.blocked": "தடைமுட்டுகள்", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.", "account.follows_you": "நீ பின் தொடர்கிறாய்", "account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}", + "account.last_status": "Last active", "account.link_verified_on": "இந்த இணைப்பை உரிமையாளர் சரிபார்க்கப்பட்டது {date}", "account.locked_info": "இந்தக் கணக்கு தனியுரிமை நிலை பூட்டப்பட்டுள்ளது. அவர்களைப் பின்தொடர்பவர் யார் என்பதை உரிமையாளர் கைமுறையாக மதிப்பாய்வு செய்கிறார்.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} நகர்த்தப்பட்டது:", "account.mute": "ஊமையான @{name}", "account.muted": "முடக்கியது", + "account.never_active": "Never", "account.posts": "Posts", "account.posts_with_replies": "Toots மற்றும் பதில்கள்", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "நெருக்கமாக", "bundle_modal_error.message": "இந்த கூறுகளை ஏற்றும்போது ஏதோ தவறு ஏற்பட்டது.", "bundle_modal_error.retry": "மீண்டும் முயற்சி செய்", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "தடுக்கப்பட்ட பயனர்கள்", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "உள்ளூர் காலக்கெடு", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "நேரடி செய்திகள்", + "column.directory": "Browse profiles", "column.domain_blocks": "மறைந்த களங்கள்", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "கோரிக்கைகளை பின்பற்றவும்", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Home", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "குதிரை வீர்ர்கள்", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "முடக்கப்பட்ட பயனர்கள்", "column.notifications": "Notifications", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "கூட்டாட்சி காலக்கெடு", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "ஆதரி", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "அமைப்புகளை மறை", "column_header.show_settings": "அமைப்புகளைக் காட்டு", "community.column_settings.media_only": "மீடியா மட்டுமே", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "வாக்கெடுப்பு காலம்", "compose_form.poll.option_placeholder": "தேர்ந்தெடுப்ப {number}", "compose_form.poll.remove_option": "இந்த விருப்பத்தை அகற்றவும்", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "Block", "confirmations.block.message": "நீங்கள் நிச்சயமாக தடைசெய்ய விரும்புகிறீர்களா {name}?", "confirmations.delete.confirm": "Delete", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "இந்த நிலையை நிச்சயமாக நீக்க விரும்புகிறீர்களா?", "confirmations.delete_list.confirm": "Delete", "confirmations.delete_list.message": "இந்த பட்டியலில் நிரந்தரமாக நீக்க விரும்புகிறீர்களா?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "அதிகாரமளி", "follow_request.reject": "விலக்கு", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} திறந்த மூல மென்பொருள். GitLab இல் நீங்கள் பங்களிக்கவோ அல்லது புகார் அளிக்கவோ முடியும் {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "சென்ற", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "பட்டியலில் சேர்", "lists.account.remove": "பட்டியலில் இருந்து அகற்று", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "இந்த பயனரின் அறிவிப்புகளை மறைக்கவா?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "புதியவற்றை எழுதுக toot", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "மறைந்த களங்கள்", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "விருப்பத்துக்குகந்த", "navigation_bar.filters": "முடக்கப்பட்ட வார்த்தைகள்", "navigation_bar.follow_requests": "கோரிக்கைகளை பின்பற்றவும்", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "இந்த நிகழ்வு பற்றி", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "சுருக்குவிசைகள்", "navigation_bar.lists": "Lists", "navigation_bar.logout": "விடு பதிகை", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "முடக்கப்பட்ட பயனர்கள்", "navigation_bar.pins": "பொருத்தப்பட்டன toots", "navigation_bar.preferences": "விருப்பங்கள்", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "பத்திரம்", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "பத்துயிர்ப்ப?ட்டு", "poll.total_votes": "{count, plural, one {# vote} மற்ற {# votes}}", "poll.vote": "வாக்களி", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "வாக்கெடுப்பைச் சேர்க்கவும்", "poll_button.remove_poll": "வாக்கெடுப்பை அகற்று", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "சுமையேற்றம்…", "regeneration_indicator.sublabel": "உங்கள் வீட்டு ஊட்டம் தயார் செய்யப்படுகிறது!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "இப்பொழுது", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "எதிராணை", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "முன்னோக்கி {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "தேடு", - "search_popout.search_format": "மேம்பட்ட தேடல் வடிவம்", - "search_popout.tips.full_text": "எளிமையான உரை நீங்கள் எழுதப்பட்ட, புகழ், அதிகரித்தது, அல்லது குறிப்பிட்டுள்ள, அதே போல் பயனர் பெயர்கள், காட்சி பெயர்கள், மற்றும் ஹேஸ்டேகைகளை கொண்டுள்ளது என்று நிலைகளை கொடுக்கிறது.", - "search_popout.tips.hashtag": "ஹேஸ்டேக்", - "search_popout.tips.status": "post", - "search_popout.tips.user": "user", "search_results.accounts": "People", "search_results.hashtags": "ஹாஷ்டேக்குகளைச்", "search_results.statuses": "Posts", diff --git a/app/soapbox/locales/te.json b/app/soapbox/locales/te.json index 49bc5ffda..53c361321 100644 --- a/app/soapbox/locales/te.json +++ b/app/soapbox/locales/te.json @@ -8,6 +8,7 @@ "account.block_domain": "{domain} నుంచి అన్నీ దాచిపెట్టు", "account.blocked": "బ్లాక్ అయినవి", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "ఈ వినియోగదారి ఇంకా ఎవరినీ అనుసరించడంలేదు.", "account.follows_you": "మిమ్మల్ని అనుసరిస్తున్నారు", "account.hide_reblogs": "@{name} నుంచి బూస్ట్ లను దాచిపెట్టు", + "account.last_status": "Last active", "account.link_verified_on": "ఈ లంకె యొక్క యాజమాన్యం {date}న పరీక్షించబడింది", "account.locked_info": "ఈ ఖాతా యొక్క గోప్యత స్థితి లాక్ చేయబడి వుంది. ఈ ఖాతాను ఎవరు అనుసరించవచ్చో యజమానే నిర్ణయం తీసుకుంటారు.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} ఇక్కడికి మారారు:", "account.mute": "@{name}ను మ్యూట్ చెయ్యి", "account.muted": "మ్యూట్ అయినవి", + "account.never_active": "Never", "account.posts": "టూట్లు", "account.posts_with_replies": "టూట్లు మరియు ప్రత్యుత్తరములు", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "మూసివేయు", "bundle_modal_error.message": "ఈ భాగం లోడ్ అవుతున్నప్పుడు ఏదో తప్పు జరిగింది.", "bundle_modal_error.retry": "మళ్ళీ ప్రయత్నించండి", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "బ్లాక్ చేయబడిన వినియోగదారులు", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "స్థానిక కాలక్రమం", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "ప్రత్యక్ష సందేశాలు", + "column.directory": "Browse profiles", "column.domain_blocks": "దాచిన డొమైన్లు", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "అనుసరించడానికి అభ్యర్ధనలు", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "హోమ్", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "జాబితాలు", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "మ్యూట్ చేయబడిన వినియోగదారులు", "column.notifications": "ప్రకటనలు", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "సమాఖ్య కాలక్రమం", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "వెనక్కి", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "అమర్పులను దాచిపెట్టు", "column_header.show_settings": "అమర్పులను చూపించు", "community.column_settings.media_only": "మీడియా మాత్రమే", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "ఎన్నిక వ్యవధి", "compose_form.poll.option_placeholder": "ఎంపిక {number}", "compose_form.poll.remove_option": "ఈ ఎంపికను తొలగించు", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "టూట్", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "బ్లాక్ చేయి", "confirmations.block.message": "మీరు ఖచ్చితంగా {name}ని బ్లాక్ చేయాలనుకుంటున్నారా?", "confirmations.delete.confirm": "తొలగించు", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "మీరు ఖచ్చితంగా ఈ స్టేటస్ ని తొలగించాలనుకుంటున్నారా?", "confirmations.delete_list.confirm": "తొలగించు", "confirmations.delete_list.message": "మీరు ఖచ్చితంగా ఈ జాబితాను శాశ్వతంగా తొలగించాలనుకుంటున్నారా?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "అనుమతించు", "follow_request.reject": "తిరస్కరించు", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "మాస్టొడొన్ ఓపెన్ సోర్స్ సాఫ్ట్వేర్. మీరు {code_link} (v{code_version}) వద్ద GitLab పై సమస్యలను నివేదించవచ్చు లేదా తోడ్పడచ్చు.", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "మునుపటి", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "జాబితాకు జోడించు", "lists.account.remove": "జాబితా నుండి తొలగించు", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "ఈ వినియోగదారు నుండి నోటిఫికేషన్లను దాచాలా?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "కొత్త టూట్ను రాయండి", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "దాచిన డొమైన్లు", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "ఇష్టపడినవి", "navigation_bar.filters": "మ్యూట్ చేయబడిన పదాలు", "navigation_bar.follow_requests": "అనుసరించడానికి అభ్యర్ధనలు", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "ఈ సేవిక గురించి", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "హాట్ కీలు", "navigation_bar.lists": "Lists", "navigation_bar.logout": "లాగ్ అవుట్ చేయండి", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "మ్యూట్ చేయబడిన వినియోగదారులు", "navigation_bar.pins": "అతికించిన టూట్లు", "navigation_bar.preferences": "ప్రాధాన్యతలు", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "భద్రత", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "నవీకరించు", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "ఎన్నుకోండి", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "ఒక ఎన్నికను చేర్చు", "poll_button.remove_poll": "ఎన్నికను తొలగించు", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "లోడ్ అవుతోంది…", "regeneration_indicator.sublabel": "మీ హోమ్ ఫీడ్ సిద్ధమవుతోంది!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "ఇప్పుడు", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "రద్దు చెయ్యి", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "{target}కి ఫార్వార్డ్ చేయండి", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "శోధన", - "search_popout.search_format": "అధునాతన శోధన ఆకృతి", - "search_popout.tips.full_text": "సాధారణ వచనం మీరు వ్రాసిన, ఇష్టపడే, పెంచబడిన లేదా పేర్కొనబడిన, అలాగే యూజర్పేర్లు, ప్రదర్శన పేర్లు, మరియు హ్యాష్ట్యాగ్లను నమోదు చేసిన హోదాలను అందిస్తుంది.", - "search_popout.tips.hashtag": "హాష్ ట్యాగ్", - "search_popout.tips.status": "స్టేటస్", - "search_popout.tips.user": "వాడుకరి", "search_results.accounts": "వ్యక్తులు", "search_results.hashtags": "హాష్ ట్యాగ్లు", "search_results.statuses": "టూట్లు", diff --git a/app/soapbox/locales/th.json b/app/soapbox/locales/th.json index c3efe2363..0d1ff6407 100644 --- a/app/soapbox/locales/th.json +++ b/app/soapbox/locales/th.json @@ -8,6 +8,7 @@ "account.block_domain": "ซ่อนทุกอย่างจาก {domain}", "account.blocked": "ปิดกั้นอยู่", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "ผู้ใช้นี้ยังไม่ได้ติดตามใคร", "account.follows_you": "ติดตามคุณ", "account.hide_reblogs": "ซ่อนการดันจาก @{name}", + "account.last_status": "Last active", "account.link_verified_on": "ตรวจสอบความเป็นเจ้าของของลิงก์นี้เมื่อ {date}", "account.locked_info": "มีการตั้งสถานะความเป็นส่วนตัวของบัญชีนี้เป็นล็อคอยู่ เจ้าของตรวจทานผู้ที่สามารถติดตามเขาด้วยตนเอง", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} ได้ย้ายไปยัง:", "account.mute": "ปิดเสียง @{name}", "account.muted": "ปิดเสียงอยู่", + "account.never_active": "Never", "account.posts": "โพสต์", "account.posts_with_replies": "โพสต์และการตอบกลับ", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "ปิด", "bundle_modal_error.message": "มีบางอย่างผิดพลาดขณะโหลดส่วนประกอบนี้", "bundle_modal_error.retry": "ลองอีกครั้ง", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "ผู้ใช้ที่ปิดกั้นอยู่", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "เส้นเวลาในเว็บ", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "ข้อความโดยตรง", + "column.directory": "Browse profiles", "column.domain_blocks": "โดเมนที่ซ่อนอยู่", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "คำขอติดตาม", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "หน้าแรก", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "รายการ", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "ผู้ใช้ที่ปิดเสียงอยู่", "column.notifications": "การแจ้งเตือน", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "เส้นเวลาที่ติดต่อกับภายนอก", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "ย้อนกลับ", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "ซ่อนการตั้งค่า", "column_header.show_settings": "แสดงการตั้งค่า", "community.column_settings.media_only": "สื่อเท่านั้น", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "ระยะเวลาโพล", "compose_form.poll.option_placeholder": "ทางเลือก {number}", "compose_form.poll.remove_option": "เอาทางเลือกนี้ออก", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "โพสต์", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "ปิดกั้นแล้วรายงาน", "confirmations.block.confirm": "ปิดกั้น", "confirmations.block.message": "คุณแน่ใจหรือไม่ว่าต้องการปิดกั้น {name}?", "confirmations.delete.confirm": "ลบ", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "คุณแน่ใจหรือไม่ว่าต้องการลบสถานะนี้?", "confirmations.delete_list.confirm": "ลบ", "confirmations.delete_list.message": "คุณแน่ใจหรือไม่ว่าต้องการลบรายการนี้อย่างถาวร?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "อนุญาต", "follow_request.reject": "ปฏิเสธ", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} เป็นซอฟต์แวร์เปิดต้นฉบับ คุณสามารถมีส่วนร่วมหรือรายงานปัญหาที่ GitLab ที่ {code_link} (v{code_version})", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "ก่อนหน้า", "lightbox.view_context": "ดูบริบท", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "เพิ่มไปยังรายการ", "lists.account.remove": "เอาออกจากรายการ", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "ซ่อนการแจ้งเตือนจากผู้ใช้นี้?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "เขียนโพสต์ใหม่", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "โดเมนที่ซ่อนอยู่", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "รายการโปรด", "navigation_bar.filters": "คำที่ปิดเสียงอยู่", "navigation_bar.follow_requests": "คำขอติดตาม", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "เกี่ยวกับเซิร์ฟเวอร์นี้", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "ปุ่มลัด", "navigation_bar.lists": "Lists", "navigation_bar.logout": "ออกจากระบบ", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "ผู้ใช้ที่ปิดเสียงอยู่", "navigation_bar.pins": "โพสต์ที่ปักหมุด", "navigation_bar.preferences": "การกำหนดลักษณะ", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "ความปลอดภัย", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "รีเฟรช", "poll.total_votes": "{count, plural, other {# การลงคะแนน}}", "poll.vote": "ลงคะแนน", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "เพิ่มโพล", "poll_button.remove_poll": "เอาโพลออก", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "กำลังโหลด…", "regeneration_indicator.sublabel": "กำลังเตรียมฟีดหน้าแรกของคุณ!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} วัน", "relative_time.hours": "{number} ชั่วโมง", "relative_time.just_now": "ตอนนี้", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "ยกเลิก", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "ส่งต่อไปยัง {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "ค้นหา", - "search_popout.search_format": "รูปแบบการค้นหาขั้นสูง", - "search_popout.tips.full_text": "ข้อความแบบง่ายส่งคืนสถานะที่คุณได้เขียน ชื่นชอบ ดัน หรือได้รับการกล่าวถึง ตลอดจนชื่อผู้ใช้, ชื่อที่แสดง และแฮชแท็กที่ตรงกัน", - "search_popout.tips.hashtag": "แฮชแท็ก", - "search_popout.tips.status": "สถานะ", - "search_popout.tips.user": "ผู้ใช้", "search_results.accounts": "ผู้คน", "search_results.hashtags": "แฮชแท็ก", "search_results.statuses": "โพสต์", diff --git a/app/soapbox/locales/tr.json b/app/soapbox/locales/tr.json index ca5957a66..12eb21c09 100644 --- a/app/soapbox/locales/tr.json +++ b/app/soapbox/locales/tr.json @@ -8,6 +8,7 @@ "account.block_domain": "{domain} alanından her şeyi gizle", "account.blocked": "Engellenmiş", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Bu kullanıcı henüz kimseyi takip etmiyor.", "account.follows_you": "Seni takip ediyor", "account.hide_reblogs": "@{name} kişisinin yinelemelerini gizle", + "account.last_status": "Last active", "account.link_verified_on": "Bu bağlantının mülkiyeti {date} tarihinde kontrol edildi", "account.locked_info": "Bu hesabın gizlilik durumu kilitli olarak ayarlanmış. Sahibi, onu kimin takip edebileceğini elle inceliyor.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} şuraya taşındı:", "account.mute": "@{name} adlı kişiyi sessize al", "account.muted": "Susturuldu", + "account.never_active": "Never", "account.posts": "Gönderi", "account.posts_with_replies": "Gönderiler ve yanıtlar", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Kapat", "bundle_modal_error.message": "Bu bileşen yüklenirken bir şeyler ters gitti.", "bundle_modal_error.retry": "Tekrar deneyin", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Engellenen kullanıcılar", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Yerel zaman tüneli", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Doğrudan mesajlar", + "column.directory": "Browse profiles", "column.domain_blocks": "Gizli alan adları", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Takip istekleri", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Anasayfa", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Listeler", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Susturulmuş kullanıcılar", "column.notifications": "Bildirimler", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Federe zaman tüneli", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Geri", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Ayarları gizle", "column_header.show_settings": "Ayarları göster", "community.column_settings.media_only": "Sadece medya", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Anket süresi", "compose_form.poll.option_placeholder": "Seçim {number}", "compose_form.poll.remove_option": "Bu seçimi kaldır", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Gönder", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Engelle & Bildir", "confirmations.block.confirm": "Engelle", "confirmations.block.message": "{name} kullanıcısını engellemek istiyor musunuz?", "confirmations.delete.confirm": "Sil", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Bu gönderiyi silmek istiyor musunuz?", "confirmations.delete_list.confirm": "Sil", "confirmations.delete_list.message": "Bu listeyi kalıcı olarak silmek istediğinize emin misiniz?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Yetkilendir", "follow_request.reject": "Reddet", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} açık kaynaklı bir yazılımdır. Gitlab {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Önceli", "lightbox.view_context": "İçeriği göster", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Listeye ekle", "lists.account.remove": "Listeden kaldır", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Bu kullanıcıdan bildirimler gizlensin mı?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Yeni bir gönderi yazın", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Gizli alan adları", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Favoriler", "navigation_bar.filters": "Susturulmuş kelimeler", "navigation_bar.follow_requests": "Takip istekleri", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Genişletilmiş bilgi", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Klavye kısayolları", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Çıkış", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Sessize alınmış kullanıcılar", "navigation_bar.pins": "Sabitlenmiş gönderiler", "navigation_bar.preferences": "Tercihler", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Güvenlik", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Yenile", "poll.total_votes": "{count, plural, one {# oy} other {# oy}}", "poll.vote": "Oy ver", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Bir anket ekleyin", "poll_button.remove_poll": "Anket kaldır", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Yükleniyor…", "regeneration_indicator.sublabel": "Ev akışınız hazırlanıyor!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}g", "relative_time.hours": "{number}s", "relative_time.just_now": "şimdi", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "İptal", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Şu kişiye ilet : {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Ara", - "search_popout.search_format": "Gelişmiş arama formatı", - "search_popout.tips.full_text": "Basit metin yazdığınız, tercih ettiğiniz, yinelediğiniz veya bunlardan bahsettiğiniz durumların yanı sıra kullanıcı adlarını, görünen adları ve hashtag'leri eşleştiren durumları döndürür.", - "search_popout.tips.hashtag": "etiketler", - "search_popout.tips.status": "durum", - "search_popout.tips.user": "kullanıcı", "search_results.accounts": "İnsanlar", "search_results.hashtags": "Hashtagler", "search_results.statuses": "Gönderiler", diff --git a/app/soapbox/locales/uk.json b/app/soapbox/locales/uk.json index b80de4a57..47b914491 100644 --- a/app/soapbox/locales/uk.json +++ b/app/soapbox/locales/uk.json @@ -8,6 +8,7 @@ "account.block_domain": "Заглушити {domain}", "account.blocked": "Заблоковані", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "Цей користувач ще ні на кого не підписався.", "account.follows_you": "Підписаний(-а) на Вас", "account.hide_reblogs": "Сховати передмухи від @{name}", + "account.last_status": "Last active", "account.link_verified_on": "Права власності на це посилання були перевірені {date}", "account.locked_info": "Статус конфіденційності цього облікового запису встановлено у заблокований. Власник вручну переглядає, хто може за ним стежити.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} переїхав на:", "account.mute": "Заглушити @{name}", "account.muted": "Заглушений", + "account.never_active": "Never", "account.posts": "Дмухи", "account.posts_with_replies": "Дмухи й відповіді", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "Закрити", "bundle_modal_error.message": "Щось пішло не так під час завантаження компоненту.", "bundle_modal_error.retry": "Спробувати ще раз", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "Заблоковані користувачі", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "Локальна стрічка", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "Прямі повідомлення", + "column.directory": "Browse profiles", "column.domain_blocks": "Приховані домени", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "Запити на підписку", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "Головна", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "Списки", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "Заглушені користувачі", "column.notifications": "Сповіщення", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "Глобальна стрічка", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "Назад", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "Приховати налаштування", "column_header.show_settings": "Показати налаштування", "community.column_settings.media_only": "Тільки медіа", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Тривалість опитування", "compose_form.poll.option_placeholder": "Варіант {number}", "compose_form.poll.remove_option": "Видалити цей варіант", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "Дмухнути", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Заблокувати та поскаржитися", "confirmations.block.confirm": "Заблокувати", "confirmations.block.message": "Ви впевнені, що хочете заблокувати {name}?", "confirmations.delete.confirm": "Видалити", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "Ви впевнені, що хочете видалити цей допис?", "confirmations.delete_list.confirm": "Видалити", "confirmations.delete_list.message": "Ви впевнені, що хочете видалити цей список назавжди?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "Авторизувати", "follow_request.reject": "Відмовити", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} — програма з відкритим сирцевим кодом. Ви можете допомогти проекту, або повідомити про проблеми на GitLab за адресою {code_link} (v{code_version}).", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "Назад", "lightbox.view_context": "Переглянути контекст", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "Додати до списку", "lists.account.remove": "Видалити зі списку", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "Приховати сповіщення від користувача?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Написати новий дмух", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "Приховані домени", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "Вподобане", "navigation_bar.filters": "Приховані слова", "navigation_bar.follow_requests": "Запити на підписку", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "Про сайт", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "Гарячі клавіші", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Вийти", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "Заглушені користувачі", "navigation_bar.pins": "Закріплені дмухи", "navigation_bar.preferences": "Налаштування", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "Безпека", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Оновити", "poll.total_votes": "{count, plural, one {# голос} few {# голоси} many {# голосів} other {# голосів}}", "poll.vote": "Проголосувати", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Додати опитування", "poll_button.remove_poll": "Видалити опитування", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "Завантаження…", "regeneration_indicator.sublabel": "Ваша домашня стрічка готується!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}д", "relative_time.hours": "{number}г", "relative_time.just_now": "щойно", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "Відмінити", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "Надіслати до {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "Пошук", - "search_popout.search_format": "Розширений формат пошуку", - "search_popout.tips.full_text": "Пошук за текстом знаходить статуси, які ви написали, вподобали, передмухнули, або в яких вас згадували. Також він знаходить імена користувачів, реальні імена та хештеґи.", - "search_popout.tips.hashtag": "хештеґ", - "search_popout.tips.status": "статус", - "search_popout.tips.user": "користувач", "search_results.accounts": "Люди", "search_results.hashtags": "Хештеґи", "search_results.statuses": "Дмухів", diff --git a/app/soapbox/locales/zh-CN.json b/app/soapbox/locales/zh-CN.json index adeab0bec..86e92a1c4 100644 --- a/app/soapbox/locales/zh-CN.json +++ b/app/soapbox/locales/zh-CN.json @@ -1,5 +1,5 @@ { - "about.also_available": "Available in:", + "about.also_available": "其它版本:", "accordion.collapse": "折叠", "accordion.expand": "展开", "account.add_or_remove_from_list": "从列表中添加或删除", @@ -7,10 +7,11 @@ "account.block": "屏蔽 @{name}", "account.block_domain": "隐藏来自 {domain} 的内容", "account.blocked": "已屏蔽。", - "account.chat": "Chat with @{name}", - "account.column_settings.title": "Acccount timeline settings", - "account.deactivated": "账号被禁用", - "account.deactivated_description": "该账号已被禁用。", + "account.chat": "与 @{name} 聊天", + "account.column_settings.description": "These settings apply to all account timelines.", + "account.column_settings.title": "Account timeline settings", + "account.deactivated": "帐号被禁用", + "account.deactivated_description": "该帐号已被禁用。", "account.direct": "发送私信给 @{name}", "account.domain_blocked": "站点已屏蔽", "account.edit_profile": "修改个人资料", @@ -21,9 +22,10 @@ "account.follows": "正在关注", "account.follows.empty": "此用户目前尚未关注任何人。", "account.follows_you": "关注了你", - "account.hide_reblogs": "隐藏来自 @{name} 的转嘟", + "account.hide_reblogs": "隐藏来自 @{name} 的转发", + "account.last_status": "Last active", "account.link_verified_on": "此链接的所有权已在 {date} 被检查", - "account.locked_info": "此账号已锁嘟。账号的主人会手动审核关注者。", + "account.locked_info": "此帐号已上锁。帐号的主人会手动审核关注者。", "account.login": "登录", "account.media": "媒体", "account.member_since": "加入于 {date}", @@ -31,8 +33,9 @@ "account.moved_to": "{name} 已经迁移到:", "account.mute": "隐藏 @{name}", "account.muted": "已隐藏", - "account.posts": "嘟文", - "account.posts_with_replies": "嘟文和回复", + "account.never_active": "Never", + "account.posts": "帖文", + "account.posts_with_replies": "帖文和回复", "account.profile": "个人资料", "account.register": "注册", "account.remote_follow": "取消关注", @@ -40,18 +43,18 @@ "account.requested": "正在等待对方同意。点击以取消发送关注请求。", "account.requested_small": "等待同意", "account.share": "分享 @{name} 的个人资料", - "account.show_reblogs": "显示来自 @{name} 的转嘟", - "account.subscribe": "Subscribe to notifications from @{name}", - "account.subscribed": "Subscribed", + "account.show_reblogs": "显示来自 @{name} 的转发", + "account.subscribe": "订阅 @{name}", + "account.subscribed": "已订阅", "account.unblock": "解除屏蔽 @{name}", "account.unblock_domain": "不再隐藏来自 {domain} 的内容", "account.unendorse": "不在个人资料中推荐此用户", "account.unfollow": "取消关注", "account.unmute": "不再隐藏 @{name}", - "account.unsubscribe": "Unsubscribe to notifications from @{name}", + "account.unsubscribe": "取消订阅 @{name}", "account_gallery.none": "没有内容", - "account_search.placeholder": "Search for an account", - "account_timeline.column_settings.show_pinned": "Show pinned posts", + "account_search.placeholder": "搜索帐号", + "account_timeline.column_settings.show_pinned": "显示置顶", "admin.awaiting_approval.approved_message": "{acct} 的注册申请已通过!", "admin.awaiting_approval.empty_message": "没有未处理的举报,如果有新的举报,它就会显示在这里。", "admin.awaiting_approval.rejected_message": "{acct} 的注册请求被拒绝。", @@ -63,62 +66,77 @@ "admin.dashboard.registration_mode.open_label": "公开", "admin.dashboard.registration_mode_label": "注册模式", "admin.dashboard.settings_saved": "设定已保存!", - "admin.dashcounters.domain_count_label": "有联系的站点", - "admin.dashcounters.mau_label": "monthly active users", - "admin.dashcounters.retention_label": "user retention", - "admin.dashcounters.status_count_label": "总嘟文数", + "admin.dashcounters.domain_count_label": "互联站点", + "admin.dashcounters.mau_label": "月度活跃用户", + "admin.dashcounters.retention_label": "用户留存", + "admin.dashcounters.status_count_label": "总帖文数", "admin.dashcounters.user_count_label": "总用户数", - "admin.dashwidgets.email_list_header": "Email list", + "admin.dashwidgets.email_list_header": "邮件列表", "admin.dashwidgets.software_header": "软件版本", - "admin.latest_accounts_panel.expand_message": "Click to see {count} more {count, plural, one {account} other {accounts}}", - "admin.latest_accounts_panel.title": "Latest Accounts", + "admin.latest_accounts_panel.expand_message": "点击查看更多帐号", + "admin.latest_accounts_panel.title": "最近帐号", "admin.moderation_log.empty_message": "没有管理记录,如果你进行管理,历史记录就会显示在这里。", "admin.reports.actions.close": "关闭举报", - "admin.reports.actions.view_status": "查看嘟文", + "admin.reports.actions.view_status": "查看帖文", "admin.reports.empty_message": "没有未处理的举报,如果有新的举报,它就会显示在这里。", "admin.reports.report_closed_message": "对@{name} 的举报已关闭", - "admin.reports.report_title": "举报 {acct} 的嘟文", - "admin.statuses.actions.delete_status": "删除嘟文", - "admin.statuses.actions.mark_status_not_sensitive": "不再标记为敏感嘟文", - "admin.statuses.actions.mark_status_sensitive": "标记为敏感嘟文", - "admin.statuses.status_deleted_message": " @{acct} 的嘟文被删除", - "admin.statuses.status_marked_message_not_sensitive": "@{acct} 的嘟文不再被标记敏感。", - "admin.statuses.status_marked_message_sensitive": "Post by @{acct} 的嘟文被标记敏感。", - "admin.user_index.empty": "No users found.", - "admin.user_index.search_input_placeholder": "Who are you looking for?", - "admin.users.actions.deactivate_user": "禁用账号 @{name}", - "admin.users.actions.delete_user": "删除账号 @{name}", - "admin.users.actions.demote_to_moderator": "Demote @{name} to a moderator", - "admin.users.actions.demote_to_moderator_message": "@{acct} was demoted to a moderator", - "admin.users.actions.demote_to_user": "Demote @{name} to a regular user", - "admin.users.actions.demote_to_user_message": "@{acct} was demoted to a regular user", - "admin.users.actions.promote_to_admin": "Promote @{name} to an admin", - "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", - "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", - "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.reports.report_title": "举报 {acct} 的帖文", + "admin.statuses.actions.delete_status": "删除帖文", + "admin.statuses.actions.mark_status_not_sensitive": "不再标记为敏感", + "admin.statuses.actions.mark_status_sensitive": "标记为敏感", + "admin.statuses.status_deleted_message": " @{acct} 的帖文被删除", + "admin.statuses.status_marked_message_not_sensitive": "@{acct} 的帖文不再被标记敏感。", + "admin.statuses.status_marked_message_sensitive": "@{acct} 的帖文被标记敏感。", + "admin.user_index.empty": "未找到用户", + "admin.user_index.search_input_placeholder": "搜索哪位用户?", + "admin.users.actions.deactivate_user": "禁用帐号 @{name}", + "admin.users.actions.delete_user": "删除帐号 @{name}", + "admin.users.actions.demote_to_moderator": "降级 @{name} 为站务", + "admin.users.actions.demote_to_moderator_message": "@{acct} 已被降级为站务", + "admin.users.actions.demote_to_user": "降级 @{name} 为普通用户", + "admin.users.actions.demote_to_user_message": "@{acct} 已被降级为普通用户", + "admin.users.actions.promote_to_admin": "升级 @{name} 为站长", + "admin.users.actions.promote_to_admin_message": "@{acct} 已被升级为站长", + "admin.users.actions.promote_to_moderator": "升级 @{name} 为站务", + "admin.users.actions.promote_to_moderator_message": "@{acct} 已被升级为站务", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "取消认证 @{name}", - "admin.users.actions.verify_user": "认证账号 @{name}", + "admin.users.actions.verify_user": "认证帐号 @{name}", "admin.users.user_deactivated_message": "@{acct} 被禁用。", "admin.users.user_deleted_message": "@{acct} 被删除。", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} 被取消认证。", "admin.users.user_verified_message": "@{acct} 被认证。", "admin_nav.awaiting_approval": "等待同意", - "admin_nav.dashboard": "仪表盘", + "admin_nav.dashboard": "管理中心", "admin_nav.reports": "举报", - "alert.unexpected.clear_cookies": "clear cookies and browser data", - "alert.unexpected.help_text": "If the problem persists, please notify a site admin with a screenshot and information about your web browser. You may also {clear_cookies} (this will log you out).", + "alert.unexpected.clear_cookies": "清除cookie和浏览器数据", + "alert.unexpected.help_text": "如果问题仍然存在,请联系站长,附带截屏与浏览器版本信息。你也可以尝试登出,{clear_cookies}。", "alert.unexpected.message": "发生了意外错误。", - "alert.unexpected.return_home": "Return Home", + "alert.unexpected.return_home": "回到首页", "alert.unexpected.title": "哎呀!", - "aliases.account.add": "Create alias", - "aliases.account_label": "Old account:", - "aliases.aliases_list_delete": "Unlink alias", - "aliases.search": "Search your old account", - "aliases.success.add": "Account alias created successfully", - "aliases.success.remove": "Account alias removed successfully", - "auth.invalid_credentials": "Wrong username or password", - "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", + "aliases.account.add": "创建别名", + "aliases.account_label": "旧帐号:", + "aliases.aliases_list_delete": "删除别名", + "aliases.search": "搜索旧帐号", + "aliases.success.add": "帐号别名创建成功", + "aliases.success.remove": "帐号别名删除成功", + "app_create.name_label": "应用别名", + "app_create.name_placeholder": "例如 'Soapbox'", + "app_create.redirect_uri_label": "重定向网址", + "app_create.restart": "创建另一个", + "app_create.results.app_label": "应用", + "app_create.results.explanation_text": "你已创建一个新应用及其令牌,请复制密钥等信息,离开本页面后这些信息将不再展示。", + "app_create.results.explanation_title": "应用创建成功", + "app_create.results.token_label": "OAuth令牌", + "app_create.scopes_label": "权限范围", + "app_create.scopes_placeholder": "例如'read write follow'", + "app_create.submit": "创建应用", + "app_create.website_label": "网站", + "auth.invalid_credentials": "用户名或密码错误", + "auth.logged_out": "已登出。", "backups.actions.create": "创建备份", "backups.empty_message": "没有找到备份 {action}。", "backups.empty_message.action": "现在要备份吗?", @@ -130,105 +148,122 @@ "bundle_modal_error.close": "关闭", "bundle_modal_error.message": "载入组件时发生错误。", "bundle_modal_error.retry": "重试", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "发送", - "chat_box.input.placeholder": "发送私聊", - "chat_panels.main_window.empty": "还没有私聊,找人聊聊吧!", - "chat_panels.main_window.title": "私聊", + "chat_box.input.placeholder": "发送聊天信息", + "chat_panels.main_window.empty": "还没有聊天信息,找人聊聊吧!", + "chat_panels.main_window.title": "聊天", "chats.actions.delete": "删除", "chats.actions.more": "更多选项", "chats.actions.report": "举报用户", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "关闭声音提醒", "chats.audio_toggle_on": "打开声音提醒", "chats.dividers.today": "此刻", - "chats.search_placeholder": "Start a chat with…", + "chats.search_placeholder": "开始聊天……", "column.admin.awaiting_approval": "等待批准", - "column.admin.dashboard": "仪表盘", + "column.admin.dashboard": "管理中心", "column.admin.moderation_log": "管理记录", "column.admin.reports": "举报", "column.admin.reports.menu.moderation_log": "管理记录", - "column.aliases": "Account aliases", - "column.aliases.create_error": "Error creating alias", - "column.aliases.delete": "Delete", - "column.aliases.delete_error": "Error deleting alias", - "column.aliases.subheading_add_new": "Add New Alias", - "column.aliases.subheading_aliases": "Current aliases", + "column.admin.users": "Users", + "column.aliases": "帐号别名", + "column.aliases.create_error": "创建别名出错", + "column.aliases.delete": "删除", + "column.aliases.delete_error": "删除别名出错", + "column.aliases.subheading_add_new": "新增别名", + "column.aliases.subheading_aliases": "当前别名", + "column.app_create": "创建应用", "column.backups": "备份", "column.blocks": "已屏蔽的用户", "column.bookmarks": "书签", - "column.chats": "私聊", + "column.chats": "聊天", "column.community": "本站时间轴", - "column.crypto_donate": "Donate Cryptocurrency", + "column.crypto_donate": "加密货币捐款", + "column.developers": "开发者", "column.direct": "私信", + "column.directory": "Browse profiles", "column.domain_blocks": "已屏蔽的站点", "column.edit_profile": "编辑个人资料", - "column.export_data": "Export data", - "column.favourites": "Likes", - "column.federation_restrictions": "Federation Restrictions", - "column.filters": "屏蔽词", - "column.filters.add_new": "添加新的屏蔽词", + "column.export_data": "导出数据", + "column.favourited_statuses": "Liked posts", + "column.favourites": "点赞", + "column.federation_restrictions": "联邦限制", + "column.filters": "过滤词", + "column.filters.add_new": "添加新的过滤词", "column.filters.conversations": "对话", - "column.filters.create_error": "添加屏蔽词时出错。", - "column.filters.delete": "删除屏蔽词", - "column.filters.delete_error": "删除屏蔽词时出错。", + "column.filters.create_error": "添加过滤词时出错。", + "column.filters.delete": "删除过滤词", + "column.filters.delete_error": "删除过滤词时出错。", "column.filters.drop_header": "丢弃而非隐藏", - "column.filters.drop_hint": "已屏蔽的嘟文会不可逆转地消失,即便移除屏蔽词之后也一样。", + "column.filters.drop_hint": "被丢弃的帖文会不可逆转地消失,即便移除过滤词之后也一样。", "column.filters.expires": "失效时间", "column.filters.expires_hint": "还未支持失效时间。", "column.filters.home_timeline": "本站时间轴", "column.filters.keyword": "关键词", "column.filters.notifications": "通知", "column.filters.public_timeline": "公共时间轴", - "column.filters.subheading_add_new": "添加新的屏蔽词", - "column.filters.subheading_filters": "查看已有屏蔽词", + "column.filters.subheading_add_new": "添加新的过滤词", + "column.filters.subheading_filters": "查看已有过滤词", "column.filters.whole_word_header": "整个词条", "column.filters.whole_word_hint": "如果关键词只包含字母和数字,将只在词语完全匹配时才会应用。", "column.follow_requests": "关注请求", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "列表", "column.home": "主页", - "column.import_data": "导入备份", + "column.import_data": "导入数据", "column.info": "站点信息", "column.lists": "列表", + "column.mentions": "Mentions", "column.mfa": "双重认证", "column.mfa_cancel": "取消", "column.mfa_confirm_button": "确定", "column.mfa_disable_button": "关闭", "column.mfa_setup": "同意并继续", - "column.mutes": "已隐藏的用户", + "column.mutes": "已静音的用户", "column.notifications": "通知", + "column.pins": "Pinned posts", "column.preferences": "选项", + "column.profile_directory": "Profile directory", "column.public": "跨站公共时间轴", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "跨站公共时间轴", - "column.scheduled_statuses": "Scheduled Posts", - "column.search": "Search", + "column.scheduled_statuses": "定时帖文", + "column.search": "搜索", "column.security": "安全", "column.soapbox_config": "Soapbox设置", "column_back_button.label": "返回", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "隐藏设置", "column_header.show_settings": "显示设置", "community.column_settings.media_only": "仅媒体", - "community.column_settings.title": "Local timeline settings", - "compose.character_counter.title": "Used {chars} out of {maxChars} characters", - "compose.invalid_schedule": "You must schedule a post at least 5 minutes out.", - "compose.submit_success": "Your post was sent", - "compose_form.direct_message_warning": "这条嘟文仅对所有被提及的用户可见。", - "compose_form.hashtag_warning": "这条嘟文被设置为“不公开”,因此它不会出现在任何话题标签的列表下。只有公开的嘟文才能通过话题标签进行搜索。", - "compose_form.lock_disclaimer": "你的帐户没有 {locked} 。任何人都可以在关注你后立即查看仅关注者可见的嘟文。", + "community.column_settings.title": "本地时间线设置", + "compose.character_counter.title": "最大字符数: {maxChars}; 已使用 {chars}", + "compose.invalid_schedule": "定时帖文只能设置为五分钟后或更晚", + "compose.submit_success": "帖文已发送", + "compose_form.direct_message_warning": "这条帖文仅对所有被提及的用户可见。", + "compose_form.hashtag_warning": "这条帖文被设置为“不公开”,因此它不会出现在任何话题标签的列表下。只有公开的帖文才能通过话题标签进行搜索。", + "compose_form.lock_disclaimer": "你的帐号没有 {locked} 。任何人都可以在关注你后立即查看仅关注者可见的帖文。", "compose_form.lock_disclaimer.lock": "开启保护", "compose_form.markdown.marked": "Markdown已开启", "compose_form.markdown.unmarked": "Markdown已关闭", - "compose_form.message": "Message", + "compose_form.message": "私信", "compose_form.placeholder": "在想什么?", "compose_form.poll.add_option": "添加一个选项", "compose_form.poll.duration": "投票持续时间", "compose_form.poll.option_placeholder": "选项 {number}", "compose_form.poll.remove_option": "移除这个选项", - "compose_form.poll.type.hint": "点击选择单选或多选", - "compose_form.publish": "嘟嘟", + "compose_form.poll.switch_to_multiple": "投票改为多选", + "compose_form.poll.switch_to_single": "投票改为单选", + "compose_form.publish": "发布", "compose_form.publish_loud": "{publish}!", - "compose_form.schedule": "Schedule", - "compose_form.scheduled_statuses.click_here": "Click here", - "compose_form.scheduled_statuses.message": "You have scheduled posts. {click_here} to see them.", + "compose_form.schedule": "定时发布", + "compose_form.scheduled_statuses.click_here": "点击此处", + "compose_form.scheduled_statuses.message": "你有定时帖文,{click_here}查看。", "compose_form.sensitive.hide": "标记媒体为敏感内容", "compose_form.sensitive.marked": "媒体已被标记为敏感内容。", "compose_form.sensitive.unmarked": "媒体未被标记为敏感内容。", @@ -237,21 +272,24 @@ "compose_form.spoiler_placeholder": "折叠部分的警告消息", "confirmation_modal.cancel": "取消", "confirmations.admin.deactivate_user.confirm": "禁用 @{name}", - "confirmations.admin.deactivate_user.message": "你确定要禁用账号 @{acct} 吗?这无法撤回!", - "confirmations.admin.delete_local_user.checkbox": "我确定我要删除本站账号", - "confirmations.admin.delete_status.confirm": "删除嘟文", - "confirmations.admin.delete_status.message": "你确定要删除 @{acct} 的嘟文吗?这无法撤回!", - "confirmations.admin.delete_user.confirm": "删除账号 @{name}", - "confirmations.admin.delete_user.message": "你确定要删除本站账号 @{acct} 吗?这无法撤回!", - "confirmations.admin.mark_status_not_sensitive.confirm": "不再标记为敏感嘟文", - "confirmations.admin.mark_status_not_sensitive.message": "你要标记账号 @{acct} 的嘟文不再敏感", - "confirmations.admin.mark_status_sensitive.confirm": "标记为敏感嘟文", - "confirmations.admin.mark_status_sensitive.message": "你要标记账号 @{acct} 的嘟文为敏感", + "confirmations.admin.deactivate_user.message": "你确定要禁用帐号 @{acct} 吗?这无法撤回!", + "confirmations.admin.delete_local_user.checkbox": "我确定我要删除本站帐号", + "confirmations.admin.delete_status.confirm": "删除帖文", + "confirmations.admin.delete_status.message": "你确定要删除 @{acct} 的帖文吗?这无法撤回!", + "confirmations.admin.delete_user.confirm": "删除帐号 @{name}", + "confirmations.admin.delete_user.message": "你确定要删除本站帐号 @{acct} 吗?这无法撤回!", + "confirmations.admin.mark_status_not_sensitive.confirm": "不再标记为敏感帖文", + "confirmations.admin.mark_status_not_sensitive.message": "你要标记帐号 @{acct} 的帖文不再敏感", + "confirmations.admin.mark_status_sensitive.confirm": "标记为敏感帖文", + "confirmations.admin.mark_status_sensitive.message": "你要标记帐号 @{acct} 的帖文为敏感", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "屏蔽与举报", "confirmations.block.confirm": "屏蔽", "confirmations.block.message": "你确定要屏蔽 {name} 吗?", "confirmations.delete.confirm": "删除", - "confirmations.delete.message": "你确定要删除这条嘟文吗?", + "confirmations.delete.heading": "Delete post", + "confirmations.delete.message": "你确定要删除这条帖文吗?", "confirmations.delete_list.confirm": "删除", "confirmations.delete_list.message": "你确定要永久删除这个列表吗?", "confirmations.domain_block.confirm": "隐藏整个站点的内容", @@ -259,57 +297,65 @@ "confirmations.mute.confirm": "隐藏", "confirmations.mute.message": "你确定要隐藏 {name} 吗?", "confirmations.redraft.confirm": "删除并重新编辑", - "confirmations.redraft.message": "你确定要删除这条嘟文并重新编辑它吗?所有相关的转嘟和收藏都会被清除,回复将会失去关联。", - "confirmations.register.needs_approval": "你的账号在被管理员审核,请稍等", + "confirmations.redraft.message": "你确定要删除这条帖文并重新编辑它吗?所有相关的转发和点赞都会被清除,回复将会失去关联。", + "confirmations.register.needs_approval": "你的帐号在被管理员审核,请稍等", "confirmations.register.needs_confirmation": "请检查你的邮箱 {email} ,我们需要邮箱验证注册", "confirmations.reply.confirm": "回复", "confirmations.reply.message": "回复此消息将会覆盖当前正在编辑的信息。确定继续吗?", "confirmations.unfollow.confirm": "取消关注", "confirmations.unfollow.message": "你确定要取消关注 {name} 吗?", - "crypto_donate.explanation_box.message": "{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!", - "crypto_donate.explanation_box.title": "Sending cryptocurrency donations", - "crypto_donate_panel.actions.more": "Click to see {count} more {count, plural, one {wallet} other {wallets}}", - "crypto_donate_panel.heading": "Donate Cryptocurrency", - "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", - "datepicker.hint": "Scheduled to post at…", - "direct.search_placeholder": "Send a message to…", - "donate": "Donate", - "donate_crypto": "Donate cryptocurrency", - "edit_federation.followers_only": "Hide posts except to followers", - "edit_federation.force_nsfw": "Force attachments to be marked sensitive", - "edit_federation.media_removal": "Strip media", - "edit_federation.reject": "Reject all activities", - "edit_federation.save": "Save", - "edit_federation.success": "{host} federation was updated", - "edit_federation.unlisted": "Force posts unlisted", - "edit_profile.error": "Profile update failed", - "edit_profile.fields.accepts_email_list_label": "Subscribe to newsletter", + "crypto_donate.explanation_box.message": "{siteTitle} 接受用户向以下钱包地址捐赠任意数量的加密货币。感谢你的支持!", + "crypto_donate.explanation_box.title": "发送加密货币捐赠", + "crypto_donate_panel.actions.more": "点击查看 {count} 个 {count, plural, one {钱包} other {钱包}}", + "crypto_donate_panel.heading": "捐赠加密货币", + "crypto_donate_panel.intro.message": "{siteTitle} 接受用户捐赠加密货币。感谢你的支持!", + "datepicker.hint": "设定发送时间……", + "developers.navigation.app_create_label": "创建应用", + "developers.navigation.intentional_error_label": "触发一个错误", + "direct.search_placeholder": "发送私信给……", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", + "donate": "捐赠", + "donate_crypto": "捐赠加密货币", + "edit_federation.followers_only": "对关注者以外的用户隐藏帖文", + "edit_federation.force_nsfw": "将附件强制标记为敏感", + "edit_federation.media_removal": "去掉媒体", + "edit_federation.reject": "拒绝所有信息交互", + "edit_federation.save": "保存", + "edit_federation.success": "{host} 联邦设定已保存", + "edit_federation.unlisted": "将帖文强制标记为不公开", + "edit_profile.error": "个人资料更新失败", + "edit_profile.fields.accepts_email_list_label": "接收邮件列表", "edit_profile.fields.avatar_label": "头像", "edit_profile.fields.bio_label": "简介", - "edit_profile.fields.bio_placeholder": "Tell us about yourself.", - "edit_profile.fields.bot_label": "这是一个机器人帐户", + "edit_profile.fields.bio_placeholder": "请介绍一下你自己。", + "edit_profile.fields.bot_label": "这是一个机器人帐号", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "昵称", - "edit_profile.fields.display_name_placeholder": "Name", + "edit_profile.fields.display_name_placeholder": "你的昵称", "edit_profile.fields.header_label": "个人资料页横幅图片", - "edit_profile.fields.hide_network_label": "Hide network", - "edit_profile.fields.locked_label": "保护你的帐户(锁嘟)", + "edit_profile.fields.hide_network_label": "隐藏关注信息", + "edit_profile.fields.locked_label": "保护你的帐号", "edit_profile.fields.meta_fields.content_placeholder": "内容", "edit_profile.fields.meta_fields.label_placeholder": "标签", - "edit_profile.fields.meta_fields_label": "验证元数据", - "edit_profile.fields.stranger_notifications_label": "Block notifications from strangers", + "edit_profile.fields.meta_fields_label": "帐号元数据", + "edit_profile.fields.stranger_notifications_label": "不接收来自陌生人的通知", "edit_profile.fields.verified_display_name": "经过验证的用户不能更新他们的昵称", - "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", - "edit_profile.hints.avatar": "文件大小限制 2.0 MB,只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 400x400px。", - "edit_profile.hints.bot": "来自这个帐户的绝大多数操作都是自动进行的,并且可能无人监控。", - "edit_profile.hints.header": "文件大小限制 2.0 MB,只支持 PNG、GIF 或 JPG 格式。图片分辨率将会压缩至 1500x500px。", - "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", + "edit_profile.hints.accepts_email_list": "接收新闻和推广邮件", + "edit_profile.hints.avatar": "只支持 PNG、GIF 或 JPG 格式,大小不超过{size}。图片分辨率将会压缩至 1500x500px。", + "edit_profile.hints.bot": "来自这个帐号的绝大多数操作都是自动进行的,并且可能无人监控。", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", + "edit_profile.hints.header": "只支持 PNG、GIF 或 JPG 格式,大小不超过{size}。图片分辨率将会压缩至 1500x500px。", + "edit_profile.hints.hide_network": "个人资料中不显示你关注的用户和关注你的用户。", "edit_profile.hints.locked": "你需要手动审核所有关注请求。", - "edit_profile.hints.meta_fields": "你可以以表格形式展示 {count, plural, one {# 个项目} other {# 个项目}} 在你的个人资料页上。", - "edit_profile.hints.stranger_notifications": "Only show notifications from people you follow", - "edit_profile.meta_fields.add": "Add new item", + "edit_profile.hints.meta_fields": "你可以在个人资料页上以表格形式展示 {count, plural, one {# 项元数据} other {# 项元数据}} 。", + "edit_profile.hints.stranger_notifications": "只显示来自你所关注用户的通知。", + "edit_profile.meta_fields.add": "新增元数据", "edit_profile.save": "保存", - "edit_profile.success": "Profile saved!", - "embed.instructions": "要在你的站点上嵌入这条嘟文,请复制以下代码:", + "edit_profile.success": "个人资料已保存。", + "embed.instructions": "要在你的站点上嵌入这条帖文,请复制以下代码:", "embed.preview": "它会像这样显示出来:", "emoji_button.activity": "活动", "emoji_button.custom": "自定义", @@ -325,49 +371,49 @@ "emoji_button.search_results": "搜索结果", "emoji_button.symbols": "符号", "emoji_button.travel": "旅行和地点", - "empty_column.account_blocked": "You are blocked by @{accountUsername}.", - "empty_column.account_favourited_statuses": "This user doesn't have any liked posts yet.", - "empty_column.account_timeline": "这里没有嘟文!", + "empty_column.account_blocked": "你被 @{accountUsername} 屏蔽了。", + "empty_column.account_favourited_statuses": "没有点赞帖文", + "empty_column.account_timeline": "这里没有帖文!", "empty_column.account_unavailable": "个人资料不可用", - "empty_column.aliases": "You haven't created any account alias yet.", - "empty_column.aliases.suggestions": "There are no account suggestions available for the provided term.", + "empty_column.aliases": "尚未创建别名", + "empty_column.aliases.suggestions": "没有相匹配的帐号建议", "empty_column.blocks": "你目前没有屏蔽任何用户。", - "empty_column.bookmarks": "你还没有任何书签,一旦你将嘟文加入书签,它就会显示在这里", + "empty_column.bookmarks": "你还没有任何书签,一旦你将帖文加入书签,它就会显示在这里", "empty_column.community": "本站时间轴暂时没有内容,快写点什么让它动起来吧!", "empty_column.direct": "你还没有使用过私信。当你发出或者收到私信时,它会在这里显示。", "empty_column.domain_blocks": "目前没有被隐藏的站点。", - "empty_column.favourited_statuses": "你还没有收藏过任何嘟文。收藏过的嘟文会显示在这里。", - "empty_column.favourites": "没有人收藏过这条嘟文。如果有人收藏了,就会显示在这里。", - "empty_column.filters": "你还没有添加任何屏蔽词。", - "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.", + "empty_column.favourited_statuses": "你还没有点赞过任何帖文。点赞过的帖文会显示在这里。", + "empty_column.favourites": "没有人点赞过这条帖文。如果有人点赞了,就会显示在这里。", + "empty_column.filters": "你还没有添加任何过滤词。", + "empty_column.follow_recommendations": "似乎暂未有推荐信息,你可以尝试搜索用户或者浏览热门标签。", "empty_column.follow_requests": "你没有收到新的关注请求。收到了之后就会显示在这里。", - "empty_column.group": "此列表中暂时没有内容。列表中用户所发送的的新嘟文将会在这里显示。", + "empty_column.group": "此列表中暂时没有内容。列表中用户所发送的的新帖文将会在这里显示。", "empty_column.hashtag": "这个话题标签下暂时没有内容。", "empty_column.home": "你还没有关注任何用户。快看看 {public} ,向其他人问个好吧。", "empty_column.home.local_tab": " {site_title} 本站时间轴", - "empty_column.list": "这个列表中暂时没有内容。列表中用户所发送的的新嘟文将会在这里显示。", + "empty_column.list": "这个列表中暂时没有内容。列表中用户所发送的的新帖文将会在这里显示。", "empty_column.lists": "你还没有创建过列表。你创建的列表会在这里显示。", "empty_column.mutes": "你没有隐藏任何用户。", "empty_column.notifications": "你还没有收到过任何通知,快和其他用户互动吧。", - "empty_column.public": "这里什么都没有!写一些公开的嘟文,或者关注其他服务器的用户后,这里就会有嘟文出现了。", + "empty_column.public": "这里什么都没有!写一些公开的帖文,或者关注其他服务器的用户后,这里就会有帖文出现了。", "empty_column.remote": "这里什么都没有!关注本站或者其他站点的用户后,这里就会有用户出现了。", - "empty_column.scheduled_statuses": "You don't have any scheduled statuses yet. When you add one, it will show up here.", - "empty_column.search.accounts": "There are no people results for \"{term}\"", - "empty_column.search.hashtags": "There are no hashtags results for \"{term}\"", - "empty_column.search.statuses": "There are no posts results for \"{term}\"", - "export_data.actions.export": "Export", - "export_data.actions.export_blocks": "Export blocks", - "export_data.actions.export_follows": "Export follows", - "export_data.actions.export_mutes": "Export mutes", - "export_data.blocks_label": "Blocks", - "export_data.follows_label": "Follows", - "export_data.hints.blocks": "Get a CSV file containing a list of blocked accounts", - "export_data.hints.follows": "Get a CSV file containing a list of followed accounts", - "export_data.hints.mutes": "Get a CSV file containing a list of muted accounts", - "export_data.mutes_label": "Mutes", - "export_data.success.blocks": "Blocks exported successfully", - "export_data.success.followers": "Followers exported successfully", - "export_data.success.mutes": "Mutes exported successfully", + "empty_column.scheduled_statuses": "暂无定时帖文。当你发布定时帖文后,它们会显示在这里。", + "empty_column.search.accounts": "无帐号匹配 \"{term}\"", + "empty_column.search.hashtags": "无标签匹配 \"{term}\"", + "empty_column.search.statuses": "无帖文匹配 \"{term}\"", + "export_data.actions.export": "导出", + "export_data.actions.export_blocks": "导出屏蔽列表", + "export_data.actions.export_follows": "导出关注列表", + "export_data.actions.export_mutes": "导出静音列表", + "export_data.blocks_label": "屏蔽", + "export_data.follows_label": "关注", + "export_data.hints.blocks": "下载屏蔽列表CSV文件", + "export_data.hints.follows": "下载关注列表CSV文件", + "export_data.hints.mutes": "下载静音列表CSV文件", + "export_data.mutes_label": "静音", + "export_data.success.blocks": "屏蔽列表导出完毕", + "export_data.success.followers": "关注列表导出完毕", + "export_data.success.mutes": "静音列表导出完毕", "federation_restriction.federated_timeline_removal": "Fediverse timeline removal", "federation_restriction.followers_only": "Hidden except to followers", "federation_restriction.full_media_removal": "Full media removal", @@ -377,32 +423,34 @@ "federation_restrictions.explanation_box.message": "Normally servers on the Fediverse can communicate freely. {siteTitle} has imposed restrictions on the following servers.", "federation_restrictions.explanation_box.title": "Instance-specific policies", "federation_restrictions.not_disclosed_message": "{siteTitle} does not disclose federation restrictions through the API.", - "fediverse_tab.explanation_box.dismiss": "Don't show again", - "fediverse_tab.explanation_box.explanation": "{site_title} 是联邦宇宙的一部分, 一个由数个站点组成的社交网络。你在这里看到的嘟文来自其他站点。你可以自由地与他们打交道,或者屏蔽任何你不喜欢的站点。请注意第二个@符号后的完整用户名,以了解嘟文来自哪个站点。要想只看到 {site_title} 的嘟文,请访问 {local} 。", + "fediverse_tab.explanation_box.dismiss": "不再显示", + "fediverse_tab.explanation_box.explanation": "{site_title} 是联邦宇宙的一部分, 一个由数个站点组成的社交网络。你在这里看到的帖文来自其他站点。你可以自由地与他们打交道,或者屏蔽任何你不喜欢的站点。请注意第二个@符号后的完整用户名,以了解帖文来自哪个站点。要想只看到 {site_title} 的帖文,请访问 {local} 。", "fediverse_tab.explanation_box.title": "什么是联邦宇宙?", - "filters.added": "Filter added.", - "filters.context_header": "屏蔽词场景", - "filters.context_hint": "屏蔽词的应用场景", - "filters.filters_list_context_label": "屏蔽词场景:", - "filters.filters_list_delete": "删除屏蔽词", - "filters.filters_list_details_label": "屏蔽词设定:", + "filters.added": "过滤已添加", + "filters.context_header": "过滤词场景", + "filters.context_hint": "过滤词的应用场景", + "filters.filters_list_context_label": "过滤词场景:", + "filters.filters_list_delete": "删除过滤词", + "filters.filters_list_details_label": "过滤词设定:", "filters.filters_list_drop": "丢弃", "filters.filters_list_hide": "隐藏", "filters.filters_list_phrase_label": "关键词:", "filters.filters_list_whole-word": "整个词条", - "filters.removed": "Filter deleted.", - "follow_recommendations.done": "Done", + "filters.removed": "过滤已移除", + "follow_recommendations.done": "完成", "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.", "follow_recommendations.lead": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!", "follow_request.authorize": "同意", "follow_request.reject": "拒绝", - "forms.copy": "Copy", + "forms.copy": "复制", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} 是开源软件。欢迎前往 GitLab({code_link} (v{code_version}))贡献代码或反馈问题。", "group.detail.archived_group": "Archived group", - "group.members.empty": "这个列表没有任何账号。", - "group.removed_accounts.empty": "这个列表没有被移除的账号", + "group.members.empty": "这个列表没有任何帐号。", + "group.removed_accounts.empty": "这个列表没有被移除的帐号", "groups.card.join": "加入", - "groups.card.members": "Members", + "groups.card.members": "成员", "groups.card.roles.admin": "You're an admin", "groups.card.roles.member": "You're a member", "groups.card.view": "查看", @@ -417,14 +465,14 @@ "groups.form.update": "更新列表", "groups.join": "Join group", "groups.leave": "Leave group", - "groups.removed_accounts": "已移除账号", + "groups.removed_accounts": "已移除帐号", "groups.sidebar-panel.item.no_recent_activity": "No recent activity", "groups.sidebar-panel.item.view": "new posts", "groups.sidebar-panel.show_all": "Show all", "groups.sidebar-panel.title": "Groups You're In", "groups.tab_admin": "管理", "groups.tab_featured": "热门", - "groups.tab_member": "Member", + "groups.tab_member": "成员", "hashtag.column_header.tag_mode.all": "以及 {additional}", "hashtag.column_header.tag_mode.any": "或是 {additional}", "hashtag.column_header.tag_mode.none": "而不用 {additional}", @@ -433,34 +481,34 @@ "header.home.label": "主页", "header.login.label": "登录", "home.column_settings.show_direct": "显示私信", - "home.column_settings.show_reblogs": "显示转嘟", + "home.column_settings.show_reblogs": "显示转发", "home.column_settings.show_replies": "显示回复", "home.column_settings.title": "Home settings", "home_column.lists": "列表", - "home_column_header.all": "All", + "home_column_header.all": "全部", "home_column_header.fediverse": "联邦宇宙", "home_column_header.home": "主页", "icon_button.icons": "图标", "icon_button.label": "选择图标", "icon_button.not_found": "没有图标! (╯°□°)╯︵ ┻━┻", "import_data.actions.import": "导入", - "import_data.actions.import_blocks": "导入已屏蔽账号", - "import_data.actions.import_follows": "导入已关注账号", - "import_data.actions.import_mutes": "导入已静音账号", - "import_data.blocks_label": "已屏蔽账号", - "import_data.follows_label": "已关注账号", - "import_data.hints.blocks": "请上传包含已屏蔽账号的CSV文件。", - "import_data.hints.follows": "请上传包含已关注账号的CSV文件。", - "import_data.hints.mutes": "请上传包含已静音账号的CSV文件。", - "import_data.mutes_label": "已静音账号", - "import_data.success.blocks": "Blocks imported successfully", - "import_data.success.followers": "Followers imported successfully", - "import_data.success.mutes": "Mutes imported successfully", + "import_data.actions.import_blocks": "导入屏蔽列表", + "import_data.actions.import_follows": "导入关注列表", + "import_data.actions.import_mutes": "导入静音列表", + "import_data.blocks_label": "屏蔽帐号", + "import_data.follows_label": "关注帐号", + "import_data.hints.blocks": "上传包含屏蔽帐号列表的CSV文件。", + "import_data.hints.follows": "上传包含关注帐号列表的CSV文件。", + "import_data.hints.mutes": "上传包含静音帐号列表的CSV文件。", + "import_data.mutes_label": "静音帐号", + "import_data.success.blocks": "屏蔽帐号列表导入完成", + "import_data.success.followers": "关注帐号列表导入完成", + "import_data.success.mutes": "静音帐号列表导入完成", "intervals.full.days": "{number} 天", "intervals.full.hours": "{number} 小时", "intervals.full.minutes": "{number} 分钟", - "introduction.federation.action": "Next", - "introduction.federation.home.headline": "Home", + "introduction.federation.action": "下一步", + "introduction.federation.home.headline": "主页", "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", "introduction.interactions.action": "Finish tutorial!", "introduction.interactions.favourite.headline": "Favorite", @@ -474,50 +522,52 @@ "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", "keyboard_shortcuts.back": "返回上一页", "keyboard_shortcuts.blocked": "打开被屏蔽用户列表", - "keyboard_shortcuts.boost": "转嘟", - "keyboard_shortcuts.compose": "选择嘟文撰写框", + "keyboard_shortcuts.boost": "转发", + "keyboard_shortcuts.compose": "选择帖文撰写框", "keyboard_shortcuts.down": "在列表中让光标下移", - "keyboard_shortcuts.enter": "展开嘟文", - "keyboard_shortcuts.favourite": "收藏嘟文", - "keyboard_shortcuts.favourites": "打开收藏列表", + "keyboard_shortcuts.enter": "展开帖文", + "keyboard_shortcuts.favourite": "点赞帖文", + "keyboard_shortcuts.favourites": "打开点赞列表", "keyboard_shortcuts.heading": "快捷键列表", "keyboard_shortcuts.home": "打开主页时间轴", "keyboard_shortcuts.hotkey": "快捷键", "keyboard_shortcuts.legend": "显示此列表", - "keyboard_shortcuts.mention": "提及嘟文作者", + "keyboard_shortcuts.mention": "提及帖文作者", "keyboard_shortcuts.muted": "打开隐藏用户列表", "keyboard_shortcuts.my_profile": "打开你的个人资料", "keyboard_shortcuts.notifications": "打开通知栏", - "keyboard_shortcuts.open_media": "to open media", - "keyboard_shortcuts.pinned": "打开置顶嘟文列表", + "keyboard_shortcuts.open_media": "打开媒体", + "keyboard_shortcuts.pinned": "打开置顶帖文列表", "keyboard_shortcuts.profile": "打开作者的个人资料", - "keyboard_shortcuts.react": "to react", - "keyboard_shortcuts.reply": "回复嘟文", + "keyboard_shortcuts.react": "互动", + "keyboard_shortcuts.reply": "回复", "keyboard_shortcuts.requests": "打开关注请求列表", "keyboard_shortcuts.search": "选择搜索框", "keyboard_shortcuts.toggle_hidden": "显示或隐藏被折叠的正文", "keyboard_shortcuts.toggle_sensitivity": "显示/隐藏媒体", - "keyboard_shortcuts.toot": "发送新嘟文", + "keyboard_shortcuts.toot": "发帖", "keyboard_shortcuts.unfocus": "取消输入", "keyboard_shortcuts.up": "在列表中让光标上移", "lightbox.close": "关闭", "lightbox.next": "下一个", "lightbox.previous": "上一个", "lightbox.view_context": "查看上下文", - "list.click_to_add": "点击以添加账号到列表", - "list_adder.header_title": "在列表内添加或删除账号", + "list.click_to_add": "点击以添加帐号到列表", + "list.label": "Select list…", + "list.select": "Select list", + "list_adder.header_title": "在列表内添加或删除帐号", "lists.account.add": "添加到列表", "lists.account.remove": "从列表中移除", "lists.edit": "编辑列表", - "lists.edit.submit": "更改标题", + "lists.edit.submit": "更改列表", "lists.new.create": "新建列表", - "lists.new.create_title": "创建标题", - "lists.new.save_title": "保存标题", + "lists.new.create_title": "创建列表", + "lists.new.save_title": "保存列表", "lists.new.title_placeholder": "新列表的标题", "lists.search": "搜索你关注的人", "lists.subheading": "你的列表", "loading_indicator.label": "加载中……", - "login.fields.instance_label": "Instance", + "login.fields.instance_label": "实例", "login.fields.instance_placeholder": "example.com", "login.fields.otp_code_hint": "输入双重认证应用里的代码,或者输入恢复代码", "login.fields.otp_code_label": "双重认证代码:", @@ -528,10 +578,10 @@ "login.otp_log_in.fail": "密码错误,请重试。", "login.reset_password_hint": "登录时出现问题了吗?", "media_gallery.toggle_visible": "切换显示/隐藏", - "media_panel.empty_message": "No media found.", + "media_panel.empty_message": "未找到媒体", "media_panel.title": "媒体", - "mfa.mfa_disable_enter_password": "输入账号密码以禁用双重认证:", - "mfa.mfa_setup_enter_password": "输入账号密码以验证身份:", + "mfa.mfa_disable_enter_password": "输入帐号密码以禁用双重认证:", + "mfa.mfa_setup_enter_password": "输入帐号密码以验证身份:", "mfa.mfa_setup_scan_description": "请使用 Google 身份验证器或其他的TOTP双重认证手机应用扫描此处的二维码。启用双重认证后,在登录时,你需要输入该应用生成的代码。", "mfa.mfa_setup_scan_key": "双重认证代码:", "mfa.mfa_setup_scan_title": "如果你无法扫描二维码,请手动输入下列文本:", @@ -542,116 +592,125 @@ "mfa.setup_hint": "请跟随以下步骤以开启双重认证", "mfa.setup_otp_title": "双重认证已关闭", "mfa.setup_recoverycodes": "恢复代码", - "mfa.setup_warning": "请立即将恢复代码保存或写到纸上,否则你可能无法登录账号。", - "missing_description_modal.cancel": "Cancel", - "missing_description_modal.continue": "Post", - "missing_description_modal.text": "You have not entered a description for all attachments. Continue anyway?", + "mfa.setup_warning": "请立即将恢复代码保存或写到纸上,否则你可能无法登录帐号。", + "missing_description_modal.cancel": "取消", + "missing_description_modal.continue": "发布", + "missing_description_modal.text": "附件没有描述信息,仍然继续发布吗?", "missing_indicator.label": "找不到内容", "missing_indicator.sublabel": "无法找到此资源", "morefollows.followers_label": "和{count} 来自其他站点的 {count, plural, one {关注者} other {关注者}} 。", "morefollows.following_label": "和{count} 来自其他站点的 {count, plural, one {正在关注} other {正在关注}} 。", "mute_modal.hide_notifications": "同时隐藏来自这个用户的通知?", - "navigation.chats": "Chats", - "navigation.dashboard": "Dashboard", - "navigation.direct_messages": "Messages", - "navigation.home": "Home", - "navigation.invites": "Invites", - "navigation.notifications": "Notifications", - "navigation.search": "Search", - "navigation_bar.account_aliases": "Account aliases", + "navigation.chats": "聊天", + "navigation.dashboard": "管理中心", + "navigation.developers": "开发者", + "navigation.direct_messages": "私信", + "navigation.home": "主页", + "navigation.invites": "邀请", + "navigation.notifications": "通知", + "navigation.search": "搜索", + "navigation_bar.account_aliases": "帐号别名", "navigation_bar.admin_settings": "管理员设置", - "navigation_bar.blocks": "已屏蔽的用户", - "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.compose": "撰写新嘟文", - "navigation_bar.compose_direct": "Direct message", - "navigation_bar.domain_blocks": "已屏蔽的站点", - "navigation_bar.export_data": "Export data", - "navigation_bar.favourites": "收藏的内容", - "navigation_bar.filters": "屏蔽关键词", + "navigation_bar.blocks": "屏蔽", + "navigation_bar.bookmarks": "书签", + "navigation_bar.compose": "撰写新帖", + "navigation_bar.compose_direct": "撰写私信", + "navigation_bar.compose_reply": "Reply to post", + "navigation_bar.domain_blocks": "屏蔽站点", + "navigation_bar.export_data": "导出数据", + "navigation_bar.favourites": "点赞的内容", + "navigation_bar.filters": "过滤", "navigation_bar.follow_requests": "关注请求", - "navigation_bar.import_data": "导入备份", + "navigation_bar.import_data": "导入数据", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "关于本站", + "navigation_bar.invites": "邀请", "navigation_bar.keyboard_shortcuts": "快捷键列表", - "navigation_bar.lists": "Lists", + "navigation_bar.lists": "列表", "navigation_bar.logout": "登出", - "navigation_bar.messages": "Messages", - "navigation_bar.mutes": "已隐藏的用户", - "navigation_bar.pins": "置顶嘟文", + "navigation_bar.messages": "私信", + "navigation_bar.mutes": "静音", + "navigation_bar.pins": "置顶帖文", "navigation_bar.preferences": "首选项", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "安全", "navigation_bar.soapbox_config": "Soapbox设置", "notification.chat_mention": "{name} 回复了你", - "notification.favourite": "{name} 收藏了你的嘟文", + "notification.favourite": "{name} 赞了你的帖文", "notification.follow": "{name} 开始关注你", "notification.follow_request": "{name} 请求关注你", "notification.mention": "{name} 提及了你", "notification.move": "{name} moved to {targetName}", - "notification.pleroma:emoji_reaction": "{name} 用Emoji互动了你的嘟文", + "notification.pleroma:emoji_reaction": "{name} 对你的帖文回应了表情", "notification.poll": "你参与的一个投票已经结束", - "notification.reblog": "{name} 转嘟了你的嘟文", + "notification.reblog": "{name} 转发了你的帖文", "notifications.clear": "清空通知列表", "notifications.clear_confirmation": "你确定要永久清空通知列表吗?", "notifications.column_settings.alert": "桌面通知", "notifications.column_settings.emoji_react": "用Emoji互动:", - "notifications.column_settings.favourite": "当你的嘟文被收藏时:", + "notifications.column_settings.favourite": "当你的帖文被点赞时:", "notifications.column_settings.filter_bar.advanced": "显示所有类别", "notifications.column_settings.filter_bar.category": "快速过滤栏", "notifications.column_settings.filter_bar.show": "显示", "notifications.column_settings.follow": "当有人关注你时:", "notifications.column_settings.follow_request": "新的关注请求:", - "notifications.column_settings.mention": "当有人在嘟文中提及你时:", - "notifications.column_settings.move": "Moves:", + "notifications.column_settings.mention": "当有人在帖文中提及你时:", + "notifications.column_settings.move": "迁移:", "notifications.column_settings.poll": "投票结果:", "notifications.column_settings.push": "推送通知", - "notifications.column_settings.reblog": "当有人转嘟了你的嘟文时:", + "notifications.column_settings.reblog": "当有人转发了你的帖文时:", "notifications.column_settings.show": "在通知栏显示", "notifications.column_settings.sound": "播放音效", "notifications.column_settings.sounds": "音效设置", "notifications.column_settings.sounds.all_sounds": "收到所有类型的通知时播放音效", - "notifications.column_settings.title": "Notification settings", + "notifications.column_settings.title": "通知设置", "notifications.filter.all": "全部", - "notifications.filter.boosts": "转嘟", + "notifications.filter.boosts": "转发", "notifications.filter.emoji_reacts": "Emoji互动", - "notifications.filter.favourites": "收藏", + "notifications.filter.favourites": "点赞", "notifications.filter.follows": "关注", "notifications.filter.mentions": "提及", - "notifications.filter.moves": "Moves", + "notifications.filter.moves": "迁移", "notifications.filter.polls": "投票结果", "notifications.group": "{count} 条通知", "notifications.queue_label": "点击查看 {count} 新 {count, plural, one {通知} other {通知}}", - "password_reset.confirmation": "Check your email for confirmation.", - "password_reset.fields.username_placeholder": "Email or username", - "password_reset.reset": "Reset password", - "pinned_statuses.none": "没有置顶嘟文.", + "password_reset.confirmation": "请查阅确认邮件。", + "password_reset.fields.username_placeholder": "电子邮件或用户名", + "password_reset.reset": "重置密码", + "pinned_statuses.none": "没有置顶帖文", "poll.closed": "已关闭", "poll.refresh": "刷新", "poll.total_votes": "{count} 票", "poll.vote": "投票", + "poll.voted": "你投给了这个选项", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "发起投票", "poll_button.remove_poll": "移除投票", "preferences.fields.auto_play_gif_label": "自动播放GIF动图", - "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", - "preferences.fields.boost_modal_label": "转嘟前确认", - "preferences.fields.content_type_label": "嘟文格式", - "preferences.fields.delete_modal_label": "删除嘟文前确认", + "preferences.fields.autoload_more_label": "滚动到时间线底部时自动加载更多帖文", + "preferences.fields.autoload_timelines_label": "滚动到时间线顶部时自动加载新帖", + "preferences.fields.boost_modal_label": "转发前确认", + "preferences.fields.content_type_label": "发帖格式", + "preferences.fields.delete_modal_label": "删除帖文前确认", "preferences.fields.demetricator_label": "使用计量器", + "preferences.fields.developer_label": "开发工具", "preferences.fields.display_media.default": "隐藏被标记为敏感内容的媒体", "preferences.fields.display_media.hide_all": "显示所有的媒体", "preferences.fields.display_media.show_all": "隐藏所有媒体", "preferences.fields.dyslexic_font_label": "阅读障碍模式", - "preferences.fields.expand_spoilers_label": "始终展开标有内容警告的帖子", + "preferences.fields.expand_spoilers_label": "始终展开标有内容警告的帖文", "preferences.fields.halloween_label": "万圣节主题", "preferences.fields.language_label": "语言", "preferences.fields.media_display_label": "媒体展示", - "preferences.fields.missing_description_modal_label": "Show confirmation dialog before sending a post without media descriptions", + "preferences.fields.missing_description_modal_label": "发帖中的媒体没有文字说明时提示", "preferences.fields.privacy_label": "默认可见范围", "preferences.fields.reduce_motion_label": "减少过渡动画效果", "preferences.fields.system_font_label": "使用系统默认字体", - "preferences.fields.underline_links_label": "Always underline links in posts", + "preferences.fields.underline_links_label": "超链接总是加下划线显示", "preferences.fields.unfollow_modal_label": "取消关注前询问我", "preferences.hints.content_type_markdown": "警告,实验性功能!", "preferences.hints.demetricator": "隐藏所有互动数据,减少社交媒体的焦虑感。", - "preferences.hints.halloween": "不给糖就捣蛋!支持暗黑或明亮主题。", + "preferences.hints.halloween": "不给糖就捣蛋!支持暗色或明亮主题。", "preferences.hints.privacy_followers_only": "仅关注者可见。", "preferences.hints.privacy_public": "所有人可见,并出现在公共时间轴上。", "preferences.hints.privacy_unlisted": "所有人可见,但不出现在公共时间轴上。", @@ -660,7 +719,7 @@ "preferences.options.privacy_followers_only": "仅关注者", "preferences.options.privacy_public": "公开", "preferences.options.privacy_unlisted": "不公开", - "privacy.change": "设置嘟文可见范围", + "privacy.change": "设置帖文可见范围", "privacy.direct.long": "只有被提及的用户能看到。", "privacy.direct.short": "私信", "privacy.private.long": "只有关注你的用户能看到。", @@ -669,78 +728,95 @@ "privacy.public.short": "公开", "privacy.unlisted.long": "所有人可见,但不会出现在公共时间轴上。", "privacy.unlisted.short": "不公开", - "profile_dropdown.add_account": "添加一个已有账号", + "profile_dropdown.add_account": "添加一个已有帐号", "profile_dropdown.logout": "登出 @{acct}", - "public.column_settings.title": "Fediverse timeline settings", + "public.column_settings.title": "跨站公共时间轴设置", + "reactions.all": "All", "regeneration_indicator.label": "加载中……", "regeneration_indicator.sublabel": "你的主页时间轴正在准备中!", - "register_invite.lead": "Complete the form below to create an account.", - "register_invite.title": "You've been invited to join {siteTitle}!", + "register_invite.lead": "填写以下表单以创建帐号", + "register_invite.title": "你已被邀请加入 {siteTitle}!", "registration.agreement": "我同意本站用户条款 {tos}。", "registration.captcha.hint": "点击图像以重新加载验证码。", "registration.closed_message": "{instance} 不再接受新的用户注册。", - "registration.closed_title": "Registrations 停止注册", + "registration.closed_title": "暂停注册", "registration.confirmation_modal.close": "关闭", "registration.fields.confirm_placeholder": "请再输入密码", "registration.fields.email_placeholder": "邮箱地址", "registration.fields.password_placeholder": "密码", "registration.fields.username_hint": "只可以使用字母、数字、下划线。", "registration.fields.username_placeholder": "用户名", - "registration.lead": "有 {instance} 的账号后,你可以关注联邦宇宙上的用户。", - "registration.newsletter": "Subscribe to newsletter.", + "registration.lead": "有 {instance} 的帐号后,你可以关注联邦宇宙上的用户。", + "registration.newsletter": "订阅新闻邮件", + "registration.password_mismatch": "密码不匹配", "registration.reason": "请填写注册理由", - "registration.reason_hint": "这会帮助我们审核你的账号", + "registration.reason_hint": "这会帮助我们审核你的帐号", "registration.sign_up": "注册", "registration.tos": "用户条款", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}天", "relative_time.hours": "{number}时", "relative_time.just_now": "刚刚", "relative_time.minutes": "{number}分", "relative_time.seconds": "{number}秒", - "remote_instance.edit_federation": "Edit federation", - "remote_instance.federation_panel.heading": "Federation Restrictions", - "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} has placed no restrictions on {host}.", - "remote_instance.federation_panel.restricted_message": "{siteTitle} blocks all activities from {host}.", - "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", - "remote_instance.pin_host": "Pin {host}", - "remote_instance.unpin_host": "Unpin {host}", + "remote_instance.edit_federation": "编辑联邦设置", + "remote_instance.federation_panel.heading": "联邦站点限制", + "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} 未对 {host} 设置限制。", + "remote_instance.federation_panel.restricted_message": "{siteTitle} 完全屏蔽了 {host} 。", + "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} 部分限制了 {host} 。", + "remote_instance.pin_host": "收藏 {host}", + "remote_instance.unpin_host": "取消收藏 {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "你在查看 {instance} 的时间轴。", "reply_indicator.cancel": "取消", - "report.block": "屏蔽账号 {target}", - "report.block_hint": "你是否也要屏蔽这个账号呢?", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", + "report.block": "屏蔽帐号 {target}", + "report.block_hint": "你是否也要屏蔽这个帐号呢?", "report.forward": "发送举报至 {target}", "report.forward_hint": "这名用户来自另一个服务器。是否要向那个服务器发送一条匿名的举报?", "report.hint": "举报将会发送给你所在服务器的监察员。你可以在下面填写举报该用户的理由:", "report.placeholder": "备注", "report.submit": "提交", "report.target": "举报 {target}", - "schedule.post_time": "Post Date/Time", - "schedule.remove": "Remove schedule", - "schedule_button.add_schedule": "Schedule post for later", - "schedule_button.remove_schedule": "Post immediately", - "scheduled_status.cancel": "Cancel", + "schedule.post_time": "发布日期与时间", + "schedule.remove": "取消发布", + "schedule_button.add_schedule": "定时发布", + "schedule_button.remove_schedule": "立即发布", + "scheduled_status.cancel": "取消", + "search.action": "搜索 “{query}”", "search.placeholder": "搜索", - "search_popout.search_format": "高级搜索格式", - "search_popout.tips.full_text": "输入关键词检索所有你发送、收藏、转嘟过或提及到你的嘟文,以及其他用户公开的用户名、昵称和话题标签。", - "search_popout.tips.hashtag": "话题标签", - "search_popout.tips.status": "嘟文", - "search_popout.tips.user": "用户", "search_results.accounts": "用户", "search_results.hashtags": "话题标签", - "search_results.statuses": "嘟文", + "search_results.statuses": "帖文", "search_results.top": "结果", "security.codes.fail": "恢复代码错误", "security.confirm.fail": "密码错误,请重试。", - "security.delete_account.fail": "删除账号失败。.", - "security.delete_account.success": "账号删除成功。", + "security.delete_account.fail": "删除帐号失败。.", + "security.delete_account.success": "帐号删除成功。", "security.disable.fail": "密码错误,请重试。", "security.disable_mfa": "关闭", "security.fields.email.label": "邮箱地址", "security.fields.new_password.label": "输入新密码", "security.fields.old_password.label": "输入原密码", - "security.fields.password.label": "Password", + "security.fields.password.label": "密码", "security.fields.password_confirmation.label": "再次输入新密码", - "security.headers.delete": "删除账号", + "security.headers.delete": "删除帐号", "security.headers.tokens": "会话", "security.headers.update_email": "更改邮箱", "security.headers.update_password": "更改密码", @@ -750,8 +826,8 @@ "security.mfa_setup_hint": "通过OTP进行双重认证", "security.qr.fail": "加载密钥失败", "security.submit": "保存更改", - "security.submit.delete": "删除账号", - "security.text.delete": "输入密码后,本站会立即删除你的账号,并且通知其他站点,但你的信息不会在其他站点上立即删除。", + "security.submit.delete": "删除帐号", + "security.text.delete": "输入密码后,本站会立即删除你的帐号,并且通知其他站点,但你的信息不会在其他站点上立即删除。", "security.tokens.revoke": "吊销", "security.update_email.fail": "更新邮箱地址失败。", "security.update_email.success": "邮箱地址已更新。", @@ -762,28 +838,28 @@ "soapbox_config.authenticated_profile_hint": "Users must be logged-in to view replies and media on user profiles.", "soapbox_config.authenticated_profile_label": "Profiles require authentication", "soapbox_config.copyright_footer.meta_fields.label_placeholder": "版权页底", - "soapbox_config.crypto_address.meta_fields.address_placeholder": "Address", + "soapbox_config.crypto_address.meta_fields.address_placeholder": "地址", "soapbox_config.crypto_address.meta_fields.note_placeholder": "Note (optional)", "soapbox_config.crypto_address.meta_fields.ticker_placeholder": "Ticker", "soapbox_config.crypto_donate_panel_limit.meta_fields.limit_placeholder": "Number of items to display in the crypto homepage widget", "soapbox_config.custom_css.meta_fields.url_placeholder": "URL", - "soapbox_config.display_fqn_label": "显示本站账号的域名(如@user@domain)。", + "soapbox_config.display_fqn_label": "显示本站帐号的域名(如@user@domain)。", "soapbox_config.fields.brand_color_label": "主题颜色", - "soapbox_config.fields.crypto_address.add": "Add new crypto address", - "soapbox_config.fields.crypto_addresses_label": "Cryptocurrency addresses", + "soapbox_config.fields.crypto_address.add": "添加加密币地址", + "soapbox_config.fields.crypto_addresses_label": "加密币地址", "soapbox_config.fields.home_footer.add": "添加主页页底", "soapbox_config.fields.home_footer_fields_label": "主页页底", "soapbox_config.fields.logo_label": "Logo", "soapbox_config.fields.promo_panel.add": "添加时间轴页底", "soapbox_config.fields.promo_panel_fields_label": "时间轴页底", "soapbox_config.fields.theme_label": "默认主题", - "soapbox_config.greentext_label": "Enable greentext support", + "soapbox_config.greentext_label": "打开greentext支持", "soapbox_config.hints.crypto_addresses": "Add cryptocurrency addresses so users of your site can donate to you. Order matters, and you must use lowercase ticker values.", "soapbox_config.hints.home_footer_fields": "你可以将自定义的链接插入在未登录时显示的主页页底(如about)。", "soapbox_config.hints.logo": "SVG。最多2MB。将被显示为50px高度,保持长宽比。", "soapbox_config.hints.promo_panel_fields": "你可以将自定义的链接插入在时间轴右方或页底(如about)。", "soapbox_config.hints.promo_panel_icons": "{ link }", - "soapbox_config.hints.promo_panel_icons.link": "Soapbox Icons List", + "soapbox_config.hints.promo_panel_icons.link": "Soapbox图标列表", "soapbox_config.home_footer.meta_fields.label_placeholder": "标签", "soapbox_config.home_footer.meta_fields.url_placeholder": "URL", "soapbox_config.promo_panel.meta_fields.icon_placeholder": "图标", @@ -792,22 +868,22 @@ "soapbox_config.raw_json_hint": "直接编辑JSON数据。将覆盖此页所有设定。单击以应用更改。", "soapbox_config.raw_json_label": "高级:编辑JSON数据", "soapbox_config.save": "保存更改", - "soapbox_config.saved": "Soapbox config saved!", + "soapbox_config.saved": "Soapbox配置已保存", "soapbox_config.verified_can_edit_name_label": "允许经过验证的用户编辑他们自己的昵称。", "status.admin_account": "打开 @{name} 的管理界面", - "status.admin_status": "打开这条嘟文的管理界面", + "status.admin_status": "打开这条帖文的管理界面", "status.block": "屏蔽 @{name}", - "status.bookmark": "Bookmark", - "status.bookmarked": "Bookmark added.", - "status.cancel_reblog_private": "取消转嘟", - "status.cannot_reblog": "这条嘟文不允许被转嘟。", - "status.chat": "Chat with @{name}", - "status.copy": "复制嘟文链接", + "status.bookmark": "书签", + "status.bookmarked": "书签已添加。", + "status.cancel_reblog_private": "取消转发", + "status.cannot_reblog": "这条帖文不允许被转发。", + "status.chat": "与 @{name} 聊天", + "status.copy": "复制帖文链接", "status.delete": "删除", "status.detailed_status": "对话详情", "status.direct": "发送私信给 @{name}", "status.embed": "嵌入", - "status.favourite": "收藏", + "status.favourite": "点赞", "status.filtered": "已过滤", "status.load_more": "加载更多", "status.media_hidden": "隐藏媒体内容", @@ -815,25 +891,25 @@ "status.more": "更多", "status.mute": "隐藏 @{name}", "status.mute_conversation": "隐藏此对话", - "status.open": "展开嘟文", + "status.open": "展开帖文", "status.pin": "在个人资料页面置顶", - "status.pinned": "置顶嘟文", + "status.pinned": "置顶帖文", "status.reactions.cry": "Sad", - "status.reactions.empty": "No one has reacted to this post yet. When someone does, they will show up here.", + "status.reactions.empty": "尚未有人回应表情", "status.reactions.heart": "Love", "status.reactions.laughing": "Haha", "status.reactions.like": "Like", "status.reactions.open_mouth": "Wow", "status.reactions.weary": "Weary", - "status.reactions_expand": "Select emoji", + "status.reactions_expand": "选择表情", "status.read_more": "阅读全文", - "status.reblog": "转嘟", - "status.reblog_private": "转嘟(可见者不变)", - "status.reblogged_by": "{name} 转嘟了", - "status.reblogs.empty": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。", + "status.reblog": "转发", + "status.reblog_private": "转发(可见范围不变)", + "status.reblogged_by": "{name} 转发了", + "status.reblogs.empty": "没有人转发过此条帖文。如果有人转发了,就会显示在这里。", "status.redraft": "删除并重新编辑", - "status.remove_account_from_group": "移除出列表", - "status.remove_post_from_group": "移除出列表", + "status.remove_account_from_group": "将帐号移出群组", + "status.remove_post_from_group": "将帖文移出群组", "status.reply": "回复", "status.replyAll": "回复所有人", "status.report": "举报 @{name}", @@ -844,49 +920,49 @@ "status.show_more": "显示内容", "status.show_more_all": "显示所有内容", "status.show_thread": "显示全部对话", - "status.title": "Post", - "status.title_direct": "Direct message", + "status.title": "帖文", + "status.title_direct": "私信", "status.unbookmark": "移除书签", - "status.unbookmarked": "Bookmark removed.", + "status.unbookmarked": "书签已移除。", "status.unmute_conversation": "不再隐藏此对话", "status.unpin": "在个人资料页面取消置顶", - "status_list.queue_label": "点击以查看 {count} 新的 {count, plural, one {嘟文} other {嘟文}}", - "statuses.tombstone": "One or more posts is unavailable.", + "status_list.queue_label": "点击查看 {count} 则新{count, plural, one {帖文} other {帖文}}", + "statuses.tombstone": "部分帖文不可见", "suggestions.dismiss": "关闭建议", - "tabs_bar.all": "All", + "tabs_bar.all": "全部", "tabs_bar.apps": "应用", - "tabs_bar.chats": "私信", - "tabs_bar.dashboard": "仪表板", - "tabs_bar.fediverse": "Fediverse", - "tabs_bar.header": "Account Info", + "tabs_bar.chats": "聊天", + "tabs_bar.dashboard": "管理中心", + "tabs_bar.fediverse": "联邦宇宙", + "tabs_bar.header": "帐号信息", "tabs_bar.home": "主页", "tabs_bar.news": "新闻", "tabs_bar.notifications": "通知", - "tabs_bar.post": "新嘟文", + "tabs_bar.post": "发帖", "tabs_bar.search": "搜索", - "tabs_bar.theme_toggle_dark": "切换到暗黑主题", + "tabs_bar.theme_toggle_dark": "切换到暗色主题", "tabs_bar.theme_toggle_light": "切换到明亮主题", - "time_remaining.days": "剩余 {number, plural, one {# 天} other {# 天}}", - "time_remaining.hours": "剩余 {number, plural, one {# 小时} other {# 小时}}", - "time_remaining.minutes": "剩余 {number, plural, one {# 分钟} other {# 分钟}}", - "time_remaining.moments": "即将结束", - "time_remaining.seconds": "剩余 {number, plural, one {# 秒} other {# 秒}}", + "time_remaining.days": "离预定时间还有 {number, plural, one {# 天} other {# 天}}", + "time_remaining.hours": "离预定时间还有 {number, plural, one {# 小时} other {# 小时}}", + "time_remaining.minutes": "离预定时间还有 {number, plural, one {# 分钟} other {# 分钟}}", + "time_remaining.moments": "即将到达预定时间", + "time_remaining.seconds": "离预定时间还有 {number, plural, one {# 秒} other {# 秒}}", "trends.count_by_accounts": "{count} 人正在讨论", "trends.title": "热门", - "ui.beforeunload": "如果你现在离开Pleroma,你的草稿内容将会丢失。", + "ui.beforeunload": "如果你现在离开网站,你的草稿内容将会丢失。", "unauthorized_modal.footer": "已经有帐号了吗? {login}.", - "unauthorized_modal.text": "你需要账号才能继续", - "unauthorized_modal.title": "注册账号 {site_title}", + "unauthorized_modal.text": "你需要帐号才能继续", + "unauthorized_modal.title": "注册帐号 {site_title}", "upload_area.title": "将文件拖放到此处开始上传", "upload_button.label": "上传媒体文件 (JPEG, PNG, GIF, WebM, MP4, MOV)", "upload_error.limit": "文件大小超过限制。", "upload_error.poll": "投票中不允许上传文件。", "upload_form.description": "为视觉障碍人士添加文字说明", - "upload_form.preview": "Preview", + "upload_form.preview": "预览", "upload_form.undo": "删除", "upload_progress.label": "上传中……", "video.close": "关闭视频", - "video.download": "Download file", + "video.download": "下载", "video.exit_fullscreen": "退出全屏", "video.expand": "展开视频", "video.fullscreen": "全屏", diff --git a/app/soapbox/locales/zh-HK.json b/app/soapbox/locales/zh-HK.json index 96e9a7697..8adb2bafb 100644 --- a/app/soapbox/locales/zh-HK.json +++ b/app/soapbox/locales/zh-HK.json @@ -8,6 +8,7 @@ "account.block_domain": "隱藏來自 {domain} 的一切文章", "account.blocked": "封鎖", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "This user doesn't follow anyone yet.", "account.follows_you": "關注你", "account.hide_reblogs": "隱藏 @{name} 的轉推", + "account.last_status": "Last active", "account.link_verified_on": "Ownership of this link was checked on {date}", "account.locked_info": "This account privacy status is set to locked. The owner manually reviews who can follow them.", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} 已經遷移到:", "account.mute": "將 @{name} 靜音", "account.muted": "靜音", + "account.never_active": "Never", "account.posts": "文章", "account.posts_with_replies": "包含回覆的文章", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "關閉", "bundle_modal_error.message": "加載本組件出錯。", "bundle_modal_error.retry": "重試", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "封鎖用戶", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "本站時間軸", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "個人訊息", + "column.directory": "Browse profiles", "column.domain_blocks": "隱藏的服務站", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "關注請求", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "主頁", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "列表", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "靜音名單", "column.notifications": "通知", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "跨站時間軸", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "返回", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "隱藏設定", "column_header.show_settings": "顯示設定", "community.column_settings.media_only": "僅媒體", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "發文", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "Block & Report", "confirmations.block.confirm": "封鎖", "confirmations.block.message": "你確定要封鎖{name}嗎?", "confirmations.delete.confirm": "刪除", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "你確定要刪除這文章嗎?", "confirmations.delete_list.confirm": "刪除", "confirmations.delete_list.message": "你確定要永久刪除這列表嗎?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "批准", "follow_request.reject": "拒絕", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name}(萬象)是一個開放源碼的軟件。你可以在官方 GitLab ({code_link} (v{code_version})) 貢獻或者回報問題。", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "回退", "lightbox.view_context": "View context", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "新增到列表", "lists.account.remove": "從列表刪除", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "隱藏來自這用戶的通知嗎?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "Compose new post", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "隱藏的服務站", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "最愛的內容", "navigation_bar.filters": "Muted words", "navigation_bar.follow_requests": "關注請求", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "關於本服務站", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "鍵盤快速鍵", "navigation_bar.lists": "Lists", "navigation_bar.logout": "登出", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "被你靜音的用戶", "navigation_bar.pins": "置頂文章", "navigation_bar.preferences": "偏好設定", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "安全", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "Refresh", "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", "poll.vote": "Vote", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "載入中……", "regeneration_indicator.sublabel": "你的主頁時間軸正在準備中!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number}日", "relative_time.hours": "{number}小時", "relative_time.just_now": "剛剛", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "取消", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "轉寄到 {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "搜尋", - "search_popout.search_format": "高級搜索格式", - "search_popout.tips.full_text": "輸入簡單的文字,搜索由你發放、收藏、轉推和提及你的文章,以及符合的用戶名稱,帳號名稱和標籤。", - "search_popout.tips.hashtag": "標籤", - "search_popout.tips.status": "文章", - "search_popout.tips.user": "用戶", "search_results.accounts": "使用者", "search_results.hashtags": "標籤", "search_results.statuses": "文章", diff --git a/app/soapbox/locales/zh-TW.json b/app/soapbox/locales/zh-TW.json index 3d58c3380..b6b3107c5 100644 --- a/app/soapbox/locales/zh-TW.json +++ b/app/soapbox/locales/zh-TW.json @@ -8,6 +8,7 @@ "account.block_domain": "隱藏來自 {domain} 的所有內容", "account.blocked": "已封鎖", "account.chat": "Chat with @{name}", + "account.column_settings.description": "These settings apply to all account timelines.", "account.column_settings.title": "Acccount timeline settings", "account.deactivated": "Deactivated", "account.deactivated_description": "This account has been deactivated.", @@ -22,6 +23,7 @@ "account.follows.empty": "這位使用者尚未關注任何使用者。", "account.follows_you": "關注了你", "account.hide_reblogs": "隱藏來自 @{name} 的轉推", + "account.last_status": "Last active", "account.link_verified_on": "已在 {date} 檢查此連結的擁有者權限", "account.locked_info": "這隻帳戶的隱私狀態被設成鎖定。該擁有者會手動審核能關注這隻帳號的人。", "account.login": "Log in", @@ -31,6 +33,7 @@ "account.moved_to": "{name} 已遷移至:", "account.mute": "靜音 @{name}", "account.muted": "已靜音", + "account.never_active": "Never", "account.posts": "嘟文", "account.posts_with_replies": "嘟文與回覆", "account.profile": "Profile", @@ -96,10 +99,14 @@ "admin.users.actions.promote_to_admin_message": "@{acct} was promoted to an admin", "admin.users.actions.promote_to_moderator": "Promote @{name} to a moderator", "admin.users.actions.promote_to_moderator_message": "@{acct} was promoted to a moderator", + "admin.users.actions.suggest_user": "Suggest @{name}", + "admin.users.actions.unsuggest_user": "Unsuggest @{name}", "admin.users.actions.unverify_user": "Unverify @{name}", "admin.users.actions.verify_user": "Verify @{name}", "admin.users.user_deactivated_message": "@{acct} was deactivated", "admin.users.user_deleted_message": "@{acct} was deleted", + "admin.users.user_suggested_message": "@{acct} was suggested", + "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", "admin_nav.awaiting_approval": "Awaiting Approval", @@ -116,9 +123,20 @@ "aliases.search": "Search your old account", "aliases.success.add": "Account alias created successfully", "aliases.success.remove": "Account alias removed successfully", + "app_create.name_label": "App name", + "app_create.name_placeholder": "e.g. 'Soapbox'", + "app_create.redirect_uri_label": "Redirect URIs", + "app_create.restart": "Create another", + "app_create.results.app_label": "App", + "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", + "app_create.results.explanation_title": "App created successfully", + "app_create.results.token_label": "OAuth token", + "app_create.scopes_label": "Scopes", + "app_create.scopes_placeholder": "e.g. 'read write follow'", + "app_create.submit": "Create app", + "app_create.website_label": "Website", "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", - "autosuggest_account_input.default_placeholder": "Search for an account", "backups.actions.create": "Create backup", "backups.empty_message": "No backups found. {action}", "backups.empty_message.action": "Create one now?", @@ -130,6 +148,7 @@ "bundle_modal_error.close": "關閉", "bundle_modal_error.message": "載入此元件時發生錯誤。", "bundle_modal_error.retry": "重試", + "chat_box.actions.close": "Close chat", "chat_box.actions.send": "Send", "chat_box.input.placeholder": "Send a message…", "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", @@ -137,6 +156,8 @@ "chats.actions.delete": "Delete message", "chats.actions.more": "More", "chats.actions.report": "Report user", + "chats.attachment": "Attachment", + "chats.attachment_image": "Image", "chats.audio_toggle_off": "Audio notification off", "chats.audio_toggle_on": "Audio notification on", "chats.dividers.today": "Today", @@ -146,22 +167,27 @@ "column.admin.moderation_log": "Moderation Log", "column.admin.reports": "Reports", "column.admin.reports.menu.moderation_log": "Moderation Log", + "column.admin.users": "Users", "column.aliases": "Account aliases", "column.aliases.create_error": "Error creating alias", "column.aliases.delete": "Delete", "column.aliases.delete_error": "Error deleting alias", "column.aliases.subheading_add_new": "Add New Alias", "column.aliases.subheading_aliases": "Current aliases", + "column.app_create": "Create app", "column.backups": "Backups", "column.blocks": "封鎖的使用者", "column.bookmarks": "Bookmarks", "column.chats": "Chats", "column.community": "本機時間軸", "column.crypto_donate": "Donate Cryptocurrency", + "column.developers": "Developers", "column.direct": "私訊", + "column.directory": "Browse profiles", "column.domain_blocks": "隱藏的網域", "column.edit_profile": "Edit profile", "column.export_data": "Export data", + "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", "column.federation_restrictions": "Federation Restrictions", "column.filters": "Muted words", @@ -183,11 +209,14 @@ "column.filters.whole_word_header": "Whole word", "column.filters.whole_word_hint": "When the keyword or phrase is alphanumeric only, it will only be applied if it matches the whole word", "column.follow_requests": "關注請求", + "column.followers": "Followers", + "column.following": "Following", "column.groups": "Groups", "column.home": "主頁", "column.import_data": "Import data", "column.info": "Server information", "column.lists": "名單", + "column.mentions": "Mentions", "column.mfa": "Multi-Factor Authentication", "column.mfa_cancel": "Cancel", "column.mfa_confirm_button": "Confirm", @@ -195,8 +224,11 @@ "column.mfa_setup": "Proceed to Setup", "column.mutes": "被靜音的使用者", "column.notifications": "通知", + "column.pins": "Pinned posts", "column.preferences": "Preferences", + "column.profile_directory": "Profile directory", "column.public": "聯邦時間軸", + "column.reactions": "Reactions", "column.reblogs": "Reposts", "column.remote": "Federated timeline", "column.scheduled_statuses": "Scheduled Posts", @@ -204,6 +236,8 @@ "column.security": "Security", "column.soapbox_config": "Soapbox config", "column_back_button.label": "上一頁", + "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.title": "Forbidden", "column_header.hide_settings": "隱藏設定", "column_header.show_settings": "顯示設定", "community.column_settings.media_only": "只有媒體", @@ -223,7 +257,8 @@ "compose_form.poll.duration": "投票期限", "compose_form.poll.option_placeholder": "第 {number} 個選擇", "compose_form.poll.remove_option": "移除此選擇", - "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", + "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", + "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.publish": "嘟出去", "compose_form.publish_loud": "{publish}!", "compose_form.schedule": "Schedule", @@ -247,10 +282,13 @@ "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", + "confirmations.admin.reject_user.confirm": "Reject @{name}", + "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", "confirmations.block.block_and_report": "封鎖並檢舉", "confirmations.block.confirm": "封鎖", "confirmations.block.message": "確定封鎖 {name} ?", "confirmations.delete.confirm": "刪除", + "confirmations.delete.heading": "Delete post", "confirmations.delete.message": "你確定要刪除這條嘟文?", "confirmations.delete_list.confirm": "刪除", "confirmations.delete_list.message": "確定永久刪除此名單?", @@ -272,7 +310,13 @@ "crypto_donate_panel.heading": "Donate Cryptocurrency", "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", "datepicker.hint": "Scheduled to post at…", + "developers.navigation.app_create_label": "Create an app", + "developers.navigation.intentional_error_label": "Trigger an error", "direct.search_placeholder": "Send a message to…", + "directory.federated": "From known fediverse", + "directory.local": "From {domain} only", + "directory.new_arrivals": "New arrivals", + "directory.recently_active": "Recently active", "donate": "Donate", "donate_crypto": "Donate cryptocurrency", "edit_federation.followers_only": "Hide posts except to followers", @@ -288,6 +332,7 @@ "edit_profile.fields.bio_label": "Bio", "edit_profile.fields.bio_placeholder": "Tell us about yourself.", "edit_profile.fields.bot_label": "This is a bot account", + "edit_profile.fields.discoverable_label": "Allow account discovery", "edit_profile.fields.display_name_label": "Display name", "edit_profile.fields.display_name_placeholder": "Name", "edit_profile.fields.header_label": "Header", @@ -301,6 +346,7 @@ "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", + "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", "edit_profile.hints.locked": "Requires you to manually approve followers", @@ -397,6 +443,8 @@ "follow_request.authorize": "授權", "follow_request.reject": "拒絕", "forms.copy": "Copy", + "forms.hide_password": "Hide password", + "forms.show_password": "Show password", "getting_started.open_source_notice": "{code_name} 是開源軟體。你可以在 GitLab {code_link} (v{code_version}) 上貢獻或是回報問題。", "group.detail.archived_group": "Archived group", "group.members.empty": "This group does not has any members.", @@ -505,6 +553,8 @@ "lightbox.previous": "上一步", "lightbox.view_context": "檢視內文", "list.click_to_add": "Click here to add people", + "list.label": "Select list…", + "list.select": "Select list", "list_adder.header_title": "Add or Remove from Lists", "lists.account.add": "新增至名單", "lists.account.remove": "從名單中移除", @@ -553,6 +603,7 @@ "mute_modal.hide_notifications": "隱藏來自這位使用者的通知?", "navigation.chats": "Chats", "navigation.dashboard": "Dashboard", + "navigation.developers": "Developers", "navigation.direct_messages": "Messages", "navigation.home": "Home", "navigation.invites": "Invites", @@ -564,13 +615,16 @@ "navigation_bar.bookmarks": "Bookmarks", "navigation_bar.compose": "撰寫新嘟文", "navigation_bar.compose_direct": "Direct message", + "navigation_bar.compose_reply": "Reply to post", "navigation_bar.domain_blocks": "隱藏的網域", "navigation_bar.export_data": "Export data", "navigation_bar.favourites": "收藏", "navigation_bar.filters": "靜音詞彙", "navigation_bar.follow_requests": "關注請求", "navigation_bar.import_data": "Import data", + "navigation_bar.in_reply_to": "In reply to", "navigation_bar.info": "關於此伺服器", + "navigation_bar.invites": "Invites", "navigation_bar.keyboard_shortcuts": "快速鍵", "navigation_bar.lists": "Lists", "navigation_bar.logout": "登出", @@ -578,6 +632,7 @@ "navigation_bar.mutes": "靜音的使用者", "navigation_bar.pins": "釘選的嘟文", "navigation_bar.preferences": "偏好設定", + "navigation_bar.profile_directory": "Profile directory", "navigation_bar.security": "安全性", "navigation_bar.soapbox_config": "Soapbox config", "notification.chat_mention": "{name} sent you a message", @@ -627,14 +682,18 @@ "poll.refresh": "重新整理", "poll.total_votes": "{count, plural, one {# 個投票} other {# 個投票}}", "poll.vote": "投票", + "poll.voted": "You voted for this answer", + "poll.votes": "{votes, plural, one {# vote} other {# votes}}", "poll_button.add_poll": "建立投票", "poll_button.remove_poll": "移除投票", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.content_type_label": "Post format", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", + "preferences.fields.developer_label": "Developer tools", "preferences.fields.display_media.default": "Hide media marked as sensitive", "preferences.fields.display_media.hide_all": "Always hide media", "preferences.fields.display_media.show_all": "Always show media", @@ -672,6 +731,7 @@ "profile_dropdown.add_account": "Add an existing account", "profile_dropdown.logout": "Log out @{acct}", "public.column_settings.title": "Fediverse timeline settings", + "reactions.all": "All", "regeneration_indicator.label": "載入中…", "regeneration_indicator.sublabel": "你的主頁時間軸正在準備中!", "register_invite.lead": "Complete the form below to create an account.", @@ -688,10 +748,12 @@ "registration.fields.username_placeholder": "Username", "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", "registration.newsletter": "Subscribe to newsletter.", + "registration.password_mismatch": "Passwords don't match.", "registration.reason": "Why do you want to join?", "registration.reason_hint": "This will help us review your application", "registration.sign_up": "Sign up", "registration.tos": "Terms of Service", + "registration.username_unavailable": "Username is already taken.", "relative_time.days": "{number} 天", "relative_time.hours": "{number} 小時", "relative_time.just_now": "剛剛", @@ -704,8 +766,26 @@ "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", "remote_instance.pin_host": "Pin {host}", "remote_instance.unpin_host": "Unpin {host}", + "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", + "remote_interaction.divider": "or", + "remote_interaction.favourite": "Proceed to like", + "remote_interaction.favourite_title": "Like a post remotely", + "remote_interaction.follow": "Proceed to follow", + "remote_interaction.follow_title": "Follow {user} remotely", + "remote_interaction.poll_vote": "Proceed to vote", + "remote_interaction.poll_vote_title": "Vote in a poll remotely", + "remote_interaction.reblog": "Proceed to repost", + "remote_interaction.reblog_title": "Reblog a post remotely", + "remote_interaction.reply": "Proceed to reply", + "remote_interaction.reply_title": "Reply to a post remotely", + "remote_interaction.user_not_found_error": "Couldn't find given user", "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", "reply_indicator.cancel": "取消", + "reply_mentions.account.add": "Add to mentions", + "reply_mentions.account.remove": "Remove from mentions", + "reply_mentions.more": "and {count} more", + "reply_mentions.reply": "Replying to {accounts}{more}", + "reply_mentions.reply_empty": "Replying to post", "report.block": "Block {target}", "report.block_hint": "Do you also want to block this account?", "report.forward": "轉寄到 {target}", @@ -719,12 +799,8 @@ "schedule_button.add_schedule": "Schedule post for later", "schedule_button.remove_schedule": "Post immediately", "scheduled_status.cancel": "Cancel", + "search.action": "Search for “{query}”", "search.placeholder": "搜尋", - "search_popout.search_format": "進階搜尋格式", - "search_popout.tips.full_text": "輸入簡單的文字,搜尋由你撰寫、最愛、轉嘟或提你的嘟文,以及符合使用者名稱、帳戶名稱和標籤。", - "search_popout.tips.hashtag": "主題標籤", - "search_popout.tips.status": "嘟文", - "search_popout.tips.user": "使用者", "search_results.accounts": "使用者", "search_results.hashtags": "主題標籤", "search_results.statuses": "嘟文", diff --git a/app/soapbox/main.js b/app/soapbox/main.js index 4828f996e..dfac430e0 100644 --- a/app/soapbox/main.js +++ b/app/soapbox/main.js @@ -1,15 +1,17 @@ 'use strict'; import './precheck'; -import { default as Soapbox } from './containers/soapbox'; +import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime'; import React from 'react'; import ReactDOM from 'react-dom'; -import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime'; -import * as perf from './performance'; -import * as monitoring from './monitoring'; -import ready from './ready'; + import { NODE_ENV } from 'soapbox/build_config'; +import { default as Soapbox } from './containers/soapbox'; +import * as monitoring from './monitoring'; +import * as perf from './performance'; +import ready from './ready'; + function main() { perf.start('main()'); diff --git a/app/soapbox/pages/admin_page.js b/app/soapbox/pages/admin_page.js index 09fa0d81a..0b9362ca9 100644 --- a/app/soapbox/pages/admin_page.js +++ b/app/soapbox/pages/admin_page.js @@ -1,12 +1,14 @@ import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import LinkFooter from '../features/ui/components/link_footer'; + import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { AdminNav, LatestAccountsPanel, } from 'soapbox/features/ui/util/async-components'; +import LinkFooter from '../features/ui/components/link_footer'; + export default class AdminPage extends ImmutablePureComponent { diff --git a/app/soapbox/pages/default_page.js b/app/soapbox/pages/default_page.js index 5d7a26e76..cd7a7efce 100644 --- a/app/soapbox/pages/default_page.js +++ b/app/soapbox/pages/default_page.js @@ -1,8 +1,10 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; import Sticky from 'react-stickynode'; + import PrimaryNavigation from 'soapbox/components/primary_navigation'; +import LinkFooter from 'soapbox/features/ui/components/link_footer'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { WhoToFollowPanel, @@ -11,7 +13,6 @@ import { FeaturesPanel, SignUpPanel, } from 'soapbox/features/ui/util/async-components'; -import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { getFeatures } from 'soapbox/utils/features'; const mapStateToProps = state => { @@ -62,6 +63,9 @@ class DefaultPage extends ImmutablePureComponent { {Component => } )} + + {Component => } + {showTrendsPanel && ( {Component => } @@ -72,9 +76,6 @@ class DefaultPage extends ImmutablePureComponent { {Component => } )} - - {Component => } -
      diff --git a/app/soapbox/pages/group_page.js b/app/soapbox/pages/group_page.js index d4da40a3f..bd7b7f85d 100644 --- a/app/soapbox/pages/group_page.js +++ b/app/soapbox/pages/group_page.js @@ -1,15 +1,16 @@ -import React from 'react'; -import { connect } from 'react-redux'; import { PropTypes } from 'prop-types'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel'; -import LinkFooter from '../features/ui/components/link_footer'; -import PromoPanel from '../features/ui/components/promo_panel'; -import HeaderContainer from '../features/groups/timeline/containers/header_container'; -import GroupPanel from '../features/groups/timeline/components/panel'; +import { connect } from 'react-redux'; + import { fetchGroup } from '../actions/groups'; import GroupSidebarPanel from '../features/groups/sidebar_panel'; +import GroupPanel from '../features/groups/timeline/components/panel'; +import HeaderContainer from '../features/groups/timeline/containers/header_container'; +import LinkFooter from '../features/ui/components/link_footer'; +import PromoPanel from '../features/ui/components/promo_panel'; +import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel'; const mapStateToProps = (state, { params: { id } }) => ({ group: state.getIn(['groups', id]), diff --git a/app/soapbox/pages/groups_page.js b/app/soapbox/pages/groups_page.js index 8d7683cb9..623e70727 100644 --- a/app/soapbox/pages/groups_page.js +++ b/app/soapbox/pages/groups_page.js @@ -1,12 +1,13 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel'; +import { connect } from 'react-redux'; + +import GroupSidebarPanel from '../features/groups/sidebar_panel'; import LinkFooter from '../features/ui/components/link_footer'; import PromoPanel from '../features/ui/components/promo_panel'; import UserPanel from '../features/ui/components/user_panel'; -import GroupSidebarPanel from '../features/groups/sidebar_panel'; +import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel'; const mapStateToProps = state => { const me = state.get('me'); diff --git a/app/soapbox/pages/home_page.js b/app/soapbox/pages/home_page.js index 62db48263..384c97307 100644 --- a/app/soapbox/pages/home_page.js +++ b/app/soapbox/pages/home_page.js @@ -1,12 +1,12 @@ import React from 'react'; +import ImmutablePureComponent from 'react-immutable-pure-component'; import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import ImmutablePureComponent from 'react-immutable-pure-component'; import Sticky from 'react-stickynode'; -import BundleContainer from '../features/ui/containers/bundle_container'; -import ComposeFormContainer from '../features/compose/containers/compose_form_container'; -import Avatar from '../components/avatar'; + +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import PrimaryNavigation from 'soapbox/components/primary_navigation'; +import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { WhoToFollowPanel, CryptoDonatePanel, @@ -18,10 +18,12 @@ import { SignUpPanel, } from 'soapbox/features/ui/util/async-components'; // import GroupSidebarPanel from '../features/groups/sidebar_panel'; -import LinkFooter from 'soapbox/features/ui/components/link_footer'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { getFeatures } from 'soapbox/utils/features'; +import Avatar from '../components/avatar'; +import ComposeFormContainer from '../features/compose/containers/compose_form_container'; +import BundleContainer from '../features/ui/containers/bundle_container'; + const mapStateToProps = state => { const me = state.get('me'); const soapbox = getSoapboxConfig(state); @@ -96,16 +98,6 @@ class HomePage extends ImmutablePureComponent { {Component => } )} - {showTrendsPanel && ( - - {Component => } - - )} - {showWhoToFollowPanel && ( - - {Component => } - - )} {Component => } @@ -119,6 +111,16 @@ class HomePage extends ImmutablePureComponent { {Component => } )} + {showTrendsPanel && ( + + {Component => } + + )} + {showWhoToFollowPanel && ( + + {Component => } + + )}
      diff --git a/app/soapbox/pages/profile_page.js b/app/soapbox/pages/profile_page.js index 84f6c4f5e..5b62910f2 100644 --- a/app/soapbox/pages/profile_page.js +++ b/app/soapbox/pages/profile_page.js @@ -1,30 +1,32 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; +import { Redirect } from 'react-router-dom'; import Sticky from 'react-stickynode'; + import Helmet from 'soapbox/components/helmet'; -import HeaderContainer from '../features/account_timeline/containers/header_container'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { WhoToFollowPanel, SignUpPanel, ProfileInfoPanel, ProfileMediaPanel, + PinnedAccountsPanel, } from 'soapbox/features/ui/util/async-components'; -import LinkFooter from '../features/ui/components/link_footer'; -import { getAcct } from 'soapbox/utils/accounts'; -import { displayFqn } from 'soapbox/utils/state'; +import { findAccountByUsername, makeGetAccount } from 'soapbox/selectors'; +import { getAcct, isLocal } from 'soapbox/utils/accounts'; import { getFeatures } from 'soapbox/utils/features'; -import { makeGetAccount } from '../selectors'; -import { Redirect } from 'react-router-dom'; -import { findAccountByUsername } from 'soapbox/selectors'; +import { displayFqn } from 'soapbox/utils/state'; + +import HeaderContainer from '../features/account_timeline/containers/header_container'; +import LinkFooter from '../features/ui/components/link_footer'; const mapStateToProps = (state, { params, withReplies = false }) => { const username = params.username || ''; const accounts = state.getIn(['accounts']); - const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() === username.toLowerCase()); + const accountFetchError = ((state.getIn(['accounts', -1, 'username']) || '').toLowerCase() === username.toLowerCase()); const getAccount = makeGetAccount(); let accountId = -1; @@ -116,7 +118,11 @@ class ProfilePage extends ImmutablePureComponent { {Component => } )} - {features.suggestions && ( + {account && features.accountEndorsements && isLocal(account) ? ( + + {Component => } + + ) : features.suggestions && ( {Component => } diff --git a/app/soapbox/pages/remote_instance_page.js b/app/soapbox/pages/remote_instance_page.js index 7805c6daa..87180f647 100644 --- a/app/soapbox/pages/remote_instance_page.js +++ b/app/soapbox/pages/remote_instance_page.js @@ -1,18 +1,19 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; import Sticky from 'react-stickynode'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; + import PrimaryNavigation from 'soapbox/components/primary_navigation'; +import LinkFooter from 'soapbox/features/ui/components/link_footer'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { PromoPanel, FeaturesPanel, InstanceInfoPanel, InstanceModerationPanel, } from 'soapbox/features/ui/util/async-components'; -import LinkFooter from 'soapbox/features/ui/components/link_footer'; -import { federationRestrictionsDisclosed } from 'soapbox/utils/state'; import { isAdmin } from 'soapbox/utils/accounts'; +import { federationRestrictionsDisclosed } from 'soapbox/utils/state'; const mapStateToProps = state => { const me = state.get('me'); diff --git a/app/soapbox/pages/status_page.js b/app/soapbox/pages/status_page.js index fa28193ca..eab6c2ebe 100644 --- a/app/soapbox/pages/status_page.js +++ b/app/soapbox/pages/status_page.js @@ -1,9 +1,10 @@ import React from 'react'; -import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; import Sticky from 'react-stickynode'; -import BundleContainer from '../features/ui/containers/bundle_container'; + import PrimaryNavigation from 'soapbox/components/primary_navigation'; +import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { WhoToFollowPanel, TrendsPanel, @@ -12,9 +13,10 @@ import { SignUpPanel, } from 'soapbox/features/ui/util/async-components'; // import GroupSidebarPanel from '../features/groups/sidebar_panel'; -import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { getFeatures } from 'soapbox/utils/features'; +import BundleContainer from '../features/ui/containers/bundle_container'; + const mapStateToProps = state => { const me = state.get('me'); const features = getFeatures(state.get('instance')); @@ -63,6 +65,9 @@ class StatusPage extends ImmutablePureComponent { {Component => } )} + + {Component => } + {showTrendsPanel && ( {Component => } @@ -73,9 +78,6 @@ class StatusPage extends ImmutablePureComponent { {Component => } )} - - {Component => } -
      diff --git a/app/soapbox/reducers/__tests__/accounts-test.js b/app/soapbox/reducers/__tests__/accounts-test.js index 10cefb3fd..f70695927 100644 --- a/app/soapbox/reducers/__tests__/accounts-test.js +++ b/app/soapbox/reducers/__tests__/accounts-test.js @@ -1,5 +1,6 @@ -import reducer from '../accounts'; import { Map as ImmutableMap } from 'immutable'; + +import reducer from '../accounts'; // import * as actions from 'soapbox/actions/importer'; // import { take } from 'lodash'; // import accounts from 'soapbox/__fixtures__/accounts.json'; diff --git a/app/soapbox/reducers/__tests__/accounts_counters-test.js b/app/soapbox/reducers/__tests__/accounts_counters-test.js index e708e9deb..8985179c5 100644 --- a/app/soapbox/reducers/__tests__/accounts_counters-test.js +++ b/app/soapbox/reducers/__tests__/accounts_counters-test.js @@ -1,5 +1,6 @@ -import reducer from '../accounts_counters'; import { Map as ImmutableMap } from 'immutable'; + +import reducer from '../accounts_counters'; // import { ACCOUNT_FOLLOW_SUCCESS, ACCOUNT_UNFOLLOW_SUCCESS } from 'soapbox/actions/accounts'; // import relationship from 'soapbox/__fixtures__/relationship.json'; // import accounts_counter_initial from 'soapbox/__fixtures__/accounts_counter_initial.json'; diff --git a/app/soapbox/reducers/__tests__/admin-test.js b/app/soapbox/reducers/__tests__/admin-test.js index e56eff6e9..807bdd02e 100644 --- a/app/soapbox/reducers/__tests__/admin-test.js +++ b/app/soapbox/reducers/__tests__/admin-test.js @@ -1,10 +1,11 @@ -import reducer from '../admin'; import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, } from 'immutable'; +import reducer from '../admin'; + describe('admin reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/alerts-test.js b/app/soapbox/reducers/__tests__/alerts-test.js index ab935b45c..7059c843f 100644 --- a/app/soapbox/reducers/__tests__/alerts-test.js +++ b/app/soapbox/reducers/__tests__/alerts-test.js @@ -1,7 +1,9 @@ -import reducer from '../alerts'; import { List as ImmutableList } from 'immutable'; + import * as actions from 'soapbox/actions/alerts'; +import reducer from '../alerts'; + describe('alerts reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableList()); diff --git a/app/soapbox/reducers/__tests__/auth-test.js b/app/soapbox/reducers/__tests__/auth-test.js index f138ebe90..b90a1be65 100644 --- a/app/soapbox/reducers/__tests__/auth-test.js +++ b/app/soapbox/reducers/__tests__/auth-test.js @@ -1,5 +1,5 @@ -import reducer from '../auth'; import { Map as ImmutableMap, fromJS } from 'immutable'; + import { AUTH_APP_CREATED, AUTH_LOGGED_IN, @@ -11,6 +11,8 @@ import { import { ME_FETCH_SKIP } from 'soapbox/actions/me'; import { MASTODON_PRELOAD_IMPORT } from 'soapbox/actions/preload'; +import reducer from '../auth'; + describe('auth reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/compose-test.js b/app/soapbox/reducers/__tests__/compose-test.js index a3b1781e4..348739a6b 100644 --- a/app/soapbox/reducers/__tests__/compose-test.js +++ b/app/soapbox/reducers/__tests__/compose-test.js @@ -1,11 +1,13 @@ -import reducer from '../compose'; import { Map as ImmutableMap } from 'immutable'; + +import * as actions from 'soapbox/actions/compose'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me'; import { SETTING_CHANGE } from 'soapbox/actions/settings'; -import * as actions from 'soapbox/actions/compose'; //import { REDRAFT } from 'soapbox/actions/statuses'; import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; +import reducer from '../compose'; + describe('compose reducer', () => { it('returns the initial state by default', () => { const state = reducer(undefined, {}); diff --git a/app/soapbox/reducers/__tests__/contexts-test.js b/app/soapbox/reducers/__tests__/contexts-test.js index 054888cec..26d6ecb39 100644 --- a/app/soapbox/reducers/__tests__/contexts-test.js +++ b/app/soapbox/reducers/__tests__/contexts-test.js @@ -1,13 +1,15 @@ -import reducer from '../contexts'; -import { CONTEXT_FETCH_SUCCESS } from 'soapbox/actions/statuses'; -import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS, } from 'immutable'; + import context1 from 'soapbox/__fixtures__/context_1.json'; import context2 from 'soapbox/__fixtures__/context_2.json'; +import { CONTEXT_FETCH_SUCCESS } from 'soapbox/actions/statuses'; +import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; + +import reducer from '../contexts'; describe('contexts reducer', () => { it('should return the initial state', () => { diff --git a/app/soapbox/reducers/__tests__/conversations-test.js b/app/soapbox/reducers/__tests__/conversations-test.js index c8379d59e..496ea620d 100644 --- a/app/soapbox/reducers/__tests__/conversations-test.js +++ b/app/soapbox/reducers/__tests__/conversations-test.js @@ -1,7 +1,9 @@ -import reducer from '../conversations'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import * as actions from 'soapbox/actions/conversations'; +import reducer from '../conversations'; + describe('conversations reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/custom_emojis-test.js b/app/soapbox/reducers/__tests__/custom_emojis-test.js index 17cd1248f..43fec78ec 100644 --- a/app/soapbox/reducers/__tests__/custom_emojis-test.js +++ b/app/soapbox/reducers/__tests__/custom_emojis-test.js @@ -1,6 +1,7 @@ -import reducer from '../custom_emojis'; import { List as ImmutableList } from 'immutable'; +import reducer from '../custom_emojis'; + describe('custom_emojis reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableList()); diff --git a/app/soapbox/reducers/__tests__/domain_lists-test.js b/app/soapbox/reducers/__tests__/domain_lists-test.js index 94003121c..e81bfbdf5 100644 --- a/app/soapbox/reducers/__tests__/domain_lists-test.js +++ b/app/soapbox/reducers/__tests__/domain_lists-test.js @@ -1,6 +1,7 @@ -import reducer from '../domain_lists'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import reducer from '../domain_lists'; + describe('domain_lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/dropdown_menu-test.js b/app/soapbox/reducers/__tests__/dropdown_menu-test.js index c618adf52..5d2977005 100644 --- a/app/soapbox/reducers/__tests__/dropdown_menu-test.js +++ b/app/soapbox/reducers/__tests__/dropdown_menu-test.js @@ -1,6 +1,7 @@ -import reducer from '../dropdown_menu'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../dropdown_menu'; + describe('dropdown_menu reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/filters-test.js b/app/soapbox/reducers/__tests__/filters-test.js index 1d0eab250..90bfc1323 100644 --- a/app/soapbox/reducers/__tests__/filters-test.js +++ b/app/soapbox/reducers/__tests__/filters-test.js @@ -1,6 +1,7 @@ -import reducer from '../filters'; import { List as ImmutableList } from 'immutable'; +import reducer from '../filters'; + describe('filters reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableList()); diff --git a/app/soapbox/reducers/__tests__/group_editor-test.js b/app/soapbox/reducers/__tests__/group_editor-test.js index 2008d6fd9..73c9e1b6a 100644 --- a/app/soapbox/reducers/__tests__/group_editor-test.js +++ b/app/soapbox/reducers/__tests__/group_editor-test.js @@ -1,6 +1,7 @@ -import reducer from '../group_editor'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../group_editor'; + describe('group_editor reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/group_lists-test.js b/app/soapbox/reducers/__tests__/group_lists-test.js index 802c394ce..fa5c21eea 100644 --- a/app/soapbox/reducers/__tests__/group_lists-test.js +++ b/app/soapbox/reducers/__tests__/group_lists-test.js @@ -1,6 +1,7 @@ -import reducer from '../group_lists'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import reducer from '../group_lists'; + describe('group_lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/group_relationships-test.js b/app/soapbox/reducers/__tests__/group_relationships-test.js index d0fead807..17cabf3c2 100644 --- a/app/soapbox/reducers/__tests__/group_relationships-test.js +++ b/app/soapbox/reducers/__tests__/group_relationships-test.js @@ -1,6 +1,7 @@ -import reducer from '../group_relationships'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../group_relationships'; + describe('group_relationships reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/groups-test.js b/app/soapbox/reducers/__tests__/groups-test.js index 933d7cf0e..94a1a6ffe 100644 --- a/app/soapbox/reducers/__tests__/groups-test.js +++ b/app/soapbox/reducers/__tests__/groups-test.js @@ -1,6 +1,7 @@ -import reducer from '../groups'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../groups'; + describe('groups reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/height_cache-test.js b/app/soapbox/reducers/__tests__/height_cache-test.js index c964bfb62..4b3ed8c21 100644 --- a/app/soapbox/reducers/__tests__/height_cache-test.js +++ b/app/soapbox/reducers/__tests__/height_cache-test.js @@ -1,5 +1,6 @@ -import reducer from '../height_cache'; import { Map as ImmutableMap } from 'immutable'; + +import reducer from '../height_cache'; import { HEIGHT_CACHE_CLEAR } from '../height_cache'; describe('height_cache reducer', () => { diff --git a/app/soapbox/reducers/__tests__/identity_proofs-test.js b/app/soapbox/reducers/__tests__/identity_proofs-test.js index 6284b41d3..fd004bfa8 100644 --- a/app/soapbox/reducers/__tests__/identity_proofs-test.js +++ b/app/soapbox/reducers/__tests__/identity_proofs-test.js @@ -1,7 +1,9 @@ -import reducer from '../identity_proofs'; import { Map as ImmutableMap } from 'immutable'; + import * as actions from 'soapbox/actions/identity_proofs'; +import reducer from '../identity_proofs'; + describe('identity_proofs reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/instance-test.js b/app/soapbox/reducers/__tests__/instance-test.js index a2ed8545b..17eae2e52 100644 --- a/app/soapbox/reducers/__tests__/instance-test.js +++ b/app/soapbox/reducers/__tests__/instance-test.js @@ -1,18 +1,114 @@ -import reducer from '../instance'; import { Map as ImmutableMap } from 'immutable'; +import { INSTANCE_REMEMBER_SUCCESS } from 'soapbox/actions/instance'; + +import reducer from '../instance'; + describe('instance reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ - max_toot_chars: 500, description_limit: 1500, - poll_limits: ImmutableMap({ - max_expiration: 2629746, - max_option_chars: 25, - max_options: 4, - min_expiration: 300, + configuration: ImmutableMap({ + statuses: ImmutableMap({ + max_characters: 500, + max_media_attachments: 4, + }), + polls: ImmutableMap({ + max_options: 4, + max_characters_per_option: 25, + min_expiration: 300, + max_expiration: 2629746, + }), }), version: '0.0.0', })); }); + + describe('INSTANCE_REMEMBER_SUCCESS', () => { + it('normalizes Pleroma instance with Mastodon configuration format', () => { + const action = { + type: INSTANCE_REMEMBER_SUCCESS, + instance: require('soapbox/__fixtures__/pleroma-instance.json'), + }; + + const result = reducer(undefined, action); + + const expected = { + configuration: { + statuses: { + max_characters: 5000, + max_media_attachments: Infinity, + }, + polls: { + max_options: 20, + max_characters_per_option: 200, + min_expiration: 0, + max_expiration: 31536000, + }, + }, + }; + + expect(result.toJS()).toMatchObject(expected); + }); + + it('normalizes Mastodon instance with retained configuration', () => { + const action = { + type: INSTANCE_REMEMBER_SUCCESS, + instance: require('soapbox/__fixtures__/mastodon-instance.json'), + }; + + const result = reducer(undefined, action); + + const expected = { + configuration: { + statuses: { + max_characters: 500, + max_media_attachments: 4, + characters_reserved_per_url: 23, + }, + media_attachments: { + image_size_limit: 10485760, + image_matrix_limit: 16777216, + video_size_limit: 41943040, + video_frame_rate_limit: 60, + video_matrix_limit: 2304000, + }, + polls: { + max_options: 4, + max_characters_per_option: 50, + min_expiration: 300, + max_expiration: 2629746, + }, + }, + }; + + expect(result.toJS()).toMatchObject(expected); + }); + + it('normalizes Mastodon 3.0.0 instance with default configuration', () => { + const action = { + type: INSTANCE_REMEMBER_SUCCESS, + instance: require('soapbox/__fixtures__/mastodon-3.0.0-instance.json'), + }; + + const result = reducer(undefined, action); + + const expected = { + configuration: { + statuses: { + max_characters: 500, + max_media_attachments: 4, + }, + polls: { + max_options: 4, + max_characters_per_option: 25, + min_expiration: 300, + max_expiration: 2629746, + }, + }, + }; + + expect(result.toJS()).toMatchObject(expected); + }); + }); }); diff --git a/app/soapbox/reducers/__tests__/list_adder-test.js b/app/soapbox/reducers/__tests__/list_adder-test.js index 9c34cee17..bda177fb4 100644 --- a/app/soapbox/reducers/__tests__/list_adder-test.js +++ b/app/soapbox/reducers/__tests__/list_adder-test.js @@ -1,7 +1,9 @@ -import reducer from '../list_adder'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import * as actions from 'soapbox/actions/lists'; +import reducer from '../list_adder'; + describe('list_adder reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/list_editor-test.js b/app/soapbox/reducers/__tests__/list_editor-test.js index 09ec6ab02..0fe2ec121 100644 --- a/app/soapbox/reducers/__tests__/list_editor-test.js +++ b/app/soapbox/reducers/__tests__/list_editor-test.js @@ -1,7 +1,9 @@ -import reducer from '../list_editor'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import * as actions from 'soapbox/actions/lists'; +import reducer from '../list_editor'; + describe('list_editor reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/lists-test.js b/app/soapbox/reducers/__tests__/lists-test.js index 52a7d28f0..56afd7a5c 100644 --- a/app/soapbox/reducers/__tests__/lists-test.js +++ b/app/soapbox/reducers/__tests__/lists-test.js @@ -1,6 +1,7 @@ -import reducer from '../lists'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../lists'; + describe('lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/meta-test.js b/app/soapbox/reducers/__tests__/meta-test.js index 59542cba5..cfdf882cb 100644 --- a/app/soapbox/reducers/__tests__/meta-test.js +++ b/app/soapbox/reducers/__tests__/meta-test.js @@ -1,6 +1,7 @@ -import reducer from '../meta'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../meta'; + describe('meta reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/modal-test.js b/app/soapbox/reducers/__tests__/modal-test.js deleted file mode 100644 index 09281e82f..000000000 --- a/app/soapbox/reducers/__tests__/modal-test.js +++ /dev/null @@ -1,42 +0,0 @@ -import reducer from '../modal'; -import { MODAL_OPEN, MODAL_CLOSE } from 'soapbox/actions/modal'; - -describe('modal reducer', () => { - it('should return the initial state', () => { - expect(reducer(undefined, {})).toEqual({ - modalType: null, - modalProps: {}, - }); - }); - - it('should handle MODAL_OPEN', () => { - const state = { - modalType: null, - modalProps: {}, - }; - const action = { - type: MODAL_OPEN, - modalType: 'type1', - modalProps: { props1: '1' }, - }; - expect(reducer(state, action)).toMatchObject({ - modalType: 'type1', - modalProps: { props1: '1' }, - }); - }); - - it('should handle MODAL_CLOSE', () => { - const state = { - modalType: 'type1', - modalProps: { props1: '1' }, - }; - const action = { - type: MODAL_CLOSE, - }; - expect(reducer(state, action)).toMatchObject({ - modalType: null, - modalProps: {}, - }); - }); - -}); diff --git a/app/soapbox/reducers/__tests__/modals-test.js b/app/soapbox/reducers/__tests__/modals-test.js new file mode 100644 index 000000000..3873d0a76 --- /dev/null +++ b/app/soapbox/reducers/__tests__/modals-test.js @@ -0,0 +1,57 @@ +import { List as ImmutableList } from 'immutable'; + +import { MODAL_OPEN, MODAL_CLOSE } from 'soapbox/actions/modals'; + +import reducer from '../modals'; + +describe('modal reducer', () => { + it('should return the initial state', () => { + expect(reducer(undefined, {})).toEqual(ImmutableList()); + }); + + it('should handle MODAL_OPEN', () => { + const state = ImmutableList(); + const action = { + type: MODAL_OPEN, + modalType: 'type1', + modalProps: { props1: '1' }, + }; + expect(reducer(state, action)).toMatchObject(ImmutableList([{ + modalType: 'type1', + modalProps: { props1: '1' }, + }])); + }); + + it('should handle MODAL_CLOSE', () => { + const state = ImmutableList([{ + modalType: 'type1', + modalProps: { props1: '1' }, + }]); + const action = { + type: MODAL_CLOSE, + }; + expect(reducer(state, action)).toMatchObject(ImmutableList()); + }); + + it('should handle MODAL_CLOSE with specified modalType', () => { + const state = ImmutableList([ + { + modalType: 'type1', + }, + { + modalType: 'type2', + }, + { + modalType: 'type1', + }, + ]); + const action = { + type: MODAL_CLOSE, + modalType: 'type2', + }; + expect(reducer(state, action)).toMatchObject(ImmutableList([{ + modalType: 'type1', + }])); + }); + +}); diff --git a/app/soapbox/reducers/__tests__/mutes-test.js b/app/soapbox/reducers/__tests__/mutes-test.js index bdf58bba4..175f2ff38 100644 --- a/app/soapbox/reducers/__tests__/mutes-test.js +++ b/app/soapbox/reducers/__tests__/mutes-test.js @@ -1,10 +1,12 @@ -import reducer from '../mutes'; import { Map as ImmutableMap } from 'immutable'; + import { MUTES_INIT_MODAL, MUTES_TOGGLE_HIDE_NOTIFICATIONS, } from 'soapbox/actions/mutes'; +import reducer from '../mutes'; + describe('mutes reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/notifications-test.js b/app/soapbox/reducers/__tests__/notifications-test.js index 581c4b38e..5c65341cc 100644 --- a/app/soapbox/reducers/__tests__/notifications-test.js +++ b/app/soapbox/reducers/__tests__/notifications-test.js @@ -1,18 +1,31 @@ -import * as actions from 'soapbox/actions/notifications'; -import reducer from '../notifications'; -import notifications from 'soapbox/__fixtures__/notifications.json'; -import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap } from 'immutable'; +import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap, fromJS } from 'immutable'; import { take } from 'lodash'; -import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts'; -import notification from 'soapbox/__fixtures__/notification.json'; + import intlMessages from 'soapbox/__fixtures__/intlMessages.json'; +import notification from 'soapbox/__fixtures__/notification.json'; +import notifications from 'soapbox/__fixtures__/notifications.json'; import relationship from 'soapbox/__fixtures__/relationship.json'; -import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; +import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts'; import { MARKER_FETCH_SUCCESS, MARKER_SAVE_REQUEST, MARKER_SAVE_SUCCESS, } from 'soapbox/actions/markers'; +import { + NOTIFICATIONS_EXPAND_SUCCESS, + NOTIFICATIONS_EXPAND_REQUEST, + NOTIFICATIONS_EXPAND_FAIL, + NOTIFICATIONS_FILTER_SET, + NOTIFICATIONS_SCROLL_TOP, + NOTIFICATIONS_UPDATE, + NOTIFICATIONS_UPDATE_QUEUE, + NOTIFICATIONS_DEQUEUE, + NOTIFICATIONS_CLEAR, + NOTIFICATIONS_MARK_READ_REQUEST, +} from 'soapbox/actions/notifications'; +import { TIMELINE_DELETE } from 'soapbox/actions/timelines'; + +import reducer from '../notifications'; describe('notifications reducer', () => { it('should return the initial state', () => { @@ -28,55 +41,89 @@ describe('notifications reducer', () => { })); }); - it('should handle NOTIFICATIONS_EXPAND_SUCCESS', () => { - const state = undefined; - const action = { - type: actions.NOTIFICATIONS_EXPAND_SUCCESS, - notifications: take(notifications, 3), - next: null, - skipLoading: true, - }; - expect(reducer(state, action)).toEqual(ImmutableMap({ - items: ImmutableOrderedMap([ - ['10744', ImmutableMap({ - id: '10744', - type: 'pleroma:emoji_reaction', - account: '9vMAje101ngtjlMj7w', + describe('NOTIFICATIONS_EXPAND_SUCCESS', () => { + it('imports the notifications', () => { + const state = undefined; + + const action = { + type: NOTIFICATIONS_EXPAND_SUCCESS, + notifications: take(notifications, 3), + next: null, + skipLoading: true, + }; + + expect(reducer(state, action)).toEqual(ImmutableMap({ + items: ImmutableOrderedMap([ + ['10744', ImmutableMap({ + id: '10744', + type: 'pleroma:emoji_reaction', + account: '9vMAje101ngtjlMj7w', + target: null, + created_at: '2020-06-10T02:54:39.000Z', + status: '9vvNxoo5EFbbnfdXQu', + emoji: '😢', + chat_message: undefined, + })], + ['10743', ImmutableMap({ + id: '10743', + type: 'favourite', + account: '9v5c6xSEgAi3Zu1Lv6', + target: null, + created_at: '2020-06-10T02:51:05.000Z', + status: '9vvNxoo5EFbbnfdXQu', + emoji: undefined, + chat_message: undefined, + })], + ['10741', ImmutableMap({ + id: '10741', + type: 'favourite', + account: '9v5cKMOPGqPcgfcWp6', + target: null, + created_at: '2020-06-10T02:05:06.000Z', + status: '9vvNxoo5EFbbnfdXQu', + emoji: undefined, + chat_message: undefined, + })], + ]), + hasMore: false, + top: false, + unread: 0, + isLoading: false, + queuedNotifications: ImmutableOrderedMap(), + totalQueuedNotificationsCount: 0, + lastRead: -1, + })); + }); + + it('drops invalid notifications', () => { + const action = { + type: NOTIFICATIONS_EXPAND_SUCCESS, + notifications: [ + { id: '1', type: 'mention', status: null, account: { id: '10' } }, + { id: '2', type: 'reblog', status: null, account: { id: '9' } }, + { id: '3', type: 'favourite', status: null, account: { id: '8' } }, + { id: '4', type: 'mention', status: { id: 'a' }, account: { id: '7' } }, + { id: '5', type: 'reblog', status: { id: 'b' }, account: null }, + ], + next: null, + skipLoading: true, + }; + + const expected = ImmutableOrderedMap([ + ['4', fromJS({ + id: '4', + type: 'mention', + account: '7', target: null, - created_at: '2020-06-10T02:54:39.000Z', - status: '9vvNxoo5EFbbnfdXQu', - emoji: '😢', - chat_message: undefined, - })], - ['10743', ImmutableMap({ - id: '10743', - type: 'favourite', - account: '9v5c6xSEgAi3Zu1Lv6', - target: null, - created_at: '2020-06-10T02:51:05.000Z', - status: '9vvNxoo5EFbbnfdXQu', + created_at: undefined, + status: 'a', emoji: undefined, chat_message: undefined, })], - ['10741', ImmutableMap({ - id: '10741', - type: 'favourite', - account: '9v5cKMOPGqPcgfcWp6', - target: null, - created_at: '2020-06-10T02:05:06.000Z', - status: '9vvNxoo5EFbbnfdXQu', - emoji: undefined, - chat_message: undefined, - })], - ]), - hasMore: false, - top: false, - unread: 0, - isLoading: false, - queuedNotifications: ImmutableOrderedMap(), - totalQueuedNotificationsCount: 0, - lastRead: -1, - })); + ]); + + expect(reducer(undefined, action).get('items')).toEqual(expected); + }); }); it('should handle NOTIFICATIONS_EXPAND_REQUEST', () => { @@ -84,7 +131,7 @@ describe('notifications reducer', () => { isLoading: false, }); const action = { - type: actions.NOTIFICATIONS_EXPAND_REQUEST, + type: NOTIFICATIONS_EXPAND_REQUEST, }; expect(reducer(state, action)).toEqual(ImmutableMap({ isLoading: true, @@ -96,7 +143,7 @@ describe('notifications reducer', () => { isLoading: true, }); const action = { - type: actions.NOTIFICATIONS_EXPAND_FAIL, + type: NOTIFICATIONS_EXPAND_FAIL, }; expect(reducer(state, action)).toEqual(ImmutableMap({ isLoading: false, @@ -146,7 +193,7 @@ describe('notifications reducer', () => { lastRead: -1, }); const action = { - type: actions.NOTIFICATIONS_FILTER_SET, + type: NOTIFICATIONS_FILTER_SET, }; expect(reducer(state, action)).toEqual(ImmutableMap({ items: ImmutableOrderedMap(), @@ -165,7 +212,7 @@ describe('notifications reducer', () => { unread: 1, }); const action = { - type: actions.NOTIFICATIONS_SCROLL_TOP, + type: NOTIFICATIONS_SCROLL_TOP, top: true, }; expect(reducer(state, action)).toEqual(ImmutableMap({ @@ -179,7 +226,7 @@ describe('notifications reducer', () => { unread: 3, }); const action = { - type: actions.NOTIFICATIONS_SCROLL_TOP, + type: NOTIFICATIONS_SCROLL_TOP, top: false, }; expect(reducer(state, action)).toEqual(ImmutableMap({ @@ -195,7 +242,7 @@ describe('notifications reducer', () => { unread: 1, }); const action = { - type: actions.NOTIFICATIONS_UPDATE, + type: NOTIFICATIONS_UPDATE, notification: notification, }; expect(reducer(state, action)).toEqual(ImmutableMap({ @@ -223,7 +270,7 @@ describe('notifications reducer', () => { totalQueuedNotificationsCount: 0, }); const action = { - type: actions.NOTIFICATIONS_UPDATE_QUEUE, + type: NOTIFICATIONS_UPDATE_QUEUE, notification: notification, intlMessages: intlMessages, intlLocale: 'en', @@ -246,7 +293,7 @@ describe('notifications reducer', () => { totalQueuedNotificationsCount: 1, }); const action = { - type: actions.NOTIFICATIONS_DEQUEUE, + type: NOTIFICATIONS_DEQUEUE, }; expect(reducer(state, action)).toEqual(ImmutableMap({ items: ImmutableOrderedMap(), @@ -274,7 +321,7 @@ describe('notifications reducer', () => { isLoading: false, }); const action = { - type: actions.NOTIFICATIONS_EXPAND_SUCCESS, + type: NOTIFICATIONS_EXPAND_SUCCESS, notifications: take(notifications, 3), next: true, }; @@ -335,7 +382,7 @@ describe('notifications reducer', () => { isLoading: false, }); const action = { - type: actions.NOTIFICATIONS_EXPAND_SUCCESS, + type: NOTIFICATIONS_EXPAND_SUCCESS, notifications: take(notifications, 3), next: true, }; @@ -514,7 +561,7 @@ describe('notifications reducer', () => { hasMore: true, }); const action = { - type: actions.NOTIFICATIONS_CLEAR, + type: NOTIFICATIONS_CLEAR, }; expect(reducer(state, action)).toEqual(ImmutableMap({ items: ImmutableOrderedMap(), @@ -527,7 +574,7 @@ describe('notifications reducer', () => { items: ImmutableOrderedMap(), }); const action = { - type: actions.NOTIFICATIONS_MARK_READ_REQUEST, + type: NOTIFICATIONS_MARK_READ_REQUEST, lastRead: 35098814, }; expect(reducer(state, action)).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/patron-test.js b/app/soapbox/reducers/__tests__/patron-test.js index 8a6001913..b83d2c025 100644 --- a/app/soapbox/reducers/__tests__/patron-test.js +++ b/app/soapbox/reducers/__tests__/patron-test.js @@ -1,7 +1,8 @@ -import reducer from '../patron'; -import { PATRON_ACCOUNT_FETCH_SUCCESS } from '../../actions/patron'; import { Map as ImmutableMap, fromJS } from 'immutable'; +import { PATRON_ACCOUNT_FETCH_SUCCESS } from '../../actions/patron'; +import reducer from '../patron'; + describe('patron reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/polls-test.js b/app/soapbox/reducers/__tests__/polls-test.js index d78698b93..55b53a8b5 100644 --- a/app/soapbox/reducers/__tests__/polls-test.js +++ b/app/soapbox/reducers/__tests__/polls-test.js @@ -1,6 +1,7 @@ -import reducer from '../polls'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../polls'; + describe('polls reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/push_notifications-test.js b/app/soapbox/reducers/__tests__/push_notifications-test.js index 97e75df54..a5db7131d 100644 --- a/app/soapbox/reducers/__tests__/push_notifications-test.js +++ b/app/soapbox/reducers/__tests__/push_notifications-test.js @@ -1,17 +1,18 @@ -import reducer from '../push_notifications'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../push_notifications'; + describe('push_notifications reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ subscription: null, alerts: new ImmutableMap({ - follow: false, - follow_request: false, - favourite: false, - reblog: false, - mention: false, - poll: false, + follow: true, + follow_request: true, + favourite: true, + reblog: true, + mention: true, + poll: true, }), isSubscribed: false, browserSupport: false, diff --git a/app/soapbox/reducers/__tests__/relationships-test.js b/app/soapbox/reducers/__tests__/relationships-test.js index 657a94c44..e2cdaea33 100644 --- a/app/soapbox/reducers/__tests__/relationships-test.js +++ b/app/soapbox/reducers/__tests__/relationships-test.js @@ -1,9 +1,11 @@ -import reducer from '../relationships'; +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import lain from 'soapbox/__fixtures__/lain.json'; + import { ACCOUNT_IMPORT, } from '../../actions/importer'; -import lain from 'soapbox/__fixtures__/lain.json'; -import { Map as ImmutableMap, fromJS } from 'immutable'; +import reducer from '../relationships'; describe('relationships reducer', () => { it('should return the initial state', () => { diff --git a/app/soapbox/reducers/__tests__/reports-test.js b/app/soapbox/reducers/__tests__/reports-test.js index 761128786..2719652cd 100644 --- a/app/soapbox/reducers/__tests__/reports-test.js +++ b/app/soapbox/reducers/__tests__/reports-test.js @@ -1,6 +1,7 @@ -import reducer from '../reports'; import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; +import reducer from '../reports'; + describe('reports reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/search-test.js b/app/soapbox/reducers/__tests__/search-test.js index 6a872ab07..aa66b6849 100644 --- a/app/soapbox/reducers/__tests__/search-test.js +++ b/app/soapbox/reducers/__tests__/search-test.js @@ -1,9 +1,11 @@ -import reducer from '../search'; +import { Map as ImmutableMap } from 'immutable'; + import { SEARCH_CHANGE, SEARCH_CLEAR, } from 'soapbox/actions/search'; -import { Map as ImmutableMap } from 'immutable'; + +import reducer from '../search'; describe('search reducer', () => { it('should return the initial state', () => { diff --git a/app/soapbox/reducers/__tests__/settings-test.js b/app/soapbox/reducers/__tests__/settings-test.js index 897dfb556..b4574d55c 100644 --- a/app/soapbox/reducers/__tests__/settings-test.js +++ b/app/soapbox/reducers/__tests__/settings-test.js @@ -1,6 +1,7 @@ -import reducer from '../settings'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../settings'; + describe('settings reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/soapbox-test.js b/app/soapbox/reducers/__tests__/soapbox-test.js index ff06e7c69..20b67fb09 100644 --- a/app/soapbox/reducers/__tests__/soapbox-test.js +++ b/app/soapbox/reducers/__tests__/soapbox-test.js @@ -1,9 +1,11 @@ -import reducer from '../soapbox'; import { Map as ImmutableMap } from 'immutable'; -import * as actions from 'soapbox/actions/soapbox'; -import { ADMIN_CONFIG_UPDATE_SUCCESS } from 'soapbox/actions/admin'; -import soapbox from 'soapbox/__fixtures__/soapbox.json'; + import soapboxConfig from 'soapbox/__fixtures__/admin_api_frontend_config.json'; +import soapbox from 'soapbox/__fixtures__/soapbox.json'; +import { ADMIN_CONFIG_UPDATE_SUCCESS } from 'soapbox/actions/admin'; +import * as actions from 'soapbox/actions/soapbox'; + +import reducer from '../soapbox'; describe('soapbox reducer', () => { it('should return the initial state', () => { diff --git a/app/soapbox/reducers/__tests__/status_lists-test.js b/app/soapbox/reducers/__tests__/status_lists-test.js index e3e6a1971..e04a24377 100644 --- a/app/soapbox/reducers/__tests__/status_lists-test.js +++ b/app/soapbox/reducers/__tests__/status_lists-test.js @@ -1,6 +1,7 @@ -import reducer from '../status_lists'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import reducer from '../status_lists'; + describe('status_lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/statuses-test.js b/app/soapbox/reducers/__tests__/statuses-test.js index 00687224a..926c9a867 100644 --- a/app/soapbox/reducers/__tests__/statuses-test.js +++ b/app/soapbox/reducers/__tests__/statuses-test.js @@ -1,8 +1,114 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import { STATUS_IMPORT } from 'soapbox/actions/importer'; +import { normalizeStatus } from 'soapbox/actions/importer/normalizer'; +import { + STATUS_CREATE_REQUEST, + STATUS_CREATE_FAIL, +} from 'soapbox/actions/statuses'; + import reducer from '../statuses'; -import { Map as ImmutableMap } from 'immutable'; describe('statuses reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); }); + + describe('STATUS_IMPORT', () => { + it('fixes the order of mentions', () => { + const status = require('soapbox/__fixtures__/status-unordered-mentions.json'); + const action = { type: STATUS_IMPORT, status }; + + const expected = ['NEETzsche', 'alex', 'Lumeinshin', 'sneeden']; + + const result = reducer(undefined, action) + .getIn(['AFChectaqZjmOVkXZ2', 'mentions']) + .map(mention => mention.get('username')) + .toJS(); + + expect(result).toEqual(expected); + }); + + it('preserves the quote', () => { + const quotePost = require('soapbox/__fixtures__/pleroma-quote-post.json'); + const quotedQuotePost = require('soapbox/__fixtures__/pleroma-quote-of-quote-post.json'); + + let state = undefined; + state = reducer(state, { type: STATUS_IMPORT, status: normalizeStatus(quotePost) }); + state = reducer(state, { type: STATUS_IMPORT, status: normalizeStatus(quotedQuotePost.pleroma.quote) }); + + expect(state.getIn(['AFmFMSpITT9xcOJKcK', 'quote'])).toEqual('AFmFLcd6XYVdjWCrOS'); + }); + + it('normalizes Mitra attachments', () => { + const status = require('soapbox/__fixtures__/mitra-status-with-attachments.json'); + + const state = reducer(undefined, { type: STATUS_IMPORT, status: normalizeStatus(status) }); + + const expected = fromJS([{ + id: '017eeb0e-e5df-30a4-77a7-a929145cb836', + type: 'image', + url: 'https://mitra.social/media/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png', + preview_url: 'https://mitra.social/media/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png', + remote_url: 'https://mitra.social/media/8e04e6091bbbac79641b5812508683ce72c38693661c18d16040553f2371e18d.png', + }, { + id: '017eeb0e-e5e4-2a48-2889-afdebf368a54', + type: 'unknown', + url: 'https://mitra.social/media/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac', + preview_url: 'https://mitra.social/media/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac', + remote_url: 'https://mitra.social/media/8f72dc2e98572eb4ba7c3a902bca5f69c448fc4391837e5f8f0d4556280440ac', + }, { + id: '017eeb0e-e5e5-79fd-6054-8b6869b1db49', + type: 'unknown', + url: 'https://mitra.social/media/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.oga', + preview_url: 'https://mitra.social/media/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.oga', + remote_url: 'https://mitra.social/media/55a81a090247cc4fc127e5716bcf7964f6e0df9b584f85f4696c0b994747a4d0.oga', + }, { + id: '017eeb0e-e5e6-c416-a444-21e560c47839', + type: 'unknown', + url: 'https://mitra.social/media/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0', + preview_url: 'https://mitra.social/media/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0', + remote_url: 'https://mitra.social/media/0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0', + }]); + + expect(state.getIn(['017eeb0e-e5e7-98fe-6b2b-ad02349251fb', 'media_attachments'])).toEqual(expected); + }); + + it('leaves Pleroma attachments alone', () => { + const status = require('soapbox/__fixtures__/pleroma-status-with-attachments.json'); + const action = { type: STATUS_IMPORT, status: normalizeStatus(status) }; + const state = reducer(undefined, action); + const expected = fromJS(status.media_attachments); + + expect(state.getIn(['AGNkA21auFR5lnEAHw', 'media_attachments'])).toEqual(expected); + }); + }); + + describe('STATUS_CREATE_REQUEST', () => { + it('increments the replies_count of its parent', () => { + const state = fromJS({ '123': { replies_count: 4 } }); + + const action = { + type: STATUS_CREATE_REQUEST, + params: { in_reply_to_id: '123' }, + }; + + const result = reducer(state, action).getIn(['123', 'replies_count']); + expect(result).toEqual(5); + }); + }); + + describe('STATUS_CREATE_FAIL', () => { + it('decrements the replies_count of its parent', () => { + const state = fromJS({ '123': { replies_count: 5 } }); + + const action = { + type: STATUS_CREATE_FAIL, + params: { in_reply_to_id: '123' }, + }; + + const result = reducer(state, action).getIn(['123', 'replies_count']); + expect(result).toEqual(4); + }); + }); }); diff --git a/app/soapbox/reducers/__tests__/suggestions-test.js b/app/soapbox/reducers/__tests__/suggestions-test.js index 6740bd7ba..7da0b7f75 100644 --- a/app/soapbox/reducers/__tests__/suggestions-test.js +++ b/app/soapbox/reducers/__tests__/suggestions-test.js @@ -1,7 +1,9 @@ -import reducer from '../suggestions'; import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + import { SUGGESTIONS_DISMISS } from 'soapbox/actions/suggestions'; +import reducer from '../suggestions'; + describe('suggestions reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/timelines-test.js b/app/soapbox/reducers/__tests__/timelines-test.js index dfa5a62d4..b00a79ebd 100644 --- a/app/soapbox/reducers/__tests__/timelines-test.js +++ b/app/soapbox/reducers/__tests__/timelines-test.js @@ -1,11 +1,13 @@ -import reducer from '../timelines'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; + import { TIMELINE_EXPAND_REQUEST, TIMELINE_EXPAND_FAIL, TIMELINE_EXPAND_SUCCESS, } from 'soapbox/actions/timelines'; +import reducer from '../timelines'; + describe('timelines reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); diff --git a/app/soapbox/reducers/__tests__/trends-test.js b/app/soapbox/reducers/__tests__/trends-test.js index 9c14da46b..5ebeabb31 100644 --- a/app/soapbox/reducers/__tests__/trends-test.js +++ b/app/soapbox/reducers/__tests__/trends-test.js @@ -1,6 +1,7 @@ -import reducer from '../trends'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import reducer from '../trends'; + describe('trends reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ diff --git a/app/soapbox/reducers/__tests__/user_lists-test.js b/app/soapbox/reducers/__tests__/user_lists-test.js index 7d571e208..a168f3cdc 100644 --- a/app/soapbox/reducers/__tests__/user_lists-test.js +++ b/app/soapbox/reducers/__tests__/user_lists-test.js @@ -1,6 +1,7 @@ -import reducer from '../user_lists'; import { Map as ImmutableMap } from 'immutable'; +import reducer from '../user_lists'; + describe('user_lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap({ @@ -14,6 +15,8 @@ describe('user_lists reducer', () => { mutes: ImmutableMap(), groups: ImmutableMap(), groups_removed_accounts: ImmutableMap(), + pinned: ImmutableMap(), + birthday_reminders: ImmutableMap(), })); }); }); diff --git a/app/soapbox/reducers/accounts.js b/app/soapbox/reducers/accounts.js index fb0ac3ca6..c8b52dd37 100644 --- a/app/soapbox/reducers/accounts.js +++ b/app/soapbox/reducers/accounts.js @@ -1,17 +1,9 @@ -import { - ACCOUNT_IMPORT, - ACCOUNTS_IMPORT, - ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP, -} from '../actions/importer'; -import { CHATS_FETCH_SUCCESS, CHAT_FETCH_SUCCESS } from 'soapbox/actions/chats'; -import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; -import { normalizeAccount as normalizeAccount2 } from 'soapbox/actions/importer/normalizer'; import { Map as ImmutableMap, List as ImmutableList, fromJS, } from 'immutable'; -import { normalizePleromaUserFields } from 'soapbox/utils/pleroma'; + import { ADMIN_USERS_FETCH_SUCCESS, ADMIN_USERS_TAG_REQUEST, @@ -30,7 +22,21 @@ import { ADMIN_USERS_DELETE_FAIL, ADMIN_USERS_DEACTIVATE_REQUEST, ADMIN_USERS_DEACTIVATE_FAIL, + ADMIN_USERS_SUGGEST_REQUEST, + ADMIN_USERS_SUGGEST_FAIL, + ADMIN_USERS_UNSUGGEST_REQUEST, + ADMIN_USERS_UNSUGGEST_FAIL, } from 'soapbox/actions/admin'; +import { CHATS_FETCH_SUCCESS, CHATS_EXPAND_SUCCESS, CHAT_FETCH_SUCCESS } from 'soapbox/actions/chats'; +import { normalizeAccount as normalizeAccount2 } from 'soapbox/actions/importer/normalizer'; +import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; +import { normalizePleromaUserFields } from 'soapbox/utils/pleroma'; + +import { + ACCOUNT_IMPORT, + ACCOUNTS_IMPORT, + ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP, +} from '../actions/importer'; const initialState = ImmutableMap(); @@ -185,6 +191,14 @@ const importAdminUsers = (state, adminUsers) => { }); }; +const setSuggested = (state, accountIds, isSuggested) => { + return state.withMutations(state => { + accountIds.forEach(id => { + state.setIn([id, 'pleroma', 'is_suggested'], isSuggested); + }); + }); +}; + export default function accounts(state = initialState, action) { switch(action.type) { case ACCOUNT_IMPORT: @@ -196,6 +210,7 @@ export default function accounts(state = initialState, action) { username: action.username, })); case CHATS_FETCH_SUCCESS: + case CHATS_EXPAND_SUCCESS: return importAccountsFromChats(state, action.chats); case CHAT_FETCH_SUCCESS: case STREAMING_CHAT_UPDATE: @@ -224,6 +239,12 @@ export default function accounts(state = initialState, action) { return setActive(state, action.accountIds, true); case ADMIN_USERS_FETCH_SUCCESS: return importAdminUsers(state, action.users); + case ADMIN_USERS_SUGGEST_REQUEST: + case ADMIN_USERS_UNSUGGEST_FAIL: + return setSuggested(state, action.accountIds, true); + case ADMIN_USERS_UNSUGGEST_REQUEST: + case ADMIN_USERS_SUGGEST_FAIL: + return setSuggested(state, action.accountIds, false); default: return state; } diff --git a/app/soapbox/reducers/accounts_counters.js b/app/soapbox/reducers/accounts_counters.js index 392599244..60b9e8cab 100644 --- a/app/soapbox/reducers/accounts_counters.js +++ b/app/soapbox/reducers/accounts_counters.js @@ -1,10 +1,12 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming'; + import { ACCOUNT_FOLLOW_SUCCESS, ACCOUNT_UNFOLLOW_SUCCESS, } from '../actions/accounts'; import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer'; -import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const normalizeAccount = (state, account) => state.set(account.id, fromJS({ followers_count: account.followers_count, diff --git a/app/soapbox/reducers/accounts_meta.js b/app/soapbox/reducers/accounts_meta.js index 731568313..d3668d524 100644 --- a/app/soapbox/reducers/accounts_meta.js +++ b/app/soapbox/reducers/accounts_meta.js @@ -3,10 +3,11 @@ * @module soapbox/reducers/accounts_meta */ -import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me'; -import { VERIFY_CREDENTIALS_SUCCESS, AUTH_ACCOUNT_REMEMBER_SUCCESS } from 'soapbox/actions/auth'; import { Map as ImmutableMap, fromJS } from 'immutable'; +import { VERIFY_CREDENTIALS_SUCCESS, AUTH_ACCOUNT_REMEMBER_SUCCESS } from 'soapbox/actions/auth'; +import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me'; + const initialState = ImmutableMap(); const importAccount = (state, account) => { diff --git a/app/soapbox/reducers/admin.js b/app/soapbox/reducers/admin.js index 98fa3aa8a..1da0ef7aa 100644 --- a/app/soapbox/reducers/admin.js +++ b/app/soapbox/reducers/admin.js @@ -1,3 +1,12 @@ +import { + Map as ImmutableMap, + List as ImmutableList, + Set as ImmutableSet, + OrderedSet as ImmutableOrderedSet, + fromJS, + is, +} from 'immutable'; + import { ADMIN_CONFIG_FETCH_SUCCESS, ADMIN_CONFIG_UPDATE_SUCCESS, @@ -10,14 +19,6 @@ import { ADMIN_USERS_APPROVE_REQUEST, ADMIN_USERS_APPROVE_SUCCESS, } from '../actions/admin'; -import { - Map as ImmutableMap, - List as ImmutableList, - Set as ImmutableSet, - OrderedSet as ImmutableOrderedSet, - fromJS, - is, -} from 'immutable'; const initialState = ImmutableMap({ reports: ImmutableMap(), diff --git a/app/soapbox/reducers/admin_log.js b/app/soapbox/reducers/admin_log.js index b8abc39e0..9008de52b 100644 --- a/app/soapbox/reducers/admin_log.js +++ b/app/soapbox/reducers/admin_log.js @@ -1,10 +1,11 @@ -import { ADMIN_LOG_FETCH_SUCCESS } from 'soapbox/actions/admin'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS, } from 'immutable'; +import { ADMIN_LOG_FETCH_SUCCESS } from 'soapbox/actions/admin'; + const initialState = ImmutableMap({ items: ImmutableMap(), index: ImmutableOrderedSet(), diff --git a/app/soapbox/reducers/alerts.js b/app/soapbox/reducers/alerts.js index f0b3f7968..79fad30e6 100644 --- a/app/soapbox/reducers/alerts.js +++ b/app/soapbox/reducers/alerts.js @@ -1,9 +1,10 @@ +import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { ALERT_SHOW, ALERT_DISMISS, ALERT_CLEAR, } from '../actions/alerts'; -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; const initialState = ImmutableList([]); @@ -15,6 +16,8 @@ export default function alerts(state = initialState, action) { title: action.title, message: action.message, severity: action.severity || 'info', + actionLabel: action.actionLabel, + actionLink: action.actionLink, })); case ALERT_DISMISS: return state.filterNot(item => item.get('key') === action.alert.key); diff --git a/app/soapbox/reducers/aliases.js b/app/soapbox/reducers/aliases.js index 4f3b86a69..158e91158 100644 --- a/app/soapbox/reducers/aliases.js +++ b/app/soapbox/reducers/aliases.js @@ -1,11 +1,17 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { ALIASES_SUGGESTIONS_READY, ALIASES_SUGGESTIONS_CLEAR, ALIASES_SUGGESTIONS_CHANGE, + ALIASES_FETCH_SUCCESS, } from '../actions/aliases'; const initialState = ImmutableMap({ + aliases: ImmutableMap({ + loaded: false, + items: ImmutableList(), + }), suggestions: ImmutableMap({ value: '', loaded: false, @@ -15,6 +21,9 @@ const initialState = ImmutableMap({ export default function aliasesReducer(state = initialState, action) { switch(action.type) { + case ALIASES_FETCH_SUCCESS: + return state + .setIn(['aliases', 'items'], action.value); case ALIASES_SUGGESTIONS_CHANGE: return state .setIn(['suggestions', 'value'], action.value) diff --git a/app/soapbox/reducers/auth.js b/app/soapbox/reducers/auth.js index 8a74a90e2..a4b649441 100644 --- a/app/soapbox/reducers/auth.js +++ b/app/soapbox/reducers/auth.js @@ -1,3 +1,11 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; +import { trim } from 'lodash'; + +import { MASTODON_PRELOAD_IMPORT } from 'soapbox/actions/preload'; +import { FE_SUBDIRECTORY } from 'soapbox/build_config'; +import KVStore from 'soapbox/storage/kv_store'; +import { validId, isURL } from 'soapbox/utils/auth'; + import { AUTH_APP_CREATED, AUTH_LOGGED_IN, @@ -8,12 +16,6 @@ import { VERIFY_CREDENTIALS_FAIL, } from '../actions/auth'; import { ME_FETCH_SKIP } from '../actions/me'; -import { MASTODON_PRELOAD_IMPORT } from 'soapbox/actions/preload'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; -import { validId, isURL } from 'soapbox/utils/auth'; -import { trim } from 'lodash'; -import { FE_SUBDIRECTORY } from 'soapbox/build_config'; -import KVStore from 'soapbox/storage/kv_store'; const defaultState = ImmutableMap({ app: ImmutableMap(), @@ -262,7 +264,7 @@ const persistAuthAccount = account => { }; const deleteForbiddenToken = (state, error, token) => { - if (error.response && [401, 403].includes(error.response.status)) { + if ([401, 403].includes(error.response?.status)) { return deleteToken(state, token); } else { return state; diff --git a/app/soapbox/reducers/backups.js b/app/soapbox/reducers/backups.js index fdfece138..349b9012a 100644 --- a/app/soapbox/reducers/backups.js +++ b/app/soapbox/reducers/backups.js @@ -1,8 +1,9 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { BACKUPS_FETCH_SUCCESS, BACKUPS_CREATE_SUCCESS, } from '../actions/backups'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/chat_message_lists.js b/app/soapbox/reducers/chat_message_lists.js index 777eddb19..9939885e6 100644 --- a/app/soapbox/reducers/chat_message_lists.js +++ b/app/soapbox/reducers/chat_message_lists.js @@ -1,12 +1,14 @@ +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + import { CHATS_FETCH_SUCCESS, + CHATS_EXPAND_SUCCESS, CHAT_MESSAGES_FETCH_SUCCESS, CHAT_MESSAGE_SEND_REQUEST, CHAT_MESSAGE_SEND_SUCCESS, CHAT_MESSAGE_DELETE_SUCCESS, } from 'soapbox/actions/chats'; import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; const initialState = ImmutableMap(); @@ -47,6 +49,7 @@ export default function chatMessageLists(state = initialState, action) { case CHAT_MESSAGE_SEND_REQUEST: return updateList(state, action.chatId, [action.uuid]); case CHATS_FETCH_SUCCESS: + case CHATS_EXPAND_SUCCESS: return importLastMessages(state, action.chats); case STREAMING_CHAT_UPDATE: if (action.chat.last_message && diff --git a/app/soapbox/reducers/chat_messages.js b/app/soapbox/reducers/chat_messages.js index 568725da3..a0787d077 100644 --- a/app/soapbox/reducers/chat_messages.js +++ b/app/soapbox/reducers/chat_messages.js @@ -1,5 +1,8 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { CHATS_FETCH_SUCCESS, + CHATS_EXPAND_SUCCESS, CHAT_MESSAGES_FETCH_SUCCESS, CHAT_MESSAGE_SEND_REQUEST, CHAT_MESSAGE_SEND_SUCCESS, @@ -7,7 +10,6 @@ import { CHAT_MESSAGE_DELETE_SUCCESS, } from 'soapbox/actions/chats'; import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); @@ -38,6 +40,7 @@ export default function chatMessages(state = initialState, action) { pending: true, })); case CHATS_FETCH_SUCCESS: + case CHATS_EXPAND_SUCCESS: return importLastMessages(state, fromJS(action.chats)); case CHAT_MESSAGES_FETCH_SUCCESS: return importMessages(state, fromJS(action.chatMessages)); diff --git a/app/soapbox/reducers/chats.js b/app/soapbox/reducers/chats.js index 56c2c4678..85447adc0 100644 --- a/app/soapbox/reducers/chats.js +++ b/app/soapbox/reducers/chats.js @@ -1,24 +1,40 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { CHATS_FETCH_SUCCESS, + CHATS_FETCH_REQUEST, + CHATS_EXPAND_SUCCESS, + CHATS_EXPAND_REQUEST, CHAT_FETCH_SUCCESS, CHAT_READ_SUCCESS, CHAT_READ_REQUEST, } from 'soapbox/actions/chats'; -import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; import { normalizeChat } from 'soapbox/actions/importer/normalizer'; -import { Map as ImmutableMap, fromJS } from 'immutable'; +import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; -const importChat = (state, chat) => state.set(chat.id, fromJS(normalizeChat(chat))); +const importChat = (state, chat) => state.setIn(['items', chat.id], fromJS(normalizeChat(chat))); -const importChats = (state, chats) => - state.withMutations(mutable => chats.forEach(chat => importChat(mutable, chat))); +const importChats = (state, chats, next) => + state.withMutations(mutable => { + if (next !== undefined) mutable.set('next', next); + chats.forEach(chat => importChat(mutable, chat)); + mutable.set('loading', false); + }); -const initialState = ImmutableMap(); +const initialState = ImmutableMap({ + next: null, + isLoading: false, + items: ImmutableMap({}), +}); export default function chats(state = initialState, action) { switch(action.type) { + case CHATS_FETCH_REQUEST: + case CHATS_EXPAND_REQUEST: + return state.set('loading', true); case CHATS_FETCH_SUCCESS: - return importChats(state, action.chats); + case CHATS_EXPAND_SUCCESS: + return importChats(state, action.chats, action.next); case STREAMING_CHAT_UPDATE: return importChats(state, [action.chat]); case CHAT_FETCH_SUCCESS: diff --git a/app/soapbox/reducers/compose.js b/app/soapbox/reducers/compose.js index 344dad6c1..c0ee4af0b 100644 --- a/app/soapbox/reducers/compose.js +++ b/app/soapbox/reducers/compose.js @@ -1,9 +1,15 @@ +import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; + +import { tagHistory } from 'soapbox/settings'; + import { COMPOSE_MOUNT, COMPOSE_UNMOUNT, COMPOSE_CHANGE, COMPOSE_REPLY, COMPOSE_REPLY_CANCEL, + COMPOSE_QUOTE, + COMPOSE_QUOTE_CANCEL, COMPOSE_DIRECT, COMPOSE_MENTION, COMPOSE_SUBMIT_REQUEST, @@ -39,15 +45,15 @@ import { COMPOSE_POLL_OPTION_CHANGE, COMPOSE_POLL_OPTION_REMOVE, COMPOSE_POLL_SETTINGS_CHANGE, + COMPOSE_ADD_TO_MENTIONS, + COMPOSE_REMOVE_FROM_MENTIONS, } from '../actions/compose'; -import { TIMELINE_DELETE } from '../actions/timelines'; -import { REDRAFT } from '../actions/statuses'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me'; import { SETTING_CHANGE, FE_NAME } from '../actions/settings'; -import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; -import { tagHistory } from 'soapbox/settings'; -import uuid from '../uuid'; +import { REDRAFT } from '../actions/statuses'; +import { TIMELINE_DELETE } from '../actions/timelines'; import { unescapeHTML } from '../utils/html'; +import uuid from '../uuid'; const initialState = ImmutableMap({ id: null, @@ -61,6 +67,7 @@ const initialState = ImmutableMap({ focusDate: null, caretPosition: null, in_reply_to: null, + quote: null, is_composing: false, is_submitting: false, is_changing_upload: false, @@ -84,7 +91,7 @@ const initialPoll = ImmutableMap({ multiple: false, }); -function statusToTextMentions(state, status, account) { +const statusToTextMentions = (state, status, account) => { const author = status.getIn(['account', 'acct']); const mentions = status.get('mentions', []).map(m => m.get('acct')); @@ -93,18 +100,38 @@ function statusToTextMentions(state, status, account) { .delete(account.get('acct')) .map(m => `@${m} `) .join(''); -} +}; + +export const statusToMentionsArray = (state, status, account) => { + const author = status.getIn(['account', 'acct']); + const mentions = status.get('mentions', []).map(m => m.get('acct')); + + return ImmutableOrderedSet([author]) + .concat(mentions) + .delete(account.get('acct')); +}; + +export const statusToMentionsAccountIdsArray = (state, status, account) => { + const author = status.getIn(['account', 'id']); + const mentions = status.get('mentions', []).map(m => m.get('id')); + + return ImmutableOrderedSet([author]) + .concat(mentions) + .delete(account.get('id')); +}; function clearAll(state) { return state.withMutations(map => { map.set('id', null); map.set('text', ''); + map.set('to', ImmutableOrderedSet()); map.set('spoiler', false); map.set('spoiler_text', ''); map.set('content_type', state.get('default_content_type')); map.set('is_submitting', false); map.set('is_changing_upload', false); map.set('in_reply_to', null); + map.set('quote', null); map.set('privacy', state.get('default_privacy')); map.set('sensitive', false); map.set('media_attachments', ImmutableList()); @@ -197,6 +224,17 @@ const expandMentions = status => { return fragment.innerHTML; }; +const getExplicitMentions = (me, status) => { + const fragment = domParser.parseFromString(status.get('content'), 'text/html').documentElement; + + const mentions = status + .get('mentions') + .filter(mention => !(fragment.querySelector(`a[href="${mention.get('url')}"]`) || mention.get('id') === me)) + .map(m => m.get('acct')); + + return ImmutableOrderedSet(mentions); +}; + const getAccountSettings = account => { return account.getIn(['pleroma', 'settings_store', FE_NAME], ImmutableMap()); }; @@ -290,7 +328,8 @@ export default function compose(state = initialState, action) { case COMPOSE_REPLY: return state.withMutations(map => { map.set('in_reply_to', action.status.get('id')); - map.set('text', statusToTextMentions(state, action.status, action.account)); + map.set('to', action.explicitAddressing ? statusToMentionsArray(state, action.status, action.account) : undefined); + map.set('text', !action.explicitAddressing ? statusToTextMentions(state, action.status, action.account) : ''); map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy'))); map.set('focusDate', new Date()); map.set('caretPosition', null); @@ -305,11 +344,25 @@ export default function compose(state = initialState, action) { map.set('spoiler_text', ''); } }); + case COMPOSE_QUOTE: + return state.withMutations(map => { + map.set('quote', action.status.get('id')); + map.set('to', undefined); + map.set('text', ''); + map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy'))); + map.set('focusDate', new Date()); + map.set('caretPosition', null); + map.set('idempotencyKey', uuid()); + map.set('content_type', state.get('default_content_type')); + map.set('spoiler', false); + map.set('spoiler_text', ''); + }); case COMPOSE_SUBMIT_REQUEST: return state.set('is_submitting', true); case COMPOSE_UPLOAD_CHANGE_REQUEST: return state.set('is_changing_upload', true); case COMPOSE_REPLY_CANCEL: + case COMPOSE_QUOTE_CANCEL: case COMPOSE_RESET: case COMPOSE_SUBMIT_SUCCESS: return clearAll(state); @@ -355,6 +408,8 @@ export default function compose(state = initialState, action) { case TIMELINE_DELETE: if (action.id === state.get('in_reply_to')) { return state.set('in_reply_to', null); + } if (action.id === state.get('quote')) { + return state.set('quote', null); } else { return state; } @@ -373,6 +428,7 @@ export default function compose(state = initialState, action) { case REDRAFT: return state.withMutations(map => { map.set('text', action.raw_text || unescapeHTML(expandMentions(action.status))); + map.set('to', action.explicitAddressing ? getExplicitMentions(action.status.get('account', 'id'), action.status) : null); map.set('in_reply_to', action.status.get('in_reply_to_id')); map.set('privacy', action.status.get('visibility')); // TODO: Actually fix this rather than just removing it @@ -416,6 +472,10 @@ export default function compose(state = initialState, action) { return state.updateIn(['poll', 'options'], options => options.delete(action.index)); case COMPOSE_POLL_SETTINGS_CHANGE: return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple)); + case COMPOSE_ADD_TO_MENTIONS: + return state.update('to', mentions => mentions.add(action.account)); + case COMPOSE_REMOVE_FROM_MENTIONS: + return state.update('to', mentions => mentions.delete(action.account)); case ME_FETCH_SUCCESS: return importAccount(state, action.me); case ME_PATCH_SUCCESS: diff --git a/app/soapbox/reducers/contexts.js b/app/soapbox/reducers/contexts.js index 9bcf87b9a..f8412c624 100644 --- a/app/soapbox/reducers/contexts.js +++ b/app/soapbox/reducers/contexts.js @@ -1,3 +1,7 @@ +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + +import { STATUS_IMPORT, STATUSES_IMPORT } from 'soapbox/actions/importer'; + import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, @@ -8,8 +12,6 @@ import { } from '../actions/statuses'; import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses'; import { TIMELINE_DELETE } from '../actions/timelines'; -import { STATUS_IMPORT, STATUSES_IMPORT } from 'soapbox/actions/importer'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; const initialState = ImmutableMap({ inReplyTos: ImmutableMap(), @@ -39,7 +41,25 @@ const importStatuses = (state, statuses) => { }); }; +const isReplyTo = (state, childId, parentId, initialId = null) => { + if (!childId) return false; + + // Prevent cycles + if (childId === initialId) return false; + initialId = initialId || childId; + + if (childId === parentId) { + return true; + } else { + const nextId = state.getIn(['inReplyTos', childId]); + return isReplyTo(state, nextId, parentId, initialId); + } +}; + const insertTombstone = (state, ancestorId, descendantId) => { + // Prevent infinite loop if the API returns a bogus response + if (isReplyTo(state, ancestorId, descendantId)) return state; + const tombstoneId = `${descendantId}-tombstone`; return state.withMutations(state => { importStatus(state, { id: tombstoneId, in_reply_to_id: ancestorId }); diff --git a/app/soapbox/reducers/conversations.js b/app/soapbox/reducers/conversations.js index f7c9884b4..29ea929f3 100644 --- a/app/soapbox/reducers/conversations.js +++ b/app/soapbox/reducers/conversations.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { CONVERSATIONS_MOUNT, CONVERSATIONS_UNMOUNT, diff --git a/app/soapbox/reducers/custom_emojis.js b/app/soapbox/reducers/custom_emojis.js index 17bafe9eb..7008d5234 100644 --- a/app/soapbox/reducers/custom_emojis.js +++ b/app/soapbox/reducers/custom_emojis.js @@ -1,8 +1,10 @@ import { List as ImmutableList, fromJS } from 'immutable'; -import { CUSTOM_EMOJIS_FETCH_SUCCESS } from '../actions/custom_emojis'; -import { addCustomToPool } from 'soapbox/features/emoji/emoji_mart_search_light'; -import { buildCustomEmojis } from '../features/emoji/emoji'; + import { emojis as emojiData } from 'soapbox/features/emoji/emoji_mart_data_light'; +import { addCustomToPool } from 'soapbox/features/emoji/emoji_mart_search_light'; + +import { CUSTOM_EMOJIS_FETCH_SUCCESS } from '../actions/custom_emojis'; +import { buildCustomEmojis } from '../features/emoji/emoji'; const initialState = ImmutableList(); diff --git a/app/soapbox/reducers/domain_lists.js b/app/soapbox/reducers/domain_lists.js index 6bf8cee68..8cdd3ba37 100644 --- a/app/soapbox/reducers/domain_lists.js +++ b/app/soapbox/reducers/domain_lists.js @@ -1,9 +1,10 @@ +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + import { DOMAIN_BLOCKS_FETCH_SUCCESS, DOMAIN_BLOCKS_EXPAND_SUCCESS, DOMAIN_UNBLOCK_SUCCESS, } from '../actions/domain_blocks'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; const initialState = ImmutableMap({ blocks: ImmutableMap({ diff --git a/app/soapbox/reducers/dropdown_menu.js b/app/soapbox/reducers/dropdown_menu.js index 4cceee9f5..6b0ae8872 100644 --- a/app/soapbox/reducers/dropdown_menu.js +++ b/app/soapbox/reducers/dropdown_menu.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap } from 'immutable'; + import { DROPDOWN_MENU_OPEN, DROPDOWN_MENU_CLOSE, diff --git a/app/soapbox/reducers/filters.js b/app/soapbox/reducers/filters.js index d0988e05d..488706573 100644 --- a/app/soapbox/reducers/filters.js +++ b/app/soapbox/reducers/filters.js @@ -1,6 +1,7 @@ -import { FILTERS_FETCH_SUCCESS } from '../actions/filters'; import { List as ImmutableList, fromJS } from 'immutable'; +import { FILTERS_FETCH_SUCCESS } from '../actions/filters'; + export default function filters(state = ImmutableList(), action) { switch(action.type) { case FILTERS_FETCH_SUCCESS: diff --git a/app/soapbox/reducers/group_editor.js b/app/soapbox/reducers/group_editor.js index b77b8e508..4086f0388 100644 --- a/app/soapbox/reducers/group_editor.js +++ b/app/soapbox/reducers/group_editor.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap } from 'immutable'; + import { GROUP_CREATE_REQUEST, GROUP_CREATE_FAIL, diff --git a/app/soapbox/reducers/group_lists.js b/app/soapbox/reducers/group_lists.js index 12944b106..c35a65bdd 100644 --- a/app/soapbox/reducers/group_lists.js +++ b/app/soapbox/reducers/group_lists.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { GROUPS_FETCH_SUCCESS } from '../actions/groups'; const initialState = ImmutableMap({ diff --git a/app/soapbox/reducers/group_relationships.js b/app/soapbox/reducers/group_relationships.js index e5f28ef30..469b17a6b 100644 --- a/app/soapbox/reducers/group_relationships.js +++ b/app/soapbox/reducers/group_relationships.js @@ -1,6 +1,7 @@ -import { GROUP_RELATIONSHIPS_FETCH_SUCCESS, GROUP_JOIN_SUCCESS, GROUP_LEAVE_SUCCESS } from '../actions/groups'; import { Map as ImmutableMap, fromJS } from 'immutable'; +import { GROUP_RELATIONSHIPS_FETCH_SUCCESS, GROUP_JOIN_SUCCESS, GROUP_LEAVE_SUCCESS } from '../actions/groups'; + const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship)); const normalizeRelationships = (state, relationships) => { diff --git a/app/soapbox/reducers/groups.js b/app/soapbox/reducers/groups.js index 58b4f4237..56309aace 100644 --- a/app/soapbox/reducers/groups.js +++ b/app/soapbox/reducers/groups.js @@ -1,10 +1,11 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import { GROUP_UPDATE_SUCCESS } from '../actions/group_editor'; import { GROUP_FETCH_SUCCESS, GROUP_FETCH_FAIL, GROUPS_FETCH_SUCCESS, } from '../actions/groups'; -import { GROUP_UPDATE_SUCCESS } from '../actions/group_editor'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/height_cache.js b/app/soapbox/reducers/height_cache.js index 77a59c8c5..2664d4f82 100644 --- a/app/soapbox/reducers/height_cache.js +++ b/app/soapbox/reducers/height_cache.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap } from 'immutable'; + import { HEIGHT_CACHE_SET, HEIGHT_CACHE_CLEAR } from '../actions/height_cache'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/identity_proofs.js b/app/soapbox/reducers/identity_proofs.js index d3034659f..64f258abe 100644 --- a/app/soapbox/reducers/identity_proofs.js +++ b/app/soapbox/reducers/identity_proofs.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, fromJS } from 'immutable'; + import { IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST, IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS, diff --git a/app/soapbox/reducers/index.js b/app/soapbox/reducers/index.js index d438b32eb..a5c178b3c 100644 --- a/app/soapbox/reducers/index.js +++ b/app/soapbox/reducers/index.js @@ -1,66 +1,68 @@ -import { combineReducers } from 'redux-immutable'; import { Map as ImmutableMap } from 'immutable'; +import { combineReducers } from 'redux-immutable'; + import { AUTH_LOGGED_OUT } from 'soapbox/actions/auth'; -import dropdown_menu from './dropdown_menu'; -import timelines from './timelines'; -import meta from './meta'; -import alerts from './alerts'; -import modal from './modal'; -import user_lists from './user_lists'; -import domain_lists from './domain_lists'; + import accounts from './accounts'; import accounts_counters from './accounts_counters'; -import statuses from './statuses'; -import relationships from './relationships'; -import settings from './settings'; -import push_notifications from './push_notifications'; -import status_lists from './status_lists'; -import mutes from './mutes'; -import reports from './reports'; -import contexts from './contexts'; -import compose from './compose'; -import search from './search'; -import notifications from './notifications'; -import height_cache from './height_cache'; -import custom_emojis from './custom_emojis'; -import lists from './lists'; -import listEditor from './list_editor'; -import listAdder from './list_adder'; -import filters from './filters'; -import conversations from './conversations'; -import suggestions from './suggestions'; -import polls from './polls'; -import identity_proofs from './identity_proofs'; -import trends from './trends'; -import groups from './groups'; -import group_relationships from './group_relationships'; -import group_lists from './group_lists'; -import group_editor from './group_editor'; -import sidebar from './sidebar'; -import patron from './patron'; -import soapbox from './soapbox'; -import instance from './instance'; -import me from './me'; -import auth from './auth'; -import admin from './admin'; -import chats from './chats'; -import chat_messages from './chat_messages'; -import chat_message_lists from './chat_message_lists'; -import profile_hover_card from './profile_hover_card'; -import backups from './backups'; -import admin_log from './admin_log'; -import security from './security'; -import scheduled_statuses from './scheduled_statuses'; -import aliases from './aliases'; import accounts_meta from './accounts_meta'; +import admin from './admin'; +import admin_log from './admin_log'; +import alerts from './alerts'; +import aliases from './aliases'; +import auth from './auth'; +import backups from './backups'; +import chat_message_lists from './chat_message_lists'; +import chat_messages from './chat_messages'; +import chats from './chats'; +import compose from './compose'; +import contexts from './contexts'; +import conversations from './conversations'; +import custom_emojis from './custom_emojis'; +import domain_lists from './domain_lists'; +import dropdown_menu from './dropdown_menu'; +import filters from './filters'; +import group_editor from './group_editor'; +import group_lists from './group_lists'; +import group_relationships from './group_relationships'; +import groups from './groups'; +import height_cache from './height_cache'; +import identity_proofs from './identity_proofs'; +import instance from './instance'; +import listAdder from './list_adder'; +import listEditor from './list_editor'; +import lists from './lists'; +import me from './me'; +import meta from './meta'; +import modals from './modals'; +import mutes from './mutes'; +import notifications from './notifications'; +import patron from './patron'; import pending_statuses from './pending_statuses'; +import polls from './polls'; +import profile_hover_card from './profile_hover_card'; +import push_notifications from './push_notifications'; +import relationships from './relationships'; +import reports from './reports'; +import scheduled_statuses from './scheduled_statuses'; +import search from './search'; +import security from './security'; +import settings from './settings'; +import sidebar from './sidebar'; +import soapbox from './soapbox'; +import status_lists from './status_lists'; +import statuses from './statuses'; +import suggestions from './suggestions'; +import timelines from './timelines'; +import trends from './trends'; +import user_lists from './user_lists'; const appReducer = combineReducers({ dropdown_menu, timelines, meta, alerts, - modal, + modals, user_lists, domain_lists, status_lists, diff --git a/app/soapbox/reducers/instance.js b/app/soapbox/reducers/instance.js index ff94b5123..8a79a2869 100644 --- a/app/soapbox/reducers/instance.js +++ b/app/soapbox/reducers/instance.js @@ -1,14 +1,18 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + +import { ADMIN_CONFIG_UPDATE_REQUEST, ADMIN_CONFIG_UPDATE_SUCCESS } from 'soapbox/actions/admin'; +import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload'; +import KVStore from 'soapbox/storage/kv_store'; +import { ConfigDB } from 'soapbox/utils/config_db'; +import { parseVersion, PLEROMA } from 'soapbox/utils/features'; +import { isNumber } from 'soapbox/utils/numbers'; + import { INSTANCE_REMEMBER_SUCCESS, INSTANCE_FETCH_SUCCESS, INSTANCE_FETCH_FAIL, NODEINFO_FETCH_SUCCESS, } from '../actions/instance'; -import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload'; -import { ADMIN_CONFIG_UPDATE_REQUEST, ADMIN_CONFIG_UPDATE_SUCCESS } from 'soapbox/actions/admin'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; -import { ConfigDB } from 'soapbox/utils/config_db'; -import KVStore from 'soapbox/storage/kv_store'; const nodeinfoToInstance = nodeinfo => { // Match Pleroma's develop branch @@ -26,21 +30,69 @@ const nodeinfoToInstance = nodeinfo => { }); }; -// Set Mastodon defaults, overridden by Pleroma servers +// Use Mastodon defaults const initialState = ImmutableMap({ - max_toot_chars: 500, description_limit: 1500, - poll_limits: ImmutableMap({ - max_expiration: 2629746, - max_option_chars: 25, - max_options: 4, - min_expiration: 300, + configuration: ImmutableMap({ + statuses: ImmutableMap({ + max_characters: 500, + max_media_attachments: 4, + }), + polls: ImmutableMap({ + max_options: 4, + max_characters_per_option: 25, + min_expiration: 300, + max_expiration: 2629746, + }), }), version: '0.0.0', }); +// Build Mastodon configuration from Pleroma instance +const pleromaToMastodonConfig = instance => { + return ImmutableMap({ + statuses: ImmutableMap({ + max_characters: instance.get('max_toot_chars'), + }), + polls: ImmutableMap({ + max_options: instance.getIn(['poll_limits', 'max_options']), + max_characters_per_option: instance.getIn(['poll_limits', 'max_option_chars']), + min_expiration: instance.getIn(['poll_limits', 'min_expiration']), + max_expiration: instance.getIn(['poll_limits', 'max_expiration']), + }), + }); +}; + +// Use new value only if old value is undefined +const mergeDefined = (oldVal, newVal) => oldVal === undefined ? newVal : oldVal; + +// Get the software's default attachment limit +const getAttachmentLimit = software => software === PLEROMA ? Infinity : 4; + +// Normalize instance (Pleroma, Mastodon, etc.) to Mastodon's format +const normalizeInstance = instance => { + const { software } = parseVersion(instance.get('version')); + const mastodonConfig = pleromaToMastodonConfig(instance); + + return instance.withMutations(instance => { + // Merge configuration + instance.update('configuration', ImmutableMap(), configuration => ( + configuration.mergeDeepWith(mergeDefined, mastodonConfig) + )); + + // If max attachments isn't set, check the backend software + instance.updateIn(['configuration', 'statuses', 'max_media_attachments'], value => { + return isNumber(value) ? value : getAttachmentLimit(software); + }); + + // Merge defaults & cleanup + instance.mergeDeepWith(mergeDefined, initialState); + instance.deleteAll(['max_toot_chars', 'poll_limits']); + }); +}; + const importInstance = (state, instance) => { - return initialState.mergeDeep(instance); + return normalizeInstance(instance); }; const importNodeinfo = (state, nodeinfo) => { @@ -111,7 +163,7 @@ const persistInstance = instance => { }; const handleInstanceFetchFail = (state, error) => { - if (error.response && error.response.status === 401) { + if (error.response?.status === 401) { return handleAuthFetch(state); } else { return state; diff --git a/app/soapbox/reducers/list_adder.js b/app/soapbox/reducers/list_adder.js index b144610a5..0f61273aa 100644 --- a/app/soapbox/reducers/list_adder.js +++ b/app/soapbox/reducers/list_adder.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { LIST_ADDER_RESET, LIST_ADDER_SETUP, diff --git a/app/soapbox/reducers/list_editor.js b/app/soapbox/reducers/list_editor.js index 6e020dbe6..ceceb27c7 100644 --- a/app/soapbox/reducers/list_editor.js +++ b/app/soapbox/reducers/list_editor.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; + import { LIST_CREATE_REQUEST, LIST_CREATE_FAIL, diff --git a/app/soapbox/reducers/lists.js b/app/soapbox/reducers/lists.js index ba3e2b3cb..2a797772b 100644 --- a/app/soapbox/reducers/lists.js +++ b/app/soapbox/reducers/lists.js @@ -1,3 +1,5 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { LIST_FETCH_SUCCESS, LIST_FETCH_FAIL, @@ -6,7 +8,6 @@ import { LIST_UPDATE_SUCCESS, LIST_DELETE_SUCCESS, } from '../actions/lists'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/me.js b/app/soapbox/reducers/me.js index 021855a14..9f0796a85 100644 --- a/app/soapbox/reducers/me.js +++ b/app/soapbox/reducers/me.js @@ -1,19 +1,19 @@ +import { + AUTH_LOGGED_OUT, + AUTH_ACCOUNT_REMEMBER_SUCCESS, + VERIFY_CREDENTIALS_SUCCESS, +} from '../actions/auth'; import { ME_FETCH_SUCCESS, ME_FETCH_FAIL, ME_FETCH_SKIP, ME_PATCH_SUCCESS, } from '../actions/me'; -import { - AUTH_LOGGED_OUT, - AUTH_ACCOUNT_REMEMBER_SUCCESS, - VERIFY_CREDENTIALS_SUCCESS, -} from '../actions/auth'; const initialState = null; const handleForbidden = (state, error) => { - if (error.response && [401, 403].includes(error.response.status)) { + if ([401, 403].includes(error.response?.status)) { return false; } else { return state; diff --git a/app/soapbox/reducers/meta.js b/app/soapbox/reducers/meta.js index 315a7c030..46f662ece 100644 --- a/app/soapbox/reducers/meta.js +++ b/app/soapbox/reducers/meta.js @@ -1,8 +1,9 @@ 'use strict'; -import { INSTANCE_FETCH_FAIL } from 'soapbox/actions/instance'; import { Map as ImmutableMap } from 'immutable'; +import { INSTANCE_FETCH_FAIL } from 'soapbox/actions/instance'; + const initialState = ImmutableMap(); export default function meta(state = initialState, action) { diff --git a/app/soapbox/reducers/modal.js b/app/soapbox/reducers/modal.js deleted file mode 100644 index 69a991fa7..000000000 --- a/app/soapbox/reducers/modal.js +++ /dev/null @@ -1,17 +0,0 @@ -import { MODAL_OPEN, MODAL_CLOSE } from '../actions/modal'; - -const initialState = { - modalType: null, - modalProps: {}, -}; - -export default function modal(state = initialState, action) { - switch(action.type) { - case MODAL_OPEN: - return { modalType: action.modalType, modalProps: action.modalProps }; - case MODAL_CLOSE: - return (action.modalType === undefined || action.modalType === state.modalType) ? initialState : state; - default: - return state; - } -} diff --git a/app/soapbox/reducers/modals.js b/app/soapbox/reducers/modals.js new file mode 100644 index 000000000..65a0b85f6 --- /dev/null +++ b/app/soapbox/reducers/modals.js @@ -0,0 +1,25 @@ +import { List as ImmutableList } from 'immutable'; + +import { MODAL_OPEN, MODAL_CLOSE } from '../actions/modals'; + +const initialState = ImmutableList(); + +export default function modal(state = initialState, action) { + switch(action.type) { + case MODAL_OPEN: + return state.push({ modalType: action.modalType, modalProps: action.modalProps }); + case MODAL_CLOSE: + if (state.size === 0) { + return state; + } + if (action.modalType === undefined) { + return state.pop(); + } + if (state.some(({ modalType }) => action.modalType === modalType)) { + return state.slice(0, state.findLastIndex(({ modalType }) => action.modalType === modalType)); + } + return state; + default: + return state; + } +} diff --git a/app/soapbox/reducers/notifications.js b/app/soapbox/reducers/notifications.js index c4b4e82eb..401fe92a9 100644 --- a/app/soapbox/reducers/notifications.js +++ b/app/soapbox/reducers/notifications.js @@ -1,3 +1,17 @@ +import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap, fromJS } from 'immutable'; + +import { + MARKER_FETCH_SUCCESS, + MARKER_SAVE_REQUEST, + MARKER_SAVE_SUCCESS, +} from 'soapbox/actions/markers'; + +import { + ACCOUNT_BLOCK_SUCCESS, + ACCOUNT_MUTE_SUCCESS, + FOLLOW_REQUEST_AUTHORIZE_SUCCESS, + FOLLOW_REQUEST_REJECT_SUCCESS, +} from '../actions/accounts'; import { NOTIFICATIONS_UPDATE, NOTIFICATIONS_EXPAND_SUCCESS, @@ -11,19 +25,7 @@ import { NOTIFICATIONS_MARK_READ_REQUEST, MAX_QUEUED_NOTIFICATIONS, } from '../actions/notifications'; -import { - ACCOUNT_BLOCK_SUCCESS, - ACCOUNT_MUTE_SUCCESS, - FOLLOW_REQUEST_AUTHORIZE_SUCCESS, - FOLLOW_REQUEST_REJECT_SUCCESS, -} from '../actions/accounts'; import { TIMELINE_DELETE } from '../actions/timelines'; -import { - MARKER_FETCH_SUCCESS, - MARKER_SAVE_REQUEST, - MARKER_SAVE_SUCCESS, -} from 'soapbox/actions/markers'; -import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap, fromJS } from 'immutable'; const initialState = ImmutableMap({ items: ImmutableOrderedMap(), @@ -64,8 +66,8 @@ const isValid = notification => { return false; } - // Mastodon can return mentions with a null status - if (notification.type === 'mention' && !notification.status.id) { + // Mastodon can return status notifications with a null status + if (['mention', 'reblog', 'favourite', 'poll'].includes(notification.type) && !notification.status.id) { return false; } diff --git a/app/soapbox/reducers/patron.js b/app/soapbox/reducers/patron.js index d05b156d7..66a8940d8 100644 --- a/app/soapbox/reducers/patron.js +++ b/app/soapbox/reducers/patron.js @@ -1,8 +1,9 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { PATRON_INSTANCE_FETCH_SUCCESS, PATRON_ACCOUNT_FETCH_SUCCESS, } from '../actions/patron'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/pending_statuses.js b/app/soapbox/reducers/pending_statuses.js index 445324ae5..1c18d7599 100644 --- a/app/soapbox/reducers/pending_statuses.js +++ b/app/soapbox/reducers/pending_statuses.js @@ -1,8 +1,9 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { STATUS_CREATE_REQUEST, STATUS_CREATE_SUCCESS, } from 'soapbox/actions/statuses'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const importStatus = (state, params, idempotencyKey) => { return state.set(idempotencyKey, params); diff --git a/app/soapbox/reducers/polls.js b/app/soapbox/reducers/polls.js index 44b7b5308..24c805457 100644 --- a/app/soapbox/reducers/polls.js +++ b/app/soapbox/reducers/polls.js @@ -1,6 +1,7 @@ -import { POLLS_IMPORT } from 'soapbox/actions/importer'; import { Map as ImmutableMap, fromJS } from 'immutable'; +import { POLLS_IMPORT } from 'soapbox/actions/importer'; + const importPolls = (state, polls) => state.withMutations(map => polls.forEach(poll => map.set(poll.id, fromJS(poll)))); const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/profile_hover_card.js b/app/soapbox/reducers/profile_hover_card.js index 5776a3e87..fcb2cbbe9 100644 --- a/app/soapbox/reducers/profile_hover_card.js +++ b/app/soapbox/reducers/profile_hover_card.js @@ -1,9 +1,10 @@ +import { Map as ImmutableMap } from 'immutable'; + import { PROFILE_HOVER_CARD_OPEN, PROFILE_HOVER_CARD_CLOSE, PROFILE_HOVER_CARD_UPDATE, } from 'soapbox/actions/profile_hover_card'; -import { Map as ImmutableMap } from 'immutable'; const initialState = ImmutableMap(); diff --git a/app/soapbox/reducers/push_notifications.js b/app/soapbox/reducers/push_notifications.js index e72952934..c622d215b 100644 --- a/app/soapbox/reducers/push_notifications.js +++ b/app/soapbox/reducers/push_notifications.js @@ -1,15 +1,16 @@ -import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from '../actions/push_notifications'; import { Map as ImmutableMap } from 'immutable'; +import { SET_BROWSER_SUPPORT, SET_SUBSCRIPTION, CLEAR_SUBSCRIPTION, SET_ALERTS } from '../actions/push_notifications'; + const initialState = ImmutableMap({ subscription: null, alerts: new ImmutableMap({ - follow: false, - follow_request: false, - favourite: false, - reblog: false, - mention: false, - poll: false, + follow: true, + follow_request: true, + favourite: true, + reblog: true, + mention: true, + poll: true, }), isSubscribed: false, browserSupport: false, diff --git a/app/soapbox/reducers/relationships.js b/app/soapbox/reducers/relationships.js index ec6ac6c14..29276c5c3 100644 --- a/app/soapbox/reducers/relationships.js +++ b/app/soapbox/reducers/relationships.js @@ -1,3 +1,8 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; +import { get } from 'lodash'; + +import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming'; + import { ACCOUNT_FOLLOW_SUCCESS, ACCOUNT_FOLLOW_REQUEST, @@ -15,17 +20,14 @@ import { ACCOUNT_UNPIN_SUCCESS, RELATIONSHIPS_FETCH_SUCCESS, } from '../actions/accounts'; -import { - ACCOUNT_IMPORT, - ACCOUNTS_IMPORT, -} from '../actions/importer'; import { DOMAIN_BLOCK_SUCCESS, DOMAIN_UNBLOCK_SUCCESS, } from '../actions/domain_blocks'; -import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming'; -import { Map as ImmutableMap, fromJS } from 'immutable'; -import { get } from 'lodash'; +import { + ACCOUNT_IMPORT, + ACCOUNTS_IMPORT, +} from '../actions/importer'; const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship)); diff --git a/app/soapbox/reducers/reports.js b/app/soapbox/reducers/reports.js index 24d4cdc26..5f9224ba9 100644 --- a/app/soapbox/reducers/reports.js +++ b/app/soapbox/reducers/reports.js @@ -1,3 +1,5 @@ +import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; + import { REPORT_INIT, REPORT_SUBMIT_REQUEST, @@ -9,7 +11,6 @@ import { REPORT_FORWARD_CHANGE, REPORT_BLOCK_CHANGE, } from '../actions/reports'; -import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; const initialState = ImmutableMap({ new: ImmutableMap({ diff --git a/app/soapbox/reducers/scheduled_statuses.js b/app/soapbox/reducers/scheduled_statuses.js index 20e591d1f..48adabbae 100644 --- a/app/soapbox/reducers/scheduled_statuses.js +++ b/app/soapbox/reducers/scheduled_statuses.js @@ -1,11 +1,13 @@ -import { STATUS_CREATE_SUCCESS } from 'soapbox/actions/statuses'; +import { Map as ImmutableMap, fromJS } from 'immutable'; + import { SCHEDULED_STATUSES_FETCH_SUCCESS, SCHEDULED_STATUS_CANCEL_REQUEST, SCHEDULED_STATUS_CANCEL_SUCCESS, } from 'soapbox/actions/scheduled_statuses'; +import { STATUS_CREATE_SUCCESS } from 'soapbox/actions/statuses'; + import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; -import { Map as ImmutableMap, fromJS } from 'immutable'; const importStatus = (state, status) => { if (!status.scheduled_at) return state; diff --git a/app/soapbox/reducers/search.js b/app/soapbox/reducers/search.js index 47aa9f00b..86e4222a5 100644 --- a/app/soapbox/reducers/search.js +++ b/app/soapbox/reducers/search.js @@ -1,3 +1,11 @@ +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; + +import { + COMPOSE_MENTION, + COMPOSE_REPLY, + COMPOSE_DIRECT, + COMPOSE_QUOTE, +} from '../actions/compose'; import { SEARCH_CHANGE, SEARCH_CLEAR, @@ -8,12 +16,6 @@ import { SEARCH_EXPAND_REQUEST, SEARCH_EXPAND_SUCCESS, } from '../actions/search'; -import { - COMPOSE_MENTION, - COMPOSE_REPLY, - COMPOSE_DIRECT, -} from '../actions/compose'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; const initialState = ImmutableMap({ value: '', @@ -28,44 +30,33 @@ const toIds = items => { return ImmutableOrderedSet(items.map(item => item.id)); }; -const getResultsFilter = results => { - if (results.accounts.length > 0) { - return 'accounts'; - } else if (results.statuses.length > 0) { - return 'statuses'; - } else if (results.hashtags.length > 0) { - return 'hashtags'; - } else { - return 'accounts'; - } -}; - -const importResults = (state, results) => { - const filter = getResultsFilter(results); - +const importResults = (state, results, searchTerm, searchType) => { return state.withMutations(state => { - state.set('results', ImmutableMap({ - accounts: toIds(results.accounts), - statuses: toIds(results.statuses), - hashtags: fromJS(results.hashtags), // it's a list of maps - accountsHasMore: results.accounts.length >= 20, - statusesHasMore: results.statuses.length >= 20, - hashtagsHasMore: results.hashtags.length >= 20, - accountsLoaded: true, - statusesLoaded: true, - hashtagsLoaded: true, - })); + if (state.get('value') === searchTerm && state.get('filter') === searchType) { + state.set('results', ImmutableMap({ + accounts: toIds(results.accounts), + statuses: toIds(results.statuses), + hashtags: fromJS(results.hashtags), // it's a list of maps + accountsHasMore: results.accounts.length >= 20, + statusesHasMore: results.statuses.length >= 20, + hashtagsHasMore: results.hashtags.length >= 20, + accountsLoaded: true, + statusesLoaded: true, + hashtagsLoaded: true, + })); - state.set('submitted', true); - state.set('filter', filter); + state.set('submitted', true); + } }); }; -const paginateResults = (state, searchType, results) => { +const paginateResults = (state, searchType, results, searchTerm) => { return state.withMutations(state => { - state.setIn(['results', `${searchType}HasMore`], results[searchType].length >= 20); - state.setIn(['results', `${searchType}Loaded`], true); - state.updateIn(['results', searchType], items => items.concat(results[searchType].map(item => item.id))); + if (state.get('value') === searchTerm) { + state.setIn(['results', `${searchType}HasMore`], results[searchType].length >= 20); + state.setIn(['results', `${searchType}Loaded`], true); + state.updateIn(['results', searchType], items => items.concat(results[searchType].map(item => item.id))); + } }); }; @@ -88,17 +79,18 @@ export default function search(state = initialState, action) { case COMPOSE_REPLY: case COMPOSE_MENTION: case COMPOSE_DIRECT: + case COMPOSE_QUOTE: return state.set('hidden', true); case SEARCH_FETCH_REQUEST: return handleSubmitted(state, action.value); case SEARCH_FETCH_SUCCESS: - return importResults(state, action.results); + return importResults(state, action.results, action.searchTerm, action.searchType); case SEARCH_FILTER_SET: return state.set('filter', action.value); case SEARCH_EXPAND_REQUEST: return state.setIn(['results', `${action.searchType}Loaded`], false); case SEARCH_EXPAND_SUCCESS: - return paginateResults(state, action.searchType, action.results); + return paginateResults(state, action.searchType, action.results, action.searchTerm); default: return state; } diff --git a/app/soapbox/reducers/security.js b/app/soapbox/reducers/security.js index 497f4fb61..443e80b49 100644 --- a/app/soapbox/reducers/security.js +++ b/app/soapbox/reducers/security.js @@ -1,11 +1,22 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + +import { + MFA_FETCH_SUCCESS, + MFA_CONFIRM_SUCCESS, + MFA_DISABLE_SUCCESS, +} from '../actions/mfa'; import { FETCH_TOKENS_SUCCESS, REVOKE_TOKEN_SUCCESS, } from '../actions/security'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; const initialState = ImmutableMap({ tokens: ImmutableList(), + mfa: ImmutableMap({ + settings: ImmutableMap({ + totp: false, + }), + }), }); const deleteToken = (state, tokenId) => { @@ -14,12 +25,30 @@ const deleteToken = (state, tokenId) => { }); }; +const importMfa = (state, data) => { + return state.set('mfa', data); +}; + +const enableMfa = (state, method) => { + return state.setIn(['mfa', 'settings', method], true); +}; + +const disableMfa = (state, method) => { + return state.setIn(['mfa', 'settings', method], false); +}; + export default function security(state = initialState, action) { switch(action.type) { case FETCH_TOKENS_SUCCESS: return state.set('tokens', fromJS(action.tokens)); case REVOKE_TOKEN_SUCCESS: return deleteToken(state, action.id); + case MFA_FETCH_SUCCESS: + return importMfa(state, fromJS(action.data)); + case MFA_CONFIRM_SUCCESS: + return enableMfa(state, action.method); + case MFA_DISABLE_SUCCESS: + return disableMfa(state, action.method); default: return state; } diff --git a/app/soapbox/reducers/settings.js b/app/soapbox/reducers/settings.js index 9bfa3f356..dfe5c7223 100644 --- a/app/soapbox/reducers/settings.js +++ b/app/soapbox/reducers/settings.js @@ -1,9 +1,16 @@ -import { SETTING_CHANGE, SETTING_SAVE, FE_NAME } from '../actions/settings'; +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import { ME_FETCH_SUCCESS } from 'soapbox/actions/me'; + +import { EMOJI_USE } from '../actions/emojis'; import { NOTIFICATIONS_FILTER_SET } from '../actions/notifications'; import { SEARCH_FILTER_SET } from '../actions/search'; -import { EMOJI_USE } from '../actions/emojis'; -import { ME_FETCH_SUCCESS } from 'soapbox/actions/me'; -import { Map as ImmutableMap, fromJS } from 'immutable'; +import { + SETTING_CHANGE, + SETTING_SAVE, + SETTINGS_UPDATE, + FE_NAME, +} from '../actions/settings'; // Default settings are in action/settings.js // @@ -35,6 +42,8 @@ export default function settings(state = initialState, action) { return updateFrequentEmojis(state, action.emoji); case SETTING_SAVE: return state.set('saved', true); + case SETTINGS_UPDATE: + return fromJS(action.settings); default: return state; } diff --git a/app/soapbox/reducers/soapbox.js b/app/soapbox/reducers/soapbox.js index 60e339786..a208b4301 100644 --- a/app/soapbox/reducers/soapbox.js +++ b/app/soapbox/reducers/soapbox.js @@ -1,11 +1,14 @@ +import { Map as ImmutableMap, fromJS } from 'immutable'; + +import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload'; +import KVStore from 'soapbox/storage/kv_store'; +import { ConfigDB } from 'soapbox/utils/config_db'; + import { ADMIN_CONFIG_UPDATE_SUCCESS } from '../actions/admin'; import { SOAPBOX_CONFIG_REQUEST_SUCCESS, SOAPBOX_CONFIG_REQUEST_FAIL, } from '../actions/soapbox'; -import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload'; -import { Map as ImmutableMap, fromJS } from 'immutable'; -import { ConfigDB } from 'soapbox/utils/config_db'; const initialState = ImmutableMap(); @@ -36,12 +39,23 @@ const preloadImport = (state, action) => { } }; +const persistSoapboxConfig = (soapboxConfig, host) => { + if (host) { + KVStore.setItem(`soapbox_config:${host}`, soapboxConfig.toJS()).catch(console.error); + } +}; + +const importSoapboxConfig = (state, soapboxConfig, host) => { + persistSoapboxConfig(soapboxConfig, host); + return soapboxConfig; +}; + export default function soapbox(state = initialState, action) { switch(action.type) { case PLEROMA_PRELOAD_IMPORT: return preloadImport(state, action); case SOAPBOX_CONFIG_REQUEST_SUCCESS: - return fromJS(action.soapboxConfig); + return importSoapboxConfig(state, fromJS(action.soapboxConfig), action.host); case SOAPBOX_CONFIG_REQUEST_FAIL: return fallbackState.mergeDeep(state); case ADMIN_CONFIG_UPDATE_SUCCESS: diff --git a/app/soapbox/reducers/status_lists.js b/app/soapbox/reducers/status_lists.js index 1953e636c..e49bb02ef 100644 --- a/app/soapbox/reducers/status_lists.js +++ b/app/soapbox/reducers/status_lists.js @@ -1,3 +1,13 @@ +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + +import { + BOOKMARKED_STATUSES_FETCH_REQUEST, + BOOKMARKED_STATUSES_FETCH_SUCCESS, + BOOKMARKED_STATUSES_FETCH_FAIL, + BOOKMARKED_STATUSES_EXPAND_REQUEST, + BOOKMARKED_STATUSES_EXPAND_SUCCESS, + BOOKMARKED_STATUSES_EXPAND_FAIL, +} from '../actions/bookmarks'; import { FAVOURITED_STATUSES_FETCH_REQUEST, FAVOURITED_STATUSES_FETCH_SUCCESS, @@ -12,18 +22,6 @@ import { ACCOUNT_FAVOURITED_STATUSES_EXPAND_SUCCESS, ACCOUNT_FAVOURITED_STATUSES_EXPAND_FAIL, } from '../actions/favourites'; -import { - BOOKMARKED_STATUSES_FETCH_REQUEST, - BOOKMARKED_STATUSES_FETCH_SUCCESS, - BOOKMARKED_STATUSES_FETCH_FAIL, - BOOKMARKED_STATUSES_EXPAND_REQUEST, - BOOKMARKED_STATUSES_EXPAND_SUCCESS, - BOOKMARKED_STATUSES_EXPAND_FAIL, -} from '../actions/bookmarks'; -import { - PINNED_STATUSES_FETCH_SUCCESS, -} from '../actions/pin_statuses'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; import { FAVOURITE_SUCCESS, UNFAVOURITE_SUCCESS, @@ -32,6 +30,9 @@ import { PIN_SUCCESS, UNPIN_SUCCESS, } from '../actions/interactions'; +import { + PINNED_STATUSES_FETCH_SUCCESS, +} from '../actions/pin_statuses'; import { SCHEDULED_STATUSES_FETCH_REQUEST, SCHEDULED_STATUSES_FETCH_SUCCESS, diff --git a/app/soapbox/reducers/statuses.js b/app/soapbox/reducers/statuses.js index f8c01ed2b..70c62244c 100644 --- a/app/soapbox/reducers/statuses.js +++ b/app/soapbox/reducers/statuses.js @@ -1,26 +1,98 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + +import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts'; + +import { + EMOJI_REACT_REQUEST, + UNEMOJI_REACT_REQUEST, +} from '../actions/emoji_reacts'; +import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; import { REBLOG_REQUEST, REBLOG_FAIL, + UNREBLOG_REQUEST, + UNREBLOG_FAIL, FAVOURITE_REQUEST, UNFAVOURITE_REQUEST, FAVOURITE_FAIL, } from '../actions/interactions'; import { + STATUS_CREATE_REQUEST, + STATUS_CREATE_FAIL, STATUS_MUTE_SUCCESS, STATUS_UNMUTE_SUCCESS, STATUS_REVEAL, STATUS_HIDE, } from '../actions/statuses'; -import { - EMOJI_REACT_REQUEST, - UNEMOJI_REACT_REQUEST, -} from '../actions/emoji_reacts'; import { TIMELINE_DELETE } from '../actions/timelines'; -import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; -import { Map as ImmutableMap, fromJS } from 'immutable'; -import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts'; -const importStatus = (state, status) => state.set(status.id, fromJS(status)); +// Ensure attachments have required fields +// https://docs.joinmastodon.org/entities/attachment/ +const normalizeAttachment = attachment => { + const url = [ + attachment.get('url'), + attachment.get('preview_url'), + attachment.get('remote_url'), + ].find(url => url) || ''; + + const base = ImmutableMap({ + url, + preview_url: url, + remote_url: url, + }); + + return attachment.mergeWith((o, n) => o || n, base); +}; + +const normalizeAttachments = status => { + return status.update('media_attachments', ImmutableList(), attachments => { + return attachments.map(normalizeAttachment); + }); +}; + +// Fix order of mentions +const fixMentions = status => { + const mentions = status.get('mentions'); + const inReplyToAccountId = status.get('in_reply_to_account_id'); + + // Sort the replied-to mention to the top + const sorted = mentions.sort((a, b) => { + if (a.get('id') === inReplyToAccountId) { + return -1; + } else { + return 0; + } + }); + + return status.set('mentions', sorted); +}; + +const isQuote = status => { + return Boolean(status.get('quote_id') || status.getIn(['pleroma', 'quote_url'])); +}; + +// Preserve quote if an existing status already has it +const fixQuote = (state, status) => { + const oldStatus = state.get(status.get('id')); + + if (oldStatus && !status.get('quote') && isQuote(status)) { + return status + .set('quote', oldStatus.get('quote')) + .updateIn(['pleroma', 'quote_visible'], visible => visible || oldStatus.getIn(['pleroma', 'quote_visible'])); + } else { + return status; + } +}; + +const normalizeStatus = (state, status) => { + return status.withMutations(status => { + fixMentions(status); + fixQuote(state, status); + normalizeAttachments(status); + }); +}; + +const importStatus = (state, status) => state.set(status.id, normalizeStatus(state, fromJS(status))); const importStatuses = (state, statuses) => state.withMutations(mutable => statuses.forEach(status => importStatus(mutable, status))); @@ -33,6 +105,22 @@ const deleteStatus = (state, id, references) => { return state.delete(id); }; +const importPendingStatus = (state, { in_reply_to_id }) => { + if (in_reply_to_id) { + return state.updateIn([in_reply_to_id, 'replies_count'], 0, count => count + 1); + } else { + return state; + } +}; + +const deletePendingStatus = (state, { in_reply_to_id }) => { + if (in_reply_to_id) { + return state.updateIn([in_reply_to_id, 'replies_count'], 0, count => Math.max(0, count - 1)); + } else { + return state; + } +}; + const initialState = ImmutableMap(); export default function statuses(state = initialState, action) { @@ -41,6 +129,10 @@ export default function statuses(state = initialState, action) { return importStatus(state, action.status); case STATUSES_IMPORT: return importStatuses(state, action.statuses); + case STATUS_CREATE_REQUEST: + return importPendingStatus(state, action.params); + case STATUS_CREATE_FAIL: + return deletePendingStatus(state, action.params); case FAVOURITE_REQUEST: return state.update(action.status.get('id'), status => status @@ -69,6 +161,10 @@ export default function statuses(state = initialState, action) { return state.setIn([action.status.get('id'), 'reblogged'], true); case REBLOG_FAIL: return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false); + case UNREBLOG_REQUEST: + return state.setIn([action.status.get('id'), 'reblogged'], false); + case UNREBLOG_FAIL: + return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], true); case STATUS_MUTE_SUCCESS: return state.setIn([action.id, 'muted'], true); case STATUS_UNMUTE_SUCCESS: diff --git a/app/soapbox/reducers/suggestions.js b/app/soapbox/reducers/suggestions.js index 509d84cf9..5362773e7 100644 --- a/app/soapbox/reducers/suggestions.js +++ b/app/soapbox/reducers/suggestions.js @@ -1,3 +1,8 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + +import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts'; +import { DOMAIN_BLOCK_SUCCESS } from 'soapbox/actions/domain_blocks'; + import { SUGGESTIONS_FETCH_REQUEST, SUGGESTIONS_FETCH_SUCCESS, @@ -7,9 +12,6 @@ import { SUGGESTIONS_V2_FETCH_SUCCESS, SUGGESTIONS_V2_FETCH_FAIL, } from '../actions/suggestions'; -import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts'; -import { DOMAIN_BLOCK_SUCCESS } from 'soapbox/actions/domain_blocks'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; const initialState = ImmutableMap({ items: ImmutableList(), diff --git a/app/soapbox/reducers/timelines.js b/app/soapbox/reducers/timelines.js index 058a40b70..2f840683d 100644 --- a/app/soapbox/reducers/timelines.js +++ b/app/soapbox/reducers/timelines.js @@ -1,3 +1,20 @@ +import { + Map as ImmutableMap, + List as ImmutableList, + OrderedSet as ImmutableOrderedSet, + fromJS, +} from 'immutable'; + +import { + ACCOUNT_BLOCK_SUCCESS, + ACCOUNT_MUTE_SUCCESS, + ACCOUNT_UNFOLLOW_SUCCESS, +} from '../actions/accounts'; +import { GROUP_REMOVE_STATUS_SUCCESS } from '../actions/groups'; +import { + STATUS_CREATE_REQUEST, + STATUS_CREATE_SUCCESS, +} from '../actions/statuses'; import { TIMELINE_UPDATE, TIMELINE_DELETE, @@ -12,22 +29,6 @@ import { MAX_QUEUED_ITEMS, TIMELINE_SCROLL_TOP, } from '../actions/timelines'; -import { - ACCOUNT_BLOCK_SUCCESS, - ACCOUNT_MUTE_SUCCESS, - ACCOUNT_UNFOLLOW_SUCCESS, -} from '../actions/accounts'; -import { - STATUS_CREATE_REQUEST, - STATUS_CREATE_SUCCESS, -} from '../actions/statuses'; -import { - Map as ImmutableMap, - List as ImmutableList, - OrderedSet as ImmutableOrderedSet, - fromJS, -} from 'immutable'; -import { GROUP_REMOVE_STATUS_SUCCESS } from '../actions/groups'; const TRUNCATE_LIMIT = 40; const TRUNCATE_SIZE = 20; @@ -68,11 +69,17 @@ const setLoading = (state, timelineId, loading) => { return state.update(timelineId, initialTimeline, timeline => timeline.set('isLoading', loading)); }; +// Keep track of when a timeline failed to load +const setFailed = (state, timelineId, failed) => { + return state.update(timelineId, initialTimeline, timeline => timeline.set('loadingFailed', failed)); +}; + const expandNormalizedTimeline = (state, timelineId, statuses, next, isPartial, isLoadingRecent) => { const newIds = getStatusIds(statuses); return state.update(timelineId, initialTimeline, timeline => timeline.withMutations(timeline => { timeline.set('isLoading', false); + timeline.set('loadingFailed', false); timeline.set('isPartial', isPartial); if (!next && !isLoadingRecent) timeline.set('hasMore', false); @@ -284,16 +291,25 @@ const importStatus = (state, status, idempotencyKey) => { }); }; +const handleExpandFail = (state, timelineId) => { + return state.withMutations(state => { + setLoading(state, timelineId, false); + setFailed(state, timelineId, true); + }); +}; + export default function timelines(state = initialState, action) { switch(action.type) { case STATUS_CREATE_REQUEST: + if (action.params.scheduled_at) return state; return importPendingStatus(state, action.params, action.idempotencyKey); case STATUS_CREATE_SUCCESS: + if (action.status.scheduled_at) return state; return importStatus(state, action.status, action.idempotencyKey); case TIMELINE_EXPAND_REQUEST: return setLoading(state, action.timeline, true); case TIMELINE_EXPAND_FAIL: - return setLoading(state, action.timeline, false); + return handleExpandFail(state, action.timeline); case TIMELINE_EXPAND_SUCCESS: return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent); case TIMELINE_UPDATE: diff --git a/app/soapbox/reducers/trends.js b/app/soapbox/reducers/trends.js index be2e3e912..c5822a660 100644 --- a/app/soapbox/reducers/trends.js +++ b/app/soapbox/reducers/trends.js @@ -1,9 +1,10 @@ +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; + import { TRENDS_FETCH_REQUEST, TRENDS_FETCH_SUCCESS, TRENDS_FETCH_FAIL, } from '../actions/trends'; -import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; const initialState = ImmutableMap({ items: ImmutableList(), diff --git a/app/soapbox/reducers/user_lists.js b/app/soapbox/reducers/user_lists.js index f0d80de77..076144f75 100644 --- a/app/soapbox/reducers/user_lists.js +++ b/app/soapbox/reducers/user_lists.js @@ -1,6 +1,5 @@ -import { - NOTIFICATIONS_UPDATE, -} from '../actions/notifications'; +import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + import { FOLLOWERS_FETCH_SUCCESS, FOLLOWERS_EXPAND_SUCCESS, @@ -10,21 +9,21 @@ import { FOLLOW_REQUESTS_EXPAND_SUCCESS, FOLLOW_REQUEST_AUTHORIZE_SUCCESS, FOLLOW_REQUEST_REJECT_SUCCESS, + PINNED_ACCOUNTS_FETCH_SUCCESS, + BIRTHDAY_REMINDERS_FETCH_SUCCESS, } from '../actions/accounts'; -import { - REBLOGS_FETCH_SUCCESS, - FAVOURITES_FETCH_SUCCESS, - REACTIONS_FETCH_SUCCESS, -} from '../actions/interactions'; import { BLOCKS_FETCH_SUCCESS, BLOCKS_EXPAND_SUCCESS, } from '../actions/blocks'; import { - MUTES_FETCH_SUCCESS, - MUTES_EXPAND_SUCCESS, -} from '../actions/mutes'; -import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; + DIRECTORY_FETCH_REQUEST, + DIRECTORY_FETCH_SUCCESS, + DIRECTORY_FETCH_FAIL, + DIRECTORY_EXPAND_REQUEST, + DIRECTORY_EXPAND_SUCCESS, + DIRECTORY_EXPAND_FAIL, +} from '../actions/directory'; import { GROUP_MEMBERS_FETCH_SUCCESS, GROUP_MEMBERS_EXPAND_SUCCESS, @@ -32,6 +31,18 @@ import { GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS, GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS, } from '../actions/groups'; +import { + REBLOGS_FETCH_SUCCESS, + FAVOURITES_FETCH_SUCCESS, + REACTIONS_FETCH_SUCCESS, +} from '../actions/interactions'; +import { + MUTES_FETCH_SUCCESS, + MUTES_EXPAND_SUCCESS, +} from '../actions/mutes'; +import { + NOTIFICATIONS_UPDATE, +} from '../actions/notifications'; const initialState = ImmutableMap({ followers: ImmutableMap(), @@ -44,6 +55,8 @@ const initialState = ImmutableMap({ mutes: ImmutableMap(), groups: ImmutableMap(), groups_removed_accounts: ImmutableMap(), + pinned: ImmutableMap(), + birthday_reminders: ImmutableMap(), }); const normalizeList = (state, type, id, accounts, next) => { @@ -98,6 +111,16 @@ export default function userLists(state = initialState, action) { return state.setIn(['mutes', 'items'], ImmutableOrderedSet(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); case MUTES_EXPAND_SUCCESS: return state.updateIn(['mutes', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); + case DIRECTORY_FETCH_SUCCESS: + return state.setIn(['directory', 'items'], ImmutableOrderedSet(action.accounts.map(item => item.id))).setIn(['directory', 'isLoading'], false); + case DIRECTORY_EXPAND_SUCCESS: + return state.updateIn(['directory', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['directory', 'isLoading'], false); + case DIRECTORY_FETCH_REQUEST: + case DIRECTORY_EXPAND_REQUEST: + return state.setIn(['directory', 'isLoading'], true); + case DIRECTORY_FETCH_FAIL: + case DIRECTORY_EXPAND_FAIL: + return state.setIn(['directory', 'isLoading'], false); case GROUP_MEMBERS_FETCH_SUCCESS: return normalizeList(state, 'groups', action.id, action.accounts, action.next); case GROUP_MEMBERS_EXPAND_SUCCESS: @@ -108,6 +131,10 @@ export default function userLists(state = initialState, action) { return appendToList(state, 'groups_removed_accounts', action.id, action.accounts, action.next); case GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS: return state.updateIn(['groups_removed_accounts', action.groupId, 'items'], list => list.filterNot(item => item === action.id)); + case PINNED_ACCOUNTS_FETCH_SUCCESS: + return normalizeList(state, 'pinned', action.id, action.accounts, action.next); + case BIRTHDAY_REMINDERS_FETCH_SUCCESS: + return state.setIn(['birthday_reminders', action.id], ImmutableOrderedSet(action.accounts.map(item => item.id))); default: return state; } diff --git a/app/soapbox/selectors/index.js b/app/soapbox/selectors/index.js index 9594a5750..b7ca3a14a 100644 --- a/app/soapbox/selectors/index.js +++ b/app/soapbox/selectors/index.js @@ -1,14 +1,15 @@ -import { createSelector } from 'reselect'; import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, } from 'immutable'; -import { getDomain } from 'soapbox/utils/accounts'; -import ConfigDB from 'soapbox/utils/config_db'; +import { createSelector } from 'reselect'; + import { getSettings } from 'soapbox/actions/settings'; -import { shouldFilter } from 'soapbox/utils/timelines'; +import { getDomain } from 'soapbox/utils/accounts'; import { validId } from 'soapbox/utils/auth'; +import ConfigDB from 'soapbox/utils/config_db'; +import { shouldFilter } from 'soapbox/utils/timelines'; const getAccountBase = (state, id) => state.getIn(['accounts', id], null); const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null); @@ -170,6 +171,8 @@ export const getAlerts = createSelector([getAlertsBase], (base) => { arr.push({ message: item.get('message'), title: item.get('title'), + actionLabel: item.get('actionLabel'), + actionLink: item.get('actionLink'), key: item.get('key'), className: `snackbar snackbar--${item.get('severity', 'info')}`, activeClassName: 'snackbar--active', @@ -209,8 +212,8 @@ export const getAccountGallery = createSelector([ export const makeGetChat = () => { return createSelector( [ - (state, { id }) => state.getIn(['chats', id]), - (state, { id }) => state.getIn(['accounts', state.getIn(['chats', id, 'account'])]), + (state, { id }) => state.getIn(['chats', 'items', id]), + (state, { id }) => state.getIn(['accounts', state.getIn(['chats', 'items', id, 'account'])]), (state, { last_message }) => state.getIn(['chat_messages', last_message]), ], diff --git a/app/soapbox/service_worker/web_push_notifications.js b/app/soapbox/service_worker/web_push_notifications.js index 2b322b325..c0eb4982e 100644 --- a/app/soapbox/service_worker/web_push_notifications.js +++ b/app/soapbox/service_worker/web_push_notifications.js @@ -1,8 +1,9 @@ import IntlMessageFormat from 'intl-messageformat'; import 'intl-pluralrules'; -import locales from './web_push_locales'; import { unescape } from 'lodash'; +import locales from './web_push_locales'; + const MAX_NOTIFICATIONS = 5; const GROUP_TAG = 'tag'; @@ -72,7 +73,7 @@ const formatMessage = (messageId, locale, values = {}) => (new IntlMessageFormat(locales[locale][messageId], locale)).format(values); const htmlToPlainText = html => - unescape(html.replace(//g, '\n').replace(/<\/p>

      /g, '\n\n').replace(/<[^>]*>/g, '')); + unescape(html.replace(//g, '\n').replace(/<\/p><[^>]*>/g, '\n\n').replace(/<[^>]*>/g, '')); const handlePush = (event) => { const { access_token, notification_id, preferred_locale, title, body, icon } = event.data.json(); @@ -90,7 +91,7 @@ const handlePush = (event) => { options.image = notification.status && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url || undefined; options.data = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/@${notification.account.username}/posts/${notification.status.id}` : `/@${notification.account.username}` }; - if (notification.status && notification.status.spoiler_text || notification.status.sensitive) { + if (notification.status?.spoiler_text || notification.status.sensitive) { options.data.hiddenBody = htmlToPlainText(notification.status.content); options.data.hiddenImage = notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url; diff --git a/app/soapbox/store/configureStore.js b/app/soapbox/store/configureStore.js index 63f92cf53..2c094c4a4 100644 --- a/app/soapbox/store/configureStore.js +++ b/app/soapbox/store/configureStore.js @@ -1,8 +1,9 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; -import appReducer from '../reducers'; + import errorsMiddleware from '../middleware/errors'; import soundsMiddleware from '../middleware/sounds'; +import appReducer from '../reducers'; export default function configureStore() { return createStore(appReducer, compose(applyMiddleware( diff --git a/app/soapbox/stream.js b/app/soapbox/stream.js index c6d648d7d..fb0474367 100644 --- a/app/soapbox/stream.js +++ b/app/soapbox/stream.js @@ -1,6 +1,7 @@ 'use strict'; import WebSocketClient from '@gamestdio/websocket'; + import { getAccessToken } from 'soapbox/utils/auth'; const randomIntUpTo = max => Math.floor(Math.random() * Math.floor(max)); diff --git a/app/soapbox/test_helpers.js b/app/soapbox/test_helpers.js index e77985e91..719c29129 100644 --- a/app/soapbox/test_helpers.js +++ b/app/soapbox/test_helpers.js @@ -1,13 +1,14 @@ 'use strict'; -import React from 'react'; -import thunk from 'redux-thunk'; -import renderer from 'react-test-renderer'; -import { Provider } from 'react-redux'; -import { IntlProvider } from 'react-intl'; -import { BrowserRouter } from 'react-router-dom'; -import configureMockStore from 'redux-mock-store'; import { Map as ImmutableMap } from 'immutable'; +import React from 'react'; +import { IntlProvider } from 'react-intl'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import renderer from 'react-test-renderer'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; + import rootReducer from 'soapbox/reducers'; // Mock Redux diff --git a/app/soapbox/test_setup.js b/app/soapbox/test_setup.js index 05f248813..a3432a744 100644 --- a/app/soapbox/test_setup.js +++ b/app/soapbox/test_setup.js @@ -2,6 +2,7 @@ import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; + import { __clear as clearApiMocks } from 'soapbox/api'; // Enzyme diff --git a/app/soapbox/utils/__tests__/accounts-test.js b/app/soapbox/utils/__tests__/accounts-test.js index d7477c133..15a42ec57 100644 --- a/app/soapbox/utils/__tests__/accounts-test.js +++ b/app/soapbox/utils/__tests__/accounts-test.js @@ -1,3 +1,5 @@ +import { fromJS } from 'immutable'; + import { getDomain, acctFull, @@ -5,7 +7,6 @@ import { isAdmin, isModerator, } from '../accounts'; -import { fromJS } from 'immutable'; describe('getDomain', () => { const account = fromJS({ diff --git a/app/soapbox/utils/__tests__/config_db-test.js b/app/soapbox/utils/__tests__/config_db-test.js index 2a185fbf4..b8ad15e0f 100644 --- a/app/soapbox/utils/__tests__/config_db-test.js +++ b/app/soapbox/utils/__tests__/config_db-test.js @@ -1,7 +1,9 @@ -import { ConfigDB } from '../config_db'; -import config_db from 'soapbox/__fixtures__/config_db.json'; import { fromJS } from 'immutable'; +import config_db from 'soapbox/__fixtures__/config_db.json'; + +import { ConfigDB } from '../config_db'; + test('find', () => { const configs = fromJS(config_db).get('configs'); expect(ConfigDB.find(configs, ':phoenix', ':json_library')).toEqual(fromJS({ diff --git a/app/soapbox/utils/__tests__/emoji_reacts-test.js b/app/soapbox/utils/__tests__/emoji_reacts-test.js index e21dda5e1..c4b05960c 100644 --- a/app/soapbox/utils/__tests__/emoji_reacts-test.js +++ b/app/soapbox/utils/__tests__/emoji_reacts-test.js @@ -1,3 +1,5 @@ +import { fromJS } from 'immutable'; + import { sortEmoji, mergeEmojiFavourites, @@ -8,7 +10,6 @@ import { simulateEmojiReact, simulateUnEmojiReact, } from '../emoji_reacts'; -import { fromJS } from 'immutable'; const ALLOWED_EMOJI = [ '👍', diff --git a/app/soapbox/utils/__tests__/features-test.js b/app/soapbox/utils/__tests__/features-test.js index d9dfdf476..3e722e4ac 100644 --- a/app/soapbox/utils/__tests__/features-test.js +++ b/app/soapbox/utils/__tests__/features-test.js @@ -1,8 +1,9 @@ +import { Map as ImmutableMap } from 'immutable'; + import { parseVersion, getFeatures, } from '../features'; -import { Map as ImmutableMap } from 'immutable'; describe('parseVersion', () => { it('with Pleroma version string', () => { @@ -93,22 +94,6 @@ describe('getFeatures', () => { }); }); - describe('attachmentLimit', () => { - it('is 4 by default', () => { - const instance = ImmutableMap({ version: '3.1.4' }); - const features = getFeatures(instance); - expect(features.attachmentLimit).toEqual(4); - }); - - it('is Infinity for Pleroma', () => { - const instance = ImmutableMap({ - version: '2.7.2 (compatible; Pleroma 1.1.50-42-g3d9ac6ae-develop)', - }); - const features = getFeatures(instance); - expect(features.attachmentLimit).toEqual(Infinity); - }); - }); - describe('focalPoint', () => { it('is true for Mastodon 2.3.0+', () => { const instance = ImmutableMap({ version: '2.3.0' }); diff --git a/app/soapbox/utils/__tests__/timelines-test.js b/app/soapbox/utils/__tests__/timelines-test.js index 7b9124559..d631c19ea 100644 --- a/app/soapbox/utils/__tests__/timelines-test.js +++ b/app/soapbox/utils/__tests__/timelines-test.js @@ -1,6 +1,7 @@ -import { shouldFilter } from '../timelines'; import { fromJS } from 'immutable'; +import { shouldFilter } from '../timelines'; + describe('shouldFilter', () => { it('returns false under normal circumstances', () => { const columnSettings = fromJS({}); diff --git a/app/soapbox/utils/auth.js b/app/soapbox/utils/auth.js index c697578a1..0d0c6c321 100644 --- a/app/soapbox/utils/auth.js +++ b/app/soapbox/utils/auth.js @@ -57,3 +57,8 @@ export const getAuthUserUrl = state => { me, ]).find(isURL); }; + +/** Get the VAPID public key. */ +export const getVapidKey = state => { + return state.getIn(['auth', 'app', 'vapid_key']) || state.getIn(['instance', 'pleroma', 'vapid_public_key']); +}; diff --git a/app/soapbox/utils/code.js b/app/soapbox/utils/code.js index 01786a2ff..49d6b8352 100644 --- a/app/soapbox/utils/code.js +++ b/app/soapbox/utils/code.js @@ -1,7 +1,8 @@ // @preval -const pkg = require('../../../package.json'); const { execSync } = require('child_process'); +const pkg = require('../../../package.json'); + const shortRepoName = url => new URL(url).pathname.substring(1); const trimHash = hash => hash.substring(0, 7); diff --git a/app/soapbox/utils/config_db.js b/app/soapbox/utils/config_db.js index 4d03aaa17..98fe650d9 100644 --- a/app/soapbox/utils/config_db.js +++ b/app/soapbox/utils/config_db.js @@ -20,7 +20,7 @@ const toSimplePolicy = configs => { return acc.set(trimStart(key, ':'), ImmutableSet(hosts)); }; - if (config && config.get) { + if (config?.get) { const value = config.get('value', ImmutableList()); return value.reduce(reducer, ImmutableMap()); } else { diff --git a/app/soapbox/utils/ethereum.js b/app/soapbox/utils/ethereum.js new file mode 100644 index 000000000..3bd8db7b1 --- /dev/null +++ b/app/soapbox/utils/ethereum.js @@ -0,0 +1,26 @@ +export const ethereum = () => window.ethereum; + +export const hasEthereum = () => Boolean(ethereum()); + +// Requests an Ethereum wallet from the browser +// Returns a Promise containing the Ethereum wallet address (string). +export const getWallet = () => { + return ethereum().request({ method: 'eth_requestAccounts' }) + .then(wallets => wallets[0]); +}; + +// Asks the browser to sign a message with Ethereum. +// Returns a Promise containing the signature (string). +export const signMessage = (wallet, message) => { + return ethereum().request({ method: 'personal_sign', params: [message, wallet] }); +}; + +// Combines the above functions. +// Returns an object with the `wallet` and `signature` +export const getWalletAndSign = message => { + return getWallet().then(wallet => { + return signMessage(wallet, message).then(signature => { + return { wallet, signature }; + }); + }); +}; diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index e36892e76..54355e005 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -1,20 +1,21 @@ // Detect backend features to conditionally render elements -import gte from 'semver/functions/gte'; -import lt from 'semver/functions/lt'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; import { createSelector } from 'reselect'; +import gte from 'semver/functions/gte'; +import lt from 'semver/functions/lt'; const any = arr => arr.some(Boolean); // For uglification export const MASTODON = 'Mastodon'; export const PLEROMA = 'Pleroma'; +export const MITRA = 'Mitra'; + +export const getFeatures = createSelector([instance => instance], instance => { + const v = parseVersion(instance.get('version')); + const features = instance.getIn(['pleroma', 'metadata', 'features'], ImmutableList()); + const federation = instance.getIn(['pleroma', 'metadata', 'federation'], ImmutableMap()); -export const getFeatures = createSelector([ - instance => parseVersion(instance.get('version')), - instance => instance.getIn(['pleroma', 'metadata', 'features'], ImmutableList()), - instance => instance.getIn(['pleroma', 'metadata', 'federation'], ImmutableMap()), -], (v, features, federation) => { return { bookmarks: any([ v.software === MASTODON && gte(v.compatVersion, '3.1.0'), @@ -24,8 +25,15 @@ export const getFeatures = createSelector([ v.software === MASTODON && gte(v.compatVersion, '2.1.0'), v.software === PLEROMA && gte(v.version, '0.9.9'), ]), - suggestions: v.software === MASTODON && gte(v.compatVersion, '2.4.3'), - suggestionsV2: v.software === MASTODON && gte(v.compatVersion, '3.4.0'), + suggestions: any([ + v.software === MASTODON && gte(v.compatVersion, '2.4.3'), + features.includes('v2_suggestions'), + ]), + suggestionsV2: any([ + v.software === MASTODON && gte(v.compatVersion, '3.4.0'), + features.includes('v2_suggestions'), + ]), + blockersVisible: features.includes('blockers_visible'), trends: v.software === MASTODON && gte(v.compatVersion, '3.0.0'), mediaV2: any([ v.software === MASTODON && gte(v.compatVersion, '3.1.3'), @@ -42,12 +50,12 @@ export const getFeatures = createSelector([ ]), emojiReacts: v.software === PLEROMA && gte(v.version, '2.0.0'), emojiReactsRGI: v.software === PLEROMA && gte(v.version, '2.2.49'), - attachmentLimit: v.software === PLEROMA ? Infinity : 4, focalPoint: v.software === MASTODON && gte(v.compatVersion, '2.3.0'), importAPI: v.software === PLEROMA, importMutes: v.software === PLEROMA && gte(v.version, '2.2.0'), emailList: features.includes('email_list'), chats: v.software === PLEROMA && gte(v.version, '2.1.0'), + chatsV2: v.software === PLEROMA && gte(v.version, '2.3.0'), scopes: v.software === PLEROMA ? 'read write follow push admin' : 'read write follow push', federating: federation.get('enabled', true), // Assume true unless explicitly false richText: v.software === PLEROMA, @@ -57,17 +65,50 @@ export const getFeatures = createSelector([ resetPasswordAPI: v.software === PLEROMA, exposableReactions: features.includes('exposable_reactions'), accountSubscriptions: v.software === PLEROMA && gte(v.version, '1.0.0'), + accountNotifies: any([ + v.software === MASTODON && gte(v.compatVersion, '3.3.0'), + v.software === PLEROMA && gte(v.version, '2.4.50'), + ]), unrestrictedLists: v.software === PLEROMA, accountByUsername: v.software === PLEROMA, + profileDirectory: any([ + v.software === MASTODON && gte(v.compatVersion, '3.0.0'), + features.includes('profile_directory'), + ]), + accountLookup: any([ + v.software === MASTODON && gte(v.compatVersion, '3.4.0'), + v.software === PLEROMA && gte(v.version, '2.4.50'), + ]), + remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'), + explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'), + accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'), + quotePosts: any([ + v.software === PLEROMA && gte(v.version, '2.4.50'), + instance.get('feature_quote') === true, + ]), + birthdays: v.software === PLEROMA && gte(v.version, '2.4.50'), + ethereumLogin: v.software === MITRA, + accountMoving: v.software === PLEROMA && gte(v.version, '2.4.50'), }; }); export const parseVersion = version => { const regex = /^([\w\.]*)(?: \(compatible; ([\w]*) (.*)\))?$/; const match = regex.exec(version); - return { - software: match[2] || MASTODON, - version: match[3] || match[1], - compatVersion: match[1], - }; + + if (match) { + return { + software: match[2] || MASTODON, + version: match[3] || match[1], + compatVersion: match[1], + }; + } else { + // If we can't parse the version, this is a new and exotic backend. + // Fall back to minimal featureset. + return { + software: null, + version: '0.0.0', + compatVersion: '0.0.0', + }; + } }; diff --git a/app/soapbox/utils/html.js b/app/soapbox/utils/html.js index 247e98c88..9eddcf876 100644 --- a/app/soapbox/utils/html.js +++ b/app/soapbox/utils/html.js @@ -1,6 +1,25 @@ // NB: This function can still return unsafe HTML export const unescapeHTML = (html) => { const wrapper = document.createElement('div'); - wrapper.innerHTML = html.replace(//g, '\n').replace(/<\/p>

      /g, '\n\n').replace(/<[^>]*>/g, ''); + wrapper.innerHTML = html.replace(//g, '\n').replace(/<\/p><[^>]*>/g, '\n\n').replace(/<[^>]*>/g, ''); return wrapper.textContent; }; + +export const stripCompatibilityFeatures = html => { + const node = document.createElement('div'); + node.innerHTML = html; + + const selectors = [ + '.quote-inline', + '.recipients-inline', + ]; + + // Remove all instances of all selectors + selectors.forEach(selector => { + node.querySelectorAll(selector).forEach(elem => { + elem.remove(); + }); + }); + + return node.innerHTML; +}; diff --git a/app/soapbox/utils/instance.js b/app/soapbox/utils/instance.js new file mode 100644 index 000000000..af9d69665 --- /dev/null +++ b/app/soapbox/utils/instance.js @@ -0,0 +1,11 @@ +export const getHost = instance => { + try { + return new URL(instance.get('uri')).host; + } catch { + try { + return new URL(`https://${instance.get('uri')}`).host; + } catch { + return null; + } + } +}; diff --git a/app/soapbox/utils/numbers.js b/app/soapbox/utils/numbers.js index 434473b40..8191692b3 100644 --- a/app/soapbox/utils/numbers.js +++ b/app/soapbox/utils/numbers.js @@ -1,7 +1,7 @@ import React from 'react'; import { FormattedNumber } from 'react-intl'; -const isNumber = number => typeof number === 'number' && !isNaN(number); +export const isNumber = number => typeof number === 'number' && !isNaN(number); export const shortNumberFormat = number => { if (!isNumber(number)) return '•'; diff --git a/app/soapbox/utils/quirks.js b/app/soapbox/utils/quirks.js index 764b10e26..c64631078 100644 --- a/app/soapbox/utils/quirks.js +++ b/app/soapbox/utils/quirks.js @@ -1,12 +1,17 @@ -import { parseVersion } from './features'; +import { createSelector } from 'reselect'; + +import { parseVersion, PLEROMA, MITRA } from './features'; // For solving bugs between API implementations -export const getQuirks = instance => { - const v = parseVersion(instance.get('version')); +export const getQuirks = createSelector([ + instance => parseVersion(instance.get('version')), +], (v) => { return { - invertedPagination: v.software === 'Pleroma', + invertedPagination: v.software === PLEROMA, + noApps: v.software === MITRA, + noOAuthForm: v.software === MITRA, }; -}; +}); export const getNextLinkName = getState => getQuirks(getState().get('instance')).invertedPagination ? 'prev' : 'next'; diff --git a/app/soapbox/utils/resize_image.js b/app/soapbox/utils/resize_image.js index d801cc200..4d0040078 100644 --- a/app/soapbox/utils/resize_image.js +++ b/app/soapbox/utils/resize_image.js @@ -43,44 +43,44 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { // Some browsers don't allow reading from a canvas and instead return all-white // or randomized data. Use a pre-defined image to check if reading the canvas // works. -const checkCanvasReliability = () => new Promise((resolve, reject) => { - switch(_browser_quirks['canvas-read-unreliable']) { - case true: - reject('Canvas reading unreliable'); - break; - case false: - resolve(); - break; - default: - // 2×2 GIF with white, red, green and blue pixels - const testImageURL = - 'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7'; - const refData = - [255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]; - const img = new Image(); - img.onload = () => { - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); - context.drawImage(img, 0, 0, 2, 2); - const imageData = context.getImageData(0, 0, 2, 2); - if (imageData.data.every((x, i) => refData[i] === x)) { - _browser_quirks['canvas-read-unreliable'] = false; - resolve(); - } else { - _browser_quirks['canvas-read-unreliable'] = true; - reject('Canvas reading unreliable'); - } - }; - img.onerror = () => { - _browser_quirks['canvas-read-unreliable'] = true; - reject('Failed to load test image'); - }; - img.src = testImageURL; - } -}); +// const checkCanvasReliability = () => new Promise((resolve, reject) => { +// switch(_browser_quirks['canvas-read-unreliable']) { +// case true: +// reject('Canvas reading unreliable'); +// break; +// case false: +// resolve(); +// break; +// default: +// // 2×2 GIF with white, red, green and blue pixels +// const testImageURL = +// 'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7'; +// const refData = +// [255, 255, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]; +// const img = new Image(); +// img.onload = () => { +// const canvas = document.createElement('canvas'); +// const context = canvas.getContext('2d'); +// context.drawImage(img, 0, 0, 2, 2); +// const imageData = context.getImageData(0, 0, 2, 2); +// if (imageData.data.every((x, i) => refData[i] === x)) { +// _browser_quirks['canvas-read-unreliable'] = false; +// resolve(); +// } else { +// _browser_quirks['canvas-read-unreliable'] = true; +// reject('Canvas reading unreliable'); +// } +// }; +// img.onerror = () => { +// _browser_quirks['canvas-read-unreliable'] = true; +// reject('Failed to load test image'); +// }; +// img.src = testImageURL; +// } +// }); const getImageUrl = inputFile => new Promise((resolve, reject) => { - if (window.URL && URL.createObjectURL) { + if (window.URL?.createObjectURL) { try { resolve(URL.createObjectURL(inputFile)); } catch (error) { @@ -162,8 +162,10 @@ const resizeImage = (img, inputFile, maxPixels) => new Promise((resolve, reject) const newWidth = Math.round(Math.sqrt(maxPixels * (width / height))); const newHeight = Math.round(Math.sqrt(maxPixels * (height / width))); - checkCanvasReliability() - .then(getOrientation(img, type)) + // Skip canvas reliability check for now (it's unreliable) + // checkCanvasReliability() + // .then(getOrientation(img, type)) + getOrientation(img, type) .then(orientation => processImage(img, { width: newWidth, height: newHeight, @@ -189,6 +191,9 @@ export default (inputFile, maxPixels = DEFAULT_MAX_PIXELS) => new Promise((resol resizeImage(img, inputFile, maxPixels) .then(resolve) - .catch(() => resolve(inputFile)); + .catch(error => { + console.error(error); + resolve(inputFile); + }); }).catch(() => resolve(inputFile)); }); diff --git a/app/soapbox/utils/state.js b/app/soapbox/utils/state.js index 8cd6db20d..5ccb4284d 100644 --- a/app/soapbox/utils/state.js +++ b/app/soapbox/utils/state.js @@ -4,10 +4,10 @@ */ import { getSoapboxConfig } from'soapbox/actions/soapbox'; -import { isPrerendered } from 'soapbox/precheck'; -import { isURL } from 'soapbox/utils/auth'; -import { getBaseURL as getAccountBaseURL } from 'soapbox/utils/accounts'; import { BACKEND_URL } from 'soapbox/build_config'; +import { isPrerendered } from 'soapbox/precheck'; +import { getBaseURL as getAccountBaseURL } from 'soapbox/utils/accounts'; +import { isURL } from 'soapbox/utils/auth'; export const displayFqn = state => { const soapbox = getSoapboxConfig(state); diff --git a/app/soapbox/utils/static.js b/app/soapbox/utils/static.js index e9fcd7001..fd5dee9d8 100644 --- a/app/soapbox/utils/static.js +++ b/app/soapbox/utils/static.js @@ -4,6 +4,7 @@ */ import { join } from 'path'; + import { FE_SUBDIRECTORY } from 'soapbox/build_config'; export const joinPublicPath = (...paths) => { diff --git a/app/soapbox/utils/status.js b/app/soapbox/utils/status.js new file mode 100644 index 000000000..48554ced9 --- /dev/null +++ b/app/soapbox/utils/status.js @@ -0,0 +1,15 @@ +export const getFirstExternalLink = status => { + try { + // Pulled from Pleroma's media parser + const selector = 'a:not(.mention,.hashtag,.attachment,[rel~="tag"])'; + const element = document.createElement('div'); + element.innerHTML = status.content; + return element.querySelector(selector); + } catch { + return null; + } +}; + +export const shouldHaveCard = status => { + return Boolean(getFirstExternalLink(status)); +}; diff --git a/app/styles/about.scss b/app/styles/about.scss index 53a20ac9d..af281ff00 100644 --- a/app/styles/about.scss +++ b/app/styles/about.scss @@ -97,6 +97,7 @@ $fluid-breakpoint: $maximum-width + 20px; } .input { + flex: 1; margin-bottom: 0; margin-right: 10px; @@ -690,6 +691,11 @@ $fluid-breakpoint: $maximum-width + 20px; .otp-form-overlay__close { align-self: flex-end; + + .svg-icon { + height: 20px; + width: 20px; + } } } } diff --git a/app/styles/accounts.scss b/app/styles/accounts.scss index 5c61002f6..340680f10 100644 --- a/app/styles/accounts.scss +++ b/app/styles/accounts.scss @@ -425,6 +425,10 @@ a .account__avatar { display: flex; flex-wrap: wrap; padding: 4px 2px; + + .empty-column-indicator { + margin: -4px -2px; + } } .account-gallery__item { @@ -456,6 +460,11 @@ a .account__avatar { display: flex; flex-direction: row; padding: 10px 0; + + &__button .svg-icon { + height: 20px; + width: 20px; + } } .account__section-headline { @@ -545,3 +554,9 @@ a .account__avatar { padding-right: 3px; } } + +.account__birthday { + display: flex; + align-items: center; + white-space: nowrap; +} diff --git a/app/styles/application.scss b/app/styles/application.scss index e8f054202..41ef7cf14 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -31,6 +31,7 @@ @import 'navigation'; @import 'placeholder'; @import 'autosuggest'; +@import 'developers'; // COMPONENTS @import 'components/buttons'; @@ -50,6 +51,7 @@ @import 'components/emoji-reacts'; @import 'components/status'; @import 'components/reply-indicator'; +@import 'components/reply-mentions'; @import 'components/detailed-status'; @import 'components/list-forms'; @import 'components/media-gallery'; @@ -91,6 +93,8 @@ @import 'components/profile-stats'; @import 'components/progress-circle'; @import 'components/register-invite'; +@import 'components/radio-button'; +@import 'components/directory'; // Holiday @import 'holiday/halloween'; diff --git a/app/styles/chats.scss b/app/styles/chats.scss index ba324be24..418d0eca8 100644 --- a/app/styles/chats.scss +++ b/app/styles/chats.scss @@ -26,11 +26,16 @@ .search--account { border-top: 1px solid hsla(var(--primary-text-color_hsl), 0.2); + padding: 5px; .autosuggest-textarea__suggestions { top: auto; bottom: 100%; } + + input.search__input { + border-radius: 6px; + } } &__header { @@ -111,6 +116,10 @@ flex-direction: column; overflow: hidden; } + + .chat-list { + overflow-y: auto; + } } .audio-toggle .react-toggle-thumb { @@ -175,7 +184,7 @@ &:hover, &:focus, - &:active, { + &:active { .chat-message__menu { opacity: 1; pointer-events: all; @@ -205,16 +214,22 @@ position: absolute; top: -8px; right: -8px; + height: 20px; + padding: 1px; background: var(--background-color); border-radius: 999px; opacity: 0; pointer-events: none; transition: 0.2s; + + .svg-icon { + height: 20px; + width: 20px; + } } } .chat-list { - overflow-y: auto; flex: 1; &__content { @@ -228,6 +243,10 @@ align-items: start; } + .account { + border-bottom: none; + } + .account__display-name { position: relative; @@ -382,13 +401,22 @@ } .page { + .chat-messages { + margin-bottom: 60px; + } + .chat-box { border-radius: 0; border: 2px solid var(--foreground-color); margin-bottom: var(--thumb-navigation-height); &__actions { + width: 100%; padding: 0; + position: fixed; + bottom: 60px; + left: 0; + z-index: 1; textarea { height: 4em; @@ -450,6 +478,10 @@ } .chat { + &__attachment-icon { + float: right; + } + &__last-message { display: block; overflow: hidden; @@ -459,6 +491,10 @@ a { color: var(--highlight-text-color); } + + &.attachment { + font-style: italic; + } } } diff --git a/app/styles/components/account-header.scss b/app/styles/components/account-header.scss index 69902227c..deaf47a3a 100644 --- a/app/styles/components/account-header.scss +++ b/app/styles/components/account-header.scss @@ -114,15 +114,67 @@ } } - &__avatar { - display: block; + @keyframes fadeIn { + 1% { + visibility: visible; + } + + 100% { + visibility: visible; + } + } + + @keyframes fadeOut { + 1% { + visibility: visible; + } + + 100% { + visibility: hidden; + } + } + + &__card { + display: flex; + flex-direction: column; position: absolute; left: 0; top: -90px; + + &.is-locked { + .account__header__avatar { + top: -20px; + opacity: 0; + animation: 0.3s fadeOut; + animation-fill-mode: forwards; + } + + .account__header__name { + top: 90px; + opacity: 1; + animation: 0.3s fadeIn; + animation-fill-mode: forwards; + } + } + + @media screen and (max-width: 895px) { + top: -45px; + left: 10px; + } + } + + &__avatar { + display: block; + position: absolute; + top: 0; border-radius: 50%; height: 200px; width: 200px; background-color: var(--foreground-color); + opacity: 1; + animation: 0.3s fadeIn; + animation-fill-mode: forwards; + transition: top 0.3s, opacity 0.15s; // NOTE - patch fix for avatar size. Wrapper may not be needed when I do polish up on the page .account__avatar { @@ -149,7 +201,6 @@ } @media screen and (max-width: 895px) { - top: -45px; left: 20px; left: max(20px + env(safe-area-inset-left)); height: 90px; @@ -163,6 +214,49 @@ } } + &__name { + display: flex; + align-items: center; + column-gap: 10px; + width: 265px; + height: 74px; + position: absolute; + top: 100px; + opacity: 0; + animation: 0.3s fadeOut; + animation-fill-mode: forwards; + transition: top 0.3s, opacity 0.15s; + + div:nth-child(2) { + width: calc(100% - 50px); + color: var(--primary-text-color); + + span:first-of-type { + display: inline-block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 18px; + line-height: 1.25; + font-weight: 600; + + &.with-badge { + max-width: calc(100% - 20px); + } + } + + small { + display: flex; + font-size: 14px; + color: var(--primary-text-color--faint); + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + } + } + } + &__extra { display: flex; flex-direction: row; @@ -202,13 +296,21 @@ padding: 7px; opacity: 0.6; - &:hover { + &:hover, + &:focus { opacity: 1; } .svg-icon { width: 20px; height: 20px; + + svg { + &.feather { + // Feather icons are a little larger + transform: scale(0.9); + } + } } } diff --git a/app/styles/components/admin.scss b/app/styles/components/admin.scss index 3f9ed12da..88a34b05c 100644 --- a/app/styles/components/admin.scss +++ b/app/styles/components/admin.scss @@ -102,10 +102,12 @@ margin-left: auto; display: flex; flex-wrap: nowrap; + column-gap: 10px; padding-left: 20px; - button.icon-button:nth-child(n+2) { - padding-left: 10px; + .svg-icon { + height: 24px; + width: 24px; } } } @@ -183,8 +185,10 @@ } &__actions { - margin-left: auto; display: flex; + align-items: center; + height: fit-content; + margin-left: auto; .icon-button { padding-left: 10px; @@ -193,6 +197,11 @@ display: flex; align-items: center; justify-content: center; + + > .svg-icon { + height: 20px; + width: 20px; + } } } } diff --git a/app/styles/components/buttons.scss b/app/styles/components/buttons.scss index 51157bf31..677ae8e28 100644 --- a/app/styles/components/buttons.scss +++ b/app/styles/components/buttons.scss @@ -67,7 +67,7 @@ button { &:disabled, &.disabled { - background-color: var(--brand-color--med); + opacity: 0.2; cursor: default; } diff --git a/app/styles/components/columns.scss b/app/styles/components/columns.scss index 633fb612c..6670d41ea 100644 --- a/app/styles/components/columns.scss +++ b/app/styles/components/columns.scss @@ -286,7 +286,8 @@ .column-link { background: var(--brand-color--med); color: var(--primary-text-color); - display: block; + display: flex; + align-items: center; font-size: 16px; padding: 15px; text-decoration: none; @@ -318,7 +319,7 @@ } } -.column-link__icon { +.svg-icon.column-link__icon { display: inline-block; margin-right: 5px; } @@ -745,6 +746,15 @@ .column-settings__row { .text-btn { margin-bottom: 15px; + + &.column-header__setting-btn { + display: flex; + align-items: center; + + .svg-icon { + margin-right: 10px; + } + } } } @@ -814,12 +824,19 @@ } .timeline-filter-message { + display: flex; + align-items: center; background-color: var(--brand-color--faint); color: var(--primary-text-color); padding: 15px 20px; .icon-button { - margin-right: 8px; + margin: 2px 8px 2px 0; + + .svg-icon { + height: 20px; + width: 20px; + } } } @@ -938,6 +955,9 @@ .sub-navigation ~ .ptr > .ptr__children > { // ScrollableList .slist .item-list > article:first-child, + // ScrollableList placeholders + .slist .item-list .slist__placeholder:first-child > .material-status:first-child, + .slist.slist--flex .item-list > .material-status:first-child, // Thread .material-status:not(.material-status + .material-status) { // MaterialStatus diff --git a/app/styles/components/compose-form.scss b/app/styles/components/compose-form.scss index 8c583edff..4c1537f4f 100644 --- a/app/styles/components/compose-form.scss +++ b/app/styles/components/compose-form.scss @@ -84,13 +84,27 @@ .spoiler-input__input { border-radius: 4px; } + &__quoted-status-wrapper { + background: var(--background-color); + + .quoted-status { + &:hover, + &:focus, + &:active { + background: transparent; + cursor: unset; + } + } + } + &.condensed { .autosuggest-textarea__textarea { min-height: 46px; border-radius: 5px; } - .compose-form__buttons-wrapper { + .compose-form__buttons-wrapper, + .compose-form__quoted-status-wrapper { height: 0; padding: 0; overflow: hidden; diff --git a/app/styles/components/datepicker.scss b/app/styles/components/datepicker.scss index 78a20b01f..dd74db173 100644 --- a/app/styles/components/datepicker.scss +++ b/app/styles/components/datepicker.scss @@ -19,6 +19,11 @@ &__cancel { padding-left: 10px; + + .svg-icon { + height: 24px; + width: 24px; + } } &--error .react-datepicker__input-container { @@ -28,6 +33,7 @@ .datepicker .react-datepicker { box-shadow: 0 0 6px 0 rgb(0 0 0 / 30%); + font-family: inherit; font-size: 12px; border: 0; border-radius: 10px; @@ -64,14 +70,14 @@ } input { - padding: 0 0 0 10px; + padding: 0 0 0 8px; } &::before { content: '\f073'; display: inline-block; - font: normal normal normal 14px/1 ForkAwesome; - font-size: 14px; + font: normal normal normal 14px/1 "Font Awesome 5 Free"; + font-size: 18px; color: var(--primary-text-color--faint); } } diff --git a/app/styles/components/detailed-status.scss b/app/styles/components/detailed-status.scss index 6215a1c95..2defdcd3e 100644 --- a/app/styles/components/detailed-status.scss +++ b/app/styles/components/detailed-status.scss @@ -88,6 +88,7 @@ color: var(--primary-text-color--faint); text-decoration: none; font-size: 13px; + cursor: pointer; } .detailed-status__button { @@ -185,17 +186,29 @@ } } - &__descendants .thread__status:first-child { + &__descendants &__status:first-child { margin-top: 10px; + + .status__wrapper--filtered { + margin-top: -10px; + } } &__status--focused:first-child, &__ancestors &__status:first-child { margin-top: 10px; + + .status__wrapper--filtered { + margin-top: -10px; + } } &__descendants &__status:last-child { margin-bottom: 10px; + + .status__wrapper--filtered { + margin-bottom: -10px; + } } &__connector { diff --git a/app/styles/components/directory.scss b/app/styles/components/directory.scss new file mode 100644 index 000000000..62f6c7172 --- /dev/null +++ b/app/styles/components/directory.scss @@ -0,0 +1,175 @@ +.directory { + &__filter-form { + display: flex; + background: var(--foreground-color); + + &__column { + padding: 10px 15px; + } + + .radio-button { + display: block; + } + } + + &__list { + display: grid; + grid-gap: 10px; + grid-template-columns: minmax(0, 50%) minmax(0, 50%); + width: 100%; + padding: 10px; + transition: opacity 100ms ease-in; + box-sizing: border-box; + + &.loading { + opacity: 0.7; + } + + @media screen and (max-width: 630px) { + grid-template-columns: minmax(0, 100%); + } + } + + &__card { + box-sizing: border-box; + margin-bottom: 0; + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.1); + border-radius: 10px; + background: var(--foreground-color); + overflow: hidden; + position: relative; + + &__info { + z-index: 1; + position: absolute; + top: 10px; + left: 10px; + } + + &__action-button { + z-index: 1; + position: absolute; + top: 78px; + right: 12px; + } + + &__img { + height: 125px; + position: relative; + background: var(--brand-color--med); + + img { + display: block; + width: 100%; + height: 100%; + margin: 0; + object-fit: cover; + } + } + + &__bar { + display: flex; + align-items: center; + background: var(--brand-color--med); + padding: 10px; + + &__name { + flex: 1 1 auto; + display: flex; + align-items: center; + text-decoration: none; + overflow: hidden; + } + + .account__avatar { + flex: 0 0 auto; + width: 48px; + min-width: 48px; + height: 48px; + padding-top: 2px; + + img { + width: 100%; + height: 100%; + display: block; + margin: 0; + border-radius: 4px; + background: var(--brand-color--faint); + object-fit: cover; + } + } + + .display-name { + margin-left: 15px; + text-align: left; + + strong { + font-size: 15px; + color: var(--primary-text-color); + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + } + + span:not(.verified-icon) { + display: block; + font-size: 14px; + color: var(--primary-text-color--faint); + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + } + } + } + + &__extra { + background: var(--foreground-color); + display: flex; + align-items: center; + justify-content: center; + + .accounts-table__count { + padding: 15px 0; + text-align: center; + font-size: 15px; + font-weight: 500; + width: 33.33%; + flex: 0 0 auto; + + small { + display: block; + color: var(--primary-text-color--faint); + font-weight: 400; + font-size: 14px; + } + } + + .account__header__content { + box-sizing: border-box; + padding: 15px 10px; + border-bottom: 1px solid var(--brand-color--med); + width: 100%; + min-height: 50px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + &.empty { + border-color: transparent; + } + + p { + display: none; + + &:first-child { + display: inline; + } + } + + br { + display: none; + } + } + } + } +} diff --git a/app/styles/components/dropdown-menu.scss b/app/styles/components/dropdown-menu.scss index 39dd1772e..5c705db81 100644 --- a/app/styles/components/dropdown-menu.scss +++ b/app/styles/components/dropdown-menu.scss @@ -52,42 +52,60 @@ ul { overflow: hidden; - padding: 6px 0; + padding: 2px 0; } - &__item a { - display: flex; - align-items: center; - box-sizing: border-box; - overflow: hidden; - padding: 4px 10px; - font-size: 15px; - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - color: var(--primary-text-color); + &__item { + a { + display: flex; + align-items: center; + box-sizing: border-box; + overflow: hidden; + margin: 0 6px; + padding: 4px; + border-radius: 6px; + font-size: 15px; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--primary-text-color); + } - &:focus, - &:hover, - &:active { - outline: 0; - color: #fff; - background: var(--brand-color) !important; - - * { + a { + &:focus, + &:hover, + &:active { + outline: 0; color: #fff; + background: var(--brand-color); + + * { + color: #fff; + } + } + + .svg-icon:first-child { + height: 20px; + width: 20px; + min-width: 20px; + margin-right: 10px; + transition: none; + + svg { + stroke-width: 1.5; + transition: none; + } } } - .svg-icon:first-child { - height: 20px; - width: 20px; - margin-right: 10px; - transition: none; + &.destructive a { + color: var(--warning-color--hicontrast); - svg { - stroke-width: 1.5; - transition: none; + &:focus, + &:hover, + &:active { + background: var(--warning-color); + color: #fff; } } } diff --git a/app/styles/components/emoji-reacts.scss b/app/styles/components/emoji-reacts.scss index 9af8b33ca..353ab043e 100644 --- a/app/styles/components/emoji-reacts.scss +++ b/app/styles/components/emoji-reacts.scss @@ -19,6 +19,10 @@ + .emoji-react { margin-right: -8px; } + + &[type='button'] { + cursor: pointer; + } } .emoji-react--reblogs, diff --git a/app/styles/components/federation-restrictions.scss b/app/styles/components/federation-restrictions.scss index 72dacc118..1b60e01cb 100644 --- a/app/styles/components/federation-restrictions.scss +++ b/app/styles/components/federation-restrictions.scss @@ -20,6 +20,10 @@ &__icon { width: 16px; + + .svg-icon svg { + stroke-width: 1.3; + } } &--expanded &__icon i.fa { diff --git a/app/styles/components/list-forms.scss b/app/styles/components/list-forms.scss index bc784fd31..354d170ec 100644 --- a/app/styles/components/list-forms.scss +++ b/app/styles/components/list-forms.scss @@ -14,6 +14,10 @@ border-radius: 8px 8px 0 0; } + &__content { + padding: 0; + } + &__accounts { background: var(--background-color); overflow-y: auto; @@ -33,7 +37,7 @@ .search { display: flex; flex-direction: row; - margin: 10px 0; + margin: 10px; > label { flex: 1 1; diff --git a/app/styles/components/mfa_form.scss b/app/styles/components/mfa_form.scss index 10ab69fc7..f16f782e3 100644 --- a/app/styles/components/mfa_form.scss +++ b/app/styles/components/mfa_form.scss @@ -1,6 +1,10 @@ .security-settings-panel { margin: 20px; + .simple_form { + padding: 0 !important; + } + h1.security-settings-panel__setup-otp { font-size: 20px; line-height: 1.25; @@ -16,11 +20,6 @@ font-weight: 400; } - div { - display: block; - margin: 10px 0; - } - .security-warning { color: var(--primary-text-color); padding: 15px 20px; @@ -31,7 +30,7 @@ } .backup_codes { - margin: 20px; + margin: 10px 0; font-weight: bold; padding: 15px 20px; font-size: 14px; @@ -40,33 +39,40 @@ text-align: center; position: relative; min-height: 125px; + display: flex; + justify-content: center; + align-items: center; .backup_code { margin: 5px auto; } - - .loading-indicator { - position: absolute; - } } .security-settings-panel__setup-otp__buttons { - margin: 20px; + margin: 15px 0; display: flex; justify-content: space-between; .button { - min-width: 182px; + flex: 1; } } - div.confirm-key { + &__qr-code { + margin: 20px 0; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + &__confirm-key { display: block; - font-size: 16px; + font-size: 14px; line-height: 1.5; color: var(--primary-text-color--faint); font-weight: 400; - margin: 0 0 20px 20px; + margin-top: 10px; } } diff --git a/app/styles/components/modal.scss b/app/styles/components/modal.scss index cf77960c5..aa12f4092 100644 --- a/app/styles/components/modal.scss +++ b/app/styles/components/modal.scss @@ -199,8 +199,15 @@ position: absolute; right: 8px; top: 8px; + height: 48px; + width: 48px; z-index: 100; color: #fff; + + .svg-icon { + height: 48px; + width: 48px; + } } .onboarding-modal, @@ -332,7 +339,10 @@ .confirmation-modal, .report-modal, .actions-modal, -.mute-modal { +.mute-modal, +.reactions-modal, +.reblogs-modal, +.mentions-modal { position: relative; flex-direction: column; overflow: hidden; @@ -378,6 +388,17 @@ } } +.reactions-modal, +.reblogs-modal, +.mentions-modal { + height: 80vh; + max-height: 650px; + + .slist { + overflow: auto; + } +} + .boost-modal__container { overflow-x: scroll; padding: 10px; @@ -392,10 +413,10 @@ .confirmation-modal__action-bar, .mute-modal__action-bar { display: flex; + align-items: center; justify-content: space-between; background: var(--background-color); padding: 10px; - line-height: 36px; & > div { flex: 1 1 auto; @@ -581,6 +602,11 @@ transition: none; } + &.destructive { + color: var(--warning-color--hicontrast); + opacity: 1; + } + &.active, &:hover, &:focus { @@ -601,6 +627,11 @@ svg { stroke-width: 1.5; + + &.feather { + // Feather icons are a little larger + transform: scale(0.9); + } } } } @@ -683,6 +714,14 @@ .media-modal__close { top: 19px; right: 15px; + height: 20px; + width: 20px; + + .svg-icon { + color: var(--primary-text-color); + height: 20px; + width: 20px; + } } } @@ -700,7 +739,8 @@ } } -.compose-modal { +.compose-modal, +.reply-mentions-modal { overflow: hidden; background-color: var(--background-color); border-radius: 6px; @@ -730,6 +770,15 @@ } } + @media screen and (max-width: 895px) { + margin: 0; + border-radius: 0; + height: 100vh; + width: 100vw; + } +} + +.compose-modal { &__close { position: absolute; right: 10px; @@ -783,12 +832,27 @@ padding: 10px 0; } } +} - @media screen and (max-width: 895px) { - margin: 0; - border-radius: 0; - height: 100vh; - width: 100vw; +.reply-mentions-modal { + &__back { + position: absolute; + left: 10px; + left: max(10px, env(safe-area-inset-right)); + color: var(--primary-text-color--faint); + + .svg-icon { + width: 24px; + height: 24px; + } + } + + &__accounts { + display: block; + flex-direction: row; + flex: 1; + overflow-y: auto; + min-height: 300px; } } @@ -835,6 +899,59 @@ } } +.remote-interaction-modal { + &__content { + display: flex; + flex-direction: column; + // align-items: center; + row-gap: 10px; + padding: 10px; + + .unauthorized-modal-content__button { + margin: 0 auto; + } + } + + &__fields { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; + + .button { + width: auto; + margin: 0; + text-transform: none; + overflow: unset; + } + } + + &__divider { + display: flex; + align-items: center; + gap: 10px; + margin: 0 -10px; + + &::before, + &::after { + content: ""; + flex: 1; + border-bottom: 1px solid hsla(var(--primary-text-color_hsl), 0.2); + } + } + + @media screen and (max-width: 895px) { + margin: 0; + border-radius: 6px; + height: unset !important; + width: 440px !important; + } + + @media screen and (max-width: 480px) { + width: 330px !important; + } +} + .focal-point-modal { max-width: 80vw; max-height: 80vh; @@ -949,3 +1066,27 @@ margin-bottom: 0; } } + +.confirmation-modal, +.mute-modal { + &__header { + display: flex; + align-items: center; + column-gap: 6px; + padding: 20px; + padding-bottom: 0; + font-size: 22px; + + .svg-icon { + height: 24px; + width: 24px; + color: var(--primary-text-color); + opacity: 0.6; + } + } + + &__container { + padding: 20px; + text-align: left; + } +} diff --git a/app/styles/components/notification.scss b/app/styles/components/notification.scss index 0a1e58a09..1bcbb937c 100644 --- a/app/styles/components/notification.scss +++ b/app/styles/components/notification.scss @@ -89,3 +89,18 @@ padding-bottom: 8px !important; } } + +.notification-birthday span[type="button"] { + &:focus, + &:hover, + &:active { + text-decoration: underline; + cursor: pointer; + } +} + +.columns-area .notification-birthday { + .notification__message { + padding-top: 0; + } +} diff --git a/app/styles/components/profile-info-panel.scss b/app/styles/components/profile-info-panel.scss index 99bf66c09..a3c3f6dc5 100644 --- a/app/styles/components/profile-info-panel.scss +++ b/app/styles/components/profile-info-panel.scss @@ -22,7 +22,8 @@ flex-wrap: wrap; } - &__join-date { + &__join-date, + &__birthday { display: flex; font-size: 14px; color: var(--primary-text-color--faint); diff --git a/app/styles/components/radio-button.scss b/app/styles/components/radio-button.scss new file mode 100644 index 000000000..d1a303f3f --- /dev/null +++ b/app/styles/components/radio-button.scss @@ -0,0 +1,35 @@ +.radio-button { + font-size: 14px; + position: relative; + display: inline-block; + padding: 6px 0; + line-height: 18px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; + + input[type=radio], + input[type=checkbox] { + display: none; + } + + &__input { + display: inline-block; + position: relative; + border: 1px solid var(--primary-text-color--faint); + box-sizing: border-box; + width: 18px; + height: 18px; + flex: 0 0 auto; + margin-right: 10px; + top: -1px; + border-radius: 50%; + vertical-align: middle; + + &.checked { + border-color: var(--brand-color); + background: var(--brand-color); + } + } +} diff --git a/app/styles/components/reply-indicator.scss b/app/styles/components/reply-indicator.scss index 367c6164a..f200dca31 100644 --- a/app/styles/components/reply-indicator.scss +++ b/app/styles/components/reply-indicator.scss @@ -18,7 +18,11 @@ .reply-indicator__cancel { float: right; - line-height: 24px; + + .svg-icon { + height: 20px; + width: 20px; + } } .reply-indicator__display-name { diff --git a/app/styles/components/reply-mentions.scss b/app/styles/components/reply-mentions.scss new file mode 100644 index 000000000..cd693803e --- /dev/null +++ b/app/styles/components/reply-mentions.scss @@ -0,0 +1,29 @@ +.reply-mentions { + margin: 0 10px; + color: var(--primary-text-color--faint); + font-size: 15px; + text-decoration: none; + + &__account, + a { + color: var(--highlight-text-color); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } +} + +.status__wrapper, +.detailed-status, +.quoted-status { + .reply-mentions { + display: block; + margin: 4px 0 0 0; + + span { + cursor: pointer; + } + } +} diff --git a/app/styles/components/sidebar-menu.scss b/app/styles/components/sidebar-menu.scss index b69e22db6..321cadc95 100644 --- a/app/styles/components/sidebar-menu.scss +++ b/app/styles/components/sidebar-menu.scss @@ -155,7 +155,7 @@ > .fa { width: 24px; - font-size: 20px; + font-size: 28px; margin-right: 15px; text-align: center; } @@ -165,7 +165,8 @@ height: 28px; margin-right: 15px; - svg.icon-tabler { + svg.icon-tabler, + svg.feather { stroke-width: 1px; } } diff --git a/app/styles/components/snackbar.scss b/app/styles/components/snackbar.scss index ffbb4c502..3f43043ca 100644 --- a/app/styles/components/snackbar.scss +++ b/app/styles/components/snackbar.scss @@ -55,4 +55,19 @@ .notification-bar-wrapper { transform: translateY(1px); } + + .notification-bar-action a { + @include font-roboto; + font-size: 16px; + color: white; + font-weight: 700; + text-decoration: none; + text-transform: none; + + &:hover, + &:active, + &:focus { + text-decoration: underline; + } + } } diff --git a/app/styles/components/status.scss b/app/styles/components/status.scss index a1eb66295..ba06c5039 100644 --- a/app/styles/components/status.scss +++ b/app/styles/components/status.scss @@ -127,7 +127,7 @@ } .status__wrapper--filtered { - color: var(--primary-text-color); + color: var(--primary-text-color--faint); border: 0; font-size: inherit; text-align: center; @@ -137,7 +137,6 @@ box-sizing: border-box; width: 100%; clear: both; - border-bottom: 1px solid var(--brand-color--med); } .status__prepend-icon-wrapper { @@ -339,6 +338,16 @@ font-weight: 500; color: var(--brand-color); } + + &--reblog { + > div { + display: flex; + + > .icon-button { + margin-right: 8px; + } + } + } } } @@ -473,15 +482,14 @@ } } -.focusable { - &:focus { - outline: 0; - box-shadow: 0 0 6px 0 hsla(var(--brand-color_hsl), 0.7); +.focusable:focus, +.focusable-within:focus-within { + outline: 0; + box-shadow: 0 0 6px 0 hsla(var(--brand-color_hsl), 0.7); - .status.status-direct { - &.muted { - background: transparent; - } + .status.status-direct { + &.muted { + background: transparent; } } } @@ -590,6 +598,11 @@ a.status-card { .status-card__description { color: var(--primary-text-color--faint); + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 5; + -webkit-box-orient: vertical; } .status-card__host { @@ -748,3 +761,79 @@ a.status-card.compact:hover { .pending-status { opacity: 0.5; } + +.quoted-status { + margin-top: 14px; + border: 1px solid var(--brand-color--med); + border-radius: 10px; + padding: 12px; + transition: background 0.2s; + cursor: pointer; + + &:hover, + &:focus, + &:active { + background: var(--brand-color--faint); + } + + &__relative-time { + padding-top: 4px; + } + + &__display-name { + color: var(--primary-text-color); + display: block; + max-width: 100%; + line-height: 24px; + overflow: hidden; + padding-right: 25px; + text-decoration: none; + + .display-name__account { + color: var(--primary-text-color--faint); + } + } + + &__display-avatar { + float: left; + margin-right: 5px; + } + + .reply-mentions { + font-size: 14px; + } + + &__content { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 6; + -webkit-box-orient: vertical; + max-height: 114px; + margin-top: 5px; + font-size: 14px; + + a { + color: var(--highlight-text-color); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + + .attachment-thumbs .media-gallery { + margin-top: 5px !important; + } + + &-tombstone { + margin-top: 14px; + padding: 12px; + border: 1px solid var(--brand-color--med); + border-radius: 10px; + color: var(--primary-text-color--faint); + font-size: 14px; + text-align: center; + } +} diff --git a/app/styles/components/wtf-panel.scss b/app/styles/components/wtf-panel.scss index b76e7a6e4..1e5e13230 100644 --- a/app/styles/components/wtf-panel.scss +++ b/app/styles/components/wtf-panel.scss @@ -30,6 +30,7 @@ &.svg-icon { width: 20px; + min-width: 20px; height: 20px; } } @@ -159,6 +160,10 @@ &__menu { margin-left: auto; + + > div { + height: 18px; + } } } diff --git a/app/styles/developers.scss b/app/styles/developers.scss new file mode 100644 index 000000000..b33877120 --- /dev/null +++ b/app/styles/developers.scss @@ -0,0 +1,21 @@ +.developers-challenge { + .code { + font-family: 'Roboto Mono', monospace; + cursor: text; + background-color: var(--background-color); + } + + span.code { + padding: 2px 4px; + border-radius: 4px; + } + + pre.code { + line-height: 1.6em; + overflow-x: auto; + border-radius: 6px; + padding: 8px 12px; + margin: 20px 0; + word-break: break-all; + } +} diff --git a/app/styles/emoji_picker.scss b/app/styles/emoji_picker.scss index 6398aeb32..9fb1a326c 100644 --- a/app/styles/emoji_picker.scss +++ b/app/styles/emoji_picker.scss @@ -169,7 +169,7 @@ } &:hover::before { - z-index: 0; + z-index: -1; content: ""; position: absolute; top: 0; @@ -344,4 +344,8 @@ height: 22px; text-align: center; } + + .fa-hack { + margin: 0 auto; + } } diff --git a/app/styles/forms.scss b/app/styles/forms.scss index 05bcbc0a4..64ab2fb4d 100644 --- a/app/styles/forms.scss +++ b/app/styles/forms.scss @@ -371,13 +371,13 @@ code { select { border-color: lighten($error-red, 12%); } + } - .error { - display: block; - font-weight: 500; - color: lighten($error-red, 12%); - margin-top: 4px; - } + .error { + display: block; + font-weight: 500; + color: lighten($error-red, 12%); + margin-top: 4px; } .input.disabled { @@ -496,7 +496,7 @@ code { &::after { display: flex; align-items: center; - font-family: "ForkAwesome"; + font-family: 'Font Awesome 5 Free'; content: ""; position: absolute; right: 12px; @@ -504,6 +504,7 @@ code { padding-left: 12px; pointer-events: none; margin-top: 8px; + font-weight: 900; } } @@ -608,6 +609,86 @@ code { margin-bottom: 14px; font-weight: bold; } + + .showable-password { + position: relative; + + input { + padding-right: 36px; + } + + .icon-button { + position: absolute; + top: 0; + right: 0; + height: 41px; + width: 36px; + padding: 0; + margin: 0; + background: transparent; + color: var(--primary-text-color); + + .svg-icon { + height: 20px; + width: 20px; + } + } + } + + .datepicker { + padding: 0; + margin-bottom: 8px; + border: none; + + &__hint { + padding-bottom: 0; + color: var(--primary-text-color); + font-size: 14px; + font-style: unset; + } + + .react-datepicker { + &__header { + padding-top: 4px; + } + + &__input-container { + border: 1px solid var(--highlight-text-color); + + input { + border: none; + } + } + } + + &__years, + &__months { + display: flex; + justify-content: space-between; + align-items: center; + margin: 0 4px; + font-size: 16px; + } + + &__button { + width: 28px; + margin: 0; + padding: 4px; + background: transparent; + color: var(--primary-text-color); + + &:hover, + &:active, + &:focus { + background: none; + } + + .svg-icon { + height: 20px; + width: 20px; + } + } + } } .block-icon { @@ -617,20 +698,6 @@ code { font-size: 24px; } -.qr-code { - flex: 0 0 auto; - background: var(--foreground-color); - padding: 4px; - margin: 0 10px 20px 0; - box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); - display: inline-block; - - svg { - display: block; - margin: 0; - } -} - .simple_form { .warning { box-sizing: border-box; @@ -741,17 +808,19 @@ code { } } -.input .row > .fa-times-circle { +.input .row > .svg-icon.delete-field { + height: 20px; + width: 20px; position: absolute; - right: 15px; + right: 13px; cursor: pointer; color: $error-red; - transform: translateY(-9px); + transform: translateY(-11px); } -.input .row > .input.with_label + .fa-times-circle { - right: 7px; - transform: translateY(9px); +.input .row > .input.with_label + .svg-icon.delete-field { + right: 5px; + transform: translateY(7px); } .site-preview { @@ -798,12 +867,19 @@ code { margin: 10px 0 0; .button { + display: flex; + align-items: center; border: 0; background: transparent; &:hover { color: var(--primary-text-color); } + + .svg-icon { + height: 20px; + width: 20px; + } } } diff --git a/app/styles/loading.scss b/app/styles/loading.scss index c26ec70fe..b5ee78662 100644 --- a/app/styles/loading.scss +++ b/app/styles/loading.scss @@ -173,7 +173,8 @@ clear: both; text-decoration: none; - &:hover { + &:hover, + &:focus { background: var(--brand-color--faint); } } @@ -229,3 +230,110 @@ .ptr__children { overflow: visible !important; } + +.ptr .lds-spinner { + width: 40px; + height: 40px; +} + +/** + * iOS style loading spinner. + * Adapted from: https://loading.io/css/ + * With some help scaling it: https://signalvnoise.com/posts/2577-loading-spinner-animation-using-css-and-webkit + */ +.lds-spinner { + display: inline-block; + position: relative; + width: 80px; + height: 80px; + + div { + position: absolute; + transform-origin: 50% 50%; + animation: lds-spinner 1.2s linear infinite; + width: 100%; + height: 100%; + + &::after { + content: ' '; + display: block; + position: absolute; + top: 3.75%; + left: 46.25%; + width: 7.5%; + height: 22.5%; + border-radius: 20%; + background: var(--primary-text-color); + } + + &:nth-child(1) { + transform: rotate(0deg); + animation-delay: -1.1s; + } + + &:nth-child(2) { + transform: rotate(30deg); + animation-delay: -1s; + } + + &:nth-child(3) { + transform: rotate(60deg); + animation-delay: -0.9s; + } + + &:nth-child(4) { + transform: rotate(90deg); + animation-delay: -0.8s; + } + + &:nth-child(5) { + transform: rotate(120deg); + animation-delay: -0.7s; + } + + &:nth-child(6) { + transform: rotate(150deg); + animation-delay: -0.6s; + } + + &:nth-child(7) { + transform: rotate(180deg); + animation-delay: -0.5s; + } + + &:nth-child(8) { + transform: rotate(210deg); + animation-delay: -0.4s; + } + + &:nth-child(9) { + transform: rotate(240deg); + animation-delay: -0.3s; + } + + &:nth-child(10) { + transform: rotate(270deg); + animation-delay: -0.2s; + } + + &:nth-child(11) { + transform: rotate(300deg); + animation-delay: -0.1s; + } + + &:nth-child(12) { + transform: rotate(330deg); + animation-delay: 0s; + } + } +} + +@keyframes lds-spinner { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} diff --git a/app/styles/navigation.scss b/app/styles/navigation.scss index f590cbd5c..87646cee0 100644 --- a/app/styles/navigation.scss +++ b/app/styles/navigation.scss @@ -87,6 +87,7 @@ color: var(--primary-text-color); text-decoration: none; font-size: 20px; + width: 55px; span { margin-top: 1px; @@ -155,19 +156,29 @@ justify-content: center; color: var(--primary-text-color); opacity: 0.6; + font-size: 16px; + + &:hover, + &:focus { + color: var(--primary-text-color); + } .svg-icon { margin-right: 7px; - width: 22px; - height: 22px; + width: 26px; + height: 26px; } } &__message { position: absolute; + padding: 0 10px; align-self: center; justify-self: center; font-weight: bold; + overflow: hidden; + text-overflow: ellipsis; + max-width: calc(100vw - 200px); } &__cog { diff --git a/app/styles/placeholder.scss b/app/styles/placeholder.scss index 0427e9463..cbdc03a55 100644 --- a/app/styles/placeholder.scss +++ b/app/styles/placeholder.scss @@ -1,6 +1,8 @@ .placeholder-status, .placeholder-hashtag, -.notification--placeholder { +.notification--placeholder, +.status-card--placeholder, +.media-gallery--placeholder { position: relative; &::before { @@ -37,15 +39,15 @@ 100% { background-position-x: 0; } } -.notification--placeholder { - .notification__message span { - color: var(--brand-color); - opacity: 0.1; - } +.notification--placeholder .notification__message span, +.placeholder-hashtag .trends__item__name { + color: var(--brand-color); + opacity: 0.1; } .status__content--placeholder, -.display-name--placeholder { +.display-name--placeholder, +.chat-list-item--placeholder .chat__last-message { letter-spacing: -1px; color: var(--brand-color) !important; opacity: 0.1; @@ -105,3 +107,24 @@ background: transparent; box-shadow: none; } + +.status-card--placeholder { + pointer-events: none; + + .status-card__title, + .status-card__description, + .status-card__host { + letter-spacing: -1px; + color: var(--brand-color) !important; + word-break: break-all; + opacity: 0.1; + } +} + +.media-gallery.media-gallery--placeholder { + background: none; + + .media-gallery__item { + background-color: var(--brand-color--faint); + } +} diff --git a/app/styles/polls.scss b/app/styles/polls.scss index 97871e1b3..ca3503938 100644 --- a/app/styles/polls.scss +++ b/app/styles/polls.scss @@ -167,6 +167,15 @@ margin-right: 10px; font-size: 14px; } + + &__cancel { + height: 20px; + + .svg-icon { + height: 20px; + width: 20px; + } + } } .compose-form__poll-wrapper { diff --git a/app/styles/themes.scss b/app/styles/themes.scss index e1d328b4f..032f8ce4d 100644 --- a/app/styles/themes.scss +++ b/app/styles/themes.scss @@ -88,6 +88,11 @@ body, var(--brand-color_s), calc(var(--brand-color_l) - 12%) ); + --warning-color--hicontrast: hsl( + var(--warning-color_h), + var(--warning-color_s), + calc(var(--warning-color_l) - 12%) + ); } .theme-mode-dark { @@ -119,4 +124,9 @@ body, var(--brand-color_s), calc(var(--brand-color_l) + 12%) ); + --warning-color--hicontrast: hsl( + var(--warning-color_h), + var(--warning-color_s), + calc(var(--warning-color_l) + 12%) + ); } diff --git a/app/styles/ui.scss b/app/styles/ui.scss index b724475e0..de2ce5e3b 100644 --- a/app/styles/ui.scss +++ b/app/styles/ui.scss @@ -221,7 +221,8 @@ } .status__relative-time, -.notification__relative_time { +.notification__relative_time, +.quoted-status__relative-time { color: var(--primary-text-color--faint); float: right; font-size: 14px; @@ -239,6 +240,15 @@ font-size: 14px; font-weight: 500; } + + &__buttons .svg-icon { + height: 18px; + width: 18px; + } +} + +article:last-child > .domain { + border-bottom: none; } .domain__wrapper { @@ -627,10 +637,8 @@ } } -.notification__filter-bar, -.search__filter-bar, -.account__section-headline, -.reaction__filter-bar { +.filter-bar, +.account__section-headline { border-bottom: 1px solid var(--brand-color--faint); cursor: default; display: flex; @@ -675,15 +683,30 @@ background-color: var(--accent-color); } } - } - button .svg-icon { - width: 18px; - height: 18px; - margin: 0 auto; + .svg-icon { + width: 18px; + height: 18px; + margin: 0 auto; + } } } +.filter-bar { + position: relative; + + &__active { + position: absolute; + height: 3px; + bottom: 0; + background-color: var(--accent-color); + } +} + +.no-reduce-motion .filter-bar__active { + transition: all 0.3s; +} + .reaction__filter-bar { overflow-x: auto; overflow-y: hidden; diff --git a/docs/store.md b/docs/store.md index 34088ab8c..7c0bff506 100644 --- a/docs/store.md +++ b/docs/store.md @@ -126,7 +126,8 @@ If it's not documented, it's because I inherited it from Mastodon and I don't kn groups: {}, followers: {}, mutes: {}, - favourited_by: {} + favourited_by: {}, + birthday_reminders: {} } ``` @@ -391,6 +392,9 @@ If it's not documented, it's because I inherited it from Mastodon and I don't kn mention: true, poll: true, reblog: true + }, + birthdays: { + show: true } }, theme: 'azure', diff --git a/package.json b/package.json index dcb0fd414..74e649581 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@sentry/browser": "^6.12.0", "@sentry/react": "^6.12.0", "@sentry/tracing": "^6.12.0", - "@tabler/icons": "^1.41.2", + "@tabler/icons": "^1.53.0", "array-includes": "^3.0.3", "autoprefixer": "^10.0.0", "axios": "^0.21.4", @@ -79,19 +79,20 @@ "detect-passive-events": "^2.0.0", "dotenv": "^8.0.0", "emoji-datasource": "5.0.0", - "emoji-mart": "^3.0.1", + "emoji-mart": "npm:emoji-mart-lazyload", "entities": "^3.0.1", "es6-symbol": "^3.1.1", "escape-html": "^1.0.3", "exif-js": "^2.3.0", "feather-icons": "^4.28.0", "fork-ts-checker-webpack-plugin": "^6.4.0", + "history": "^4.10.1", "html-webpack-harddisk-plugin": "^2.0.0", "html-webpack-plugin": "^5.3.2", "http-link-header": "^1.0.2", "immutable": "^4.0.0-rc.14", "imports-loader": "^1.0.0", - "intersection-observer": "^0.11.0", + "intersection-observer": "^0.12.0", "intl": "^1.2.5", "intl-messageformat": "^9.0.0", "intl-messageformat-parser": "^6.0.0", @@ -118,7 +119,7 @@ "qrcode.react": "^1.0.0", "react": "^16.13.1", "react-color": "^2.18.1", - "react-datepicker": "^4.1.1", + "react-datepicker": "^4.6.0", "react-dom": "^16.13.1", "react-helmet": "^6.0.0", "react-hotkeys": "^1.1.4", @@ -172,7 +173,7 @@ "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.6", "eslint": "^7.0.0", - "eslint-plugin-import": "^2.24.2", + "eslint-plugin-import": "^2.25.4", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-react": "^7.25.1", diff --git a/webpack/development.js b/webpack/development.js index 9beb0cf5a..526ff5c0b 100644 --- a/webpack/development.js +++ b/webpack/development.js @@ -2,7 +2,9 @@ console.log('Running in development mode'); // eslint-disable-line no-console const { join } = require('path'); + const { merge } = require('webpack-merge'); + const sharedConfig = require('./shared'); const watchOptions = {}; diff --git a/webpack/production.js b/webpack/production.js index 220ed8991..53265caf3 100644 --- a/webpack/production.js +++ b/webpack/production.js @@ -2,9 +2,11 @@ console.log('Running in production mode'); // eslint-disable-line no-console const { join } = require('path'); -const { merge } = require('webpack-merge'); -const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + const OfflinePlugin = require('@lcdp/offline-plugin'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const { merge } = require('webpack-merge'); + const sharedConfig = require('./shared'); const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config')); @@ -104,7 +106,11 @@ module.exports = merge(sharedConfig, { ]; const isBackendRoute = ({ pathname }) => { - return backendRoutes.some(pathname.startsWith); + if (pathname) { + return backendRoutes.some(pathname.startsWith); + } else { + return false; + } }; return isBackendRoute(requestUrl) && requestUrl; diff --git a/webpack/rules/babel-build-config.js b/webpack/rules/babel-build-config.js index 78e2b47aa..8b1088fa6 100644 --- a/webpack/rules/babel-build-config.js +++ b/webpack/rules/babel-build-config.js @@ -1,4 +1,5 @@ const { resolve } = require('path'); + const { env } = require('../configuration'); // This is a hack, used to force build_config @preval to recompile diff --git a/webpack/rules/babel-git.js b/webpack/rules/babel-git.js index b68139ed6..eac6c9877 100644 --- a/webpack/rules/babel-git.js +++ b/webpack/rules/babel-git.js @@ -1,4 +1,5 @@ const { resolve } = require('path'); + const { env } = require('../configuration'); // This is a hack, used in conjunction with rules/git-refresh.js diff --git a/webpack/rules/babel.js b/webpack/rules/babel.js index 6c40d6d7f..1272639e9 100644 --- a/webpack/rules/babel.js +++ b/webpack/rules/babel.js @@ -1,4 +1,5 @@ const { join, resolve } = require('path'); + const { env, settings } = require('../configuration'); module.exports = { diff --git a/webpack/rules/index.js b/webpack/rules/index.js index 4c4fa6872..bdf850c6d 100644 --- a/webpack/rules/index.js +++ b/webpack/rules/index.js @@ -1,9 +1,9 @@ -const babel = require('./babel'); -const git = require('./babel-git'); -const gitRefresh = require('./git-refresh'); -const buildConfig = require('./babel-build-config'); -const css = require('./css'); const assets = require('./assets'); +const babel = require('./babel'); +const buildConfig = require('./babel-build-config'); +const git = require('./babel-git'); +const css = require('./css'); +const gitRefresh = require('./git-refresh'); const nodeModules = require('./node_modules'); // Webpack loaders are processed in reverse order diff --git a/webpack/rules/node_modules.js b/webpack/rules/node_modules.js index 403851eed..aa46fe596 100644 --- a/webpack/rules/node_modules.js +++ b/webpack/rules/node_modules.js @@ -1,4 +1,5 @@ const { join } = require('path'); + const { settings, env } = require('../configuration'); module.exports = { diff --git a/webpack/shared.js b/webpack/shared.js index a5d407111..d77475ba7 100644 --- a/webpack/shared.js +++ b/webpack/shared.js @@ -1,13 +1,15 @@ // Note: You must restart bin/webpack-dev-server for changes to take effect -const webpack = require('webpack'); const { join, resolve } = require('path'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const AssetsManifestPlugin = require('webpack-assets-manifest'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); + const CopyPlugin = require('copy-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const webpack = require('webpack'); +const AssetsManifestPlugin = require('webpack-assets-manifest'); + const { env, settings, output } = require('./configuration'); const rules = require('./rules'); diff --git a/webpack/test.js b/webpack/test.js index 36f44aed6..814801ae5 100644 --- a/webpack/test.js +++ b/webpack/test.js @@ -2,6 +2,7 @@ console.log('Running in test mode'); // eslint-disable-line no-console const { merge } = require('webpack-merge'); + const sharedConfig = require('./shared'); module.exports = merge(sharedConfig, { diff --git a/webpack/translationRunner.js b/webpack/translationRunner.js index 5f75ee757..072e53e32 100644 --- a/webpack/translationRunner.js +++ b/webpack/translationRunner.js @@ -1,7 +1,8 @@ const fs = require('fs'); const path = require('path'); + const parser = require('intl-messageformat-parser'); -const { default: manageTranslations, readMessageFiles } = require('react-intl-translations-manager'); +const { default: manageTranslations, readMessageFiles } = require('react-intl-translations-manager'); // eslint-disable-line import/order const RFC5646_REGEXP = /^[a-z]{2,3}(?:-(?:x|[A-Za-z]{2,4}))*$/; @@ -152,7 +153,7 @@ const extractedMessages = extractedMessagesFiles.reduce((acc, messageFile) => { const translations = languages.map((language) => { return { language: language, - data : JSON.parse(fs.readFileSync(path.join(translationsDirectory, language + '.json'), 'utf8')), + data: JSON.parse(fs.readFileSync(path.join(translationsDirectory, language + '.json'), 'utf8')), }; }); diff --git a/yarn.lock b/yarn.lock index a7488578a..28587eaa2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,11 +17,11 @@ "@babel/highlight" "^7.14.5" "@babel/code-frame@^7.8.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== dependencies: - "@babel/highlight" "^7.16.0" + "@babel/highlight" "^7.16.7" "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": version "7.15.0" @@ -240,10 +240,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== "@babel/helper-validator-option@^7.14.5": version "7.14.5" @@ -278,12 +278,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" + "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" @@ -1540,10 +1540,10 @@ remark "^13.0.0" unist-util-find-all-after "^3.0.2" -"@tabler/icons@^1.41.2": - version "1.41.2" - resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.41.2.tgz#effccbb261539b68609cc7dc660a058683170ee1" - integrity sha512-X6cQmMC24hiwg0p2BzasvU3IeCCdOk0f/9d6gNNtJM4lzG2TCloTns1bVvU5MAFkITGukxUqjPFE3Ecd6kGsfw== +"@tabler/icons@^1.53.0": + version "1.53.0" + resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.53.0.tgz#51536e01b343cfaf26b701df306b2c0369769e3c" + integrity sha512-Skk1BqXEOEhiRsXJgZBYtjFa/+4dMSFA5UyzTUW20oyyUSd3iizhEWrYt0jT87iFu771gWoqVV2/OGobBcGjgQ== "@tootallnate/once@1": version "1.1.2" @@ -2126,6 +2126,17 @@ array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.2, array-inclu get-intrinsic "^1.1.1" is-string "^1.0.5" +array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -2150,7 +2161,7 @@ array.prototype.find@^2.1.1: define-properties "^1.1.3" es-abstract "^1.17.4" -array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.4: +array.prototype.flat@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== @@ -2159,6 +2170,15 @@ array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.4: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + array.prototype.flatmap@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" @@ -2727,7 +2747,7 @@ cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.3: parse5-htmlparser2-tree-adapter "^6.0.1" tslib "^2.2.0" -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.2, chokidar@^3.5.1: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -2742,6 +2762,21 @@ cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^3.4.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -3293,10 +3328,10 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@^2.0.1: - version "2.23.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9" - integrity sha512-5ycpauovVyAk0kXNZz6ZoB9AYMZB4DObse7P3BPWmyEjXNORTI8EJ6X0uaSAq4sCHzM1uajzrkr6HnsLQpxGXA== +date-fns@^2.24.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2" + integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw== debug@2.6.9, debug@^2.6.9: version "2.6.9" @@ -3619,12 +3654,13 @@ emoji-datasource@5.0.0: resolved "https://registry.yarnpkg.com/emoji-datasource/-/emoji-datasource-5.0.0.tgz#1522fdba3c52223a1cf5a1c1fc282935400eaa06" integrity sha512-LuvLWFnxznTH++GytEzpzOPUo1SB+6CUFqIlVETJJ3x9fpyMCKFfyqberbhMLOpT1qcNe+km+zoyBeUSC3u5Rw== -emoji-mart@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-3.0.1.tgz#9ce86706e02aea0506345f98464814a662ca54c6" - integrity sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg== +"emoji-mart@npm:emoji-mart-lazyload": + version "3.0.1-j" + resolved "https://registry.yarnpkg.com/emoji-mart-lazyload/-/emoji-mart-lazyload-3.0.1-j.tgz#87a90d30b79d9145ece078d53e3e683c1a10ce9c" + integrity sha512-0wKF7MR0/iAeCIoiBLY+JjXCugycTgYRC2SL0y9/bjNSQlbeMdzILmPQJAufU/mgLFDUitOvjxLDhOZ9yxZ48g== dependencies: "@babel/runtime" "^7.0.0" + intersection-observer "^0.12.0" prop-types "^15.6.0" emoji-regex@^8.0.0: @@ -3653,9 +3689,9 @@ encodeurl@~1.0.2: integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= enhanced-resolve@^5.0.0: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== + version "5.9.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" + integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3795,6 +3831,32 @@ es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.18.0, es-abstract@^1.18 string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -3885,34 +3947,32 @@ eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" -eslint-module-utils@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" - integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== +eslint-module-utils@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz#1d0aa455dcf41052339b63cada8ab5fd57577129" + integrity sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg== dependencies: debug "^3.2.7" - pkg-dir "^2.0.0" + find-up "^2.1.0" -eslint-plugin-import@^2.24.2: - version "2.24.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da" - integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q== +eslint-plugin-import@^2.25.4: + version "2.25.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" + integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== dependencies: - array-includes "^3.1.3" - array.prototype.flat "^1.2.4" + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" debug "^2.6.9" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.6.2" - find-up "^2.0.0" + eslint-module-utils "^2.7.2" has "^1.0.3" - is-core-module "^2.6.0" + is-core-module "^2.8.0" + is-glob "^4.0.3" minimatch "^3.0.4" - object.values "^1.1.4" - pkg-up "^2.0.0" - read-pkg-up "^3.0.0" + object.values "^1.1.5" resolve "^1.20.0" - tsconfig-paths "^3.11.0" + tsconfig-paths "^3.12.0" eslint-plugin-jsx-a11y@^6.4.1: version "6.4.1" @@ -4287,7 +4347,7 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -4326,9 +4386,9 @@ foreach@^2.0.5: integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= fork-ts-checker-webpack-plugin@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.4.0.tgz#057e477cf1d8b013b2ed2669437f818680289c4c" - integrity sha512-3I3wFkc4DbzaUDPWEi96wdYGu4EKtxBafhZYm0o4mX51d9bphAY4P3mBl8K5mFXFJqVzHfmdbm9kLGnm7vwwBg== + version "6.5.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" + integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -4647,7 +4707,7 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -history@^4.7.2: +history@^4.10.1, history@^4.7.2: version "4.10.1" resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== @@ -5011,10 +5071,10 @@ interpret@^2.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -intersection-observer@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.11.0.tgz#f4ea067070326f68393ee161cc0a2ca4c0040c6f" - integrity sha512-KZArj2QVnmdud9zTpKf279m2bbGfG+4/kn16UU0NL3pTVl52ZHiJ9IRNSsnn6jaHrL9EGLFM5eWjTx2fz/+zoQ== +intersection-observer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.0.tgz#6c84628f67ce8698e5f9ccf857d97718745837aa" + integrity sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ== intl-messageformat-parser@6.1.2: version "6.1.2" @@ -5177,13 +5237,20 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.6.0: +is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== dependencies: has "^1.0.3" +is-core-module@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -5235,6 +5302,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-hexadecimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" @@ -5342,6 +5416,11 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -5387,6 +5466,13 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -6170,16 +6256,6 @@ listr2@^3.8.2: through "^2.3.8" wrap-ansi "^7.0.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - loader-runner@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" @@ -6485,9 +6561,9 @@ media-typer@0.3.0: integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= memfs@^3.1.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" - integrity sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg== + version "3.4.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" + integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== dependencies: fs-monkey "1.0.3" @@ -6742,7 +6818,7 @@ node-releases@^1.1.75: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== -normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: +normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -6888,6 +6964,15 @@ object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2, object.values@ define-properties "^1.1.3" es-abstract "^1.18.2" +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -7168,13 +7253,6 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -7195,11 +7273,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -7207,13 +7280,6 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -7221,13 +7287,6 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -7843,16 +7902,16 @@ react-color@^2.18.1: reactcss "^1.2.0" tinycolor2 "^1.4.1" -react-datepicker@^4.1.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.2.1.tgz#72caf5055bc7c4eb0279c1f6d7624ded053edc4c" - integrity sha512-0gcvHMnX8rS1fV90PjjsB7MQdsWNU77JeVHf6bbwK9HnFxgwjVflTx40ebKmHV+leqe+f+FgUP9Nvqbe5RGyfA== +react-datepicker@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.6.0.tgz#10fc7c5b9c72df5c3e29712d559cb3fe73fd9f62" + integrity sha512-JGSQnQSQYUkS7zvSaZuyHv5lxp3wMrN7GXV0VA0E9Ax9fL3Bb6E1pSXjL6C3WoeuV8dt/mItQfRkPpRGCrl/OA== dependencies: "@popperjs/core" "^2.9.2" classnames "^2.2.6" - date-fns "^2.0.1" + date-fns "^2.24.0" prop-types "^15.7.2" - react-onclickoutside "^6.10.0" + react-onclickoutside "^6.12.0" react-popper "^2.2.5" react-dom@^16.13.1: @@ -7982,10 +8041,10 @@ react-notification@^6.8.4: dependencies: prop-types "^15.6.2" -react-onclickoutside@^6.10.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.12.0.tgz#c63db2e3c2c852b288160cdb6cff443604e28db4" - integrity sha512-oPlOTYcISLHfpMog2lUZMFSbqOs4LFcA4+vo7fpfevB5v9Z0D5VBDBkfeO5lv+hpEcGoaGk67braLT+QT+eICA== +react-onclickoutside@^6.12.0: + version "6.12.1" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.12.1.tgz#92dddd28f55e483a1838c5c2930e051168c1e96b" + integrity sha512-a5Q7CkWznBRUWPmocCvE8b6lEYw1s6+opp/60dCunhO+G6E4tDTO2Sd2jKE+leEnnrLAE2Wj5DlDHNqj5wPv1Q== react-overlays@^0.9.0: version "0.9.3" @@ -8163,14 +8222,6 @@ reactcss@^1.2.0: dependencies: lodash "^4.0.1" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -8180,15 +8231,6 @@ read-pkg-up@^7.0.1: read-pkg "^5.2.0" type-fest "^0.8.1" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - read-pkg@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" @@ -9460,10 +9502,10 @@ ts-loader@^9.2.6: micromatch "^4.0.0" semver "^7.3.4" -tsconfig-paths@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" - integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== +tsconfig-paths@^3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" + integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.1" @@ -9569,9 +9611,9 @@ typescript@^4.0: integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== typescript@^4.4.4: - version "4.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6"