Compare commits

...

122 commits

Author SHA1 Message Date
0e80d060dc Merge remote-tracking branch 'upstream/main'
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-26 11:25:14 +02:00
Matt Jankowski
db57fe80c8
Remove page_json var from ap/replies spec (#32000) 2024-09-26 08:54:01 +00:00
github-actions[bot]
278a075b22
New Crowdin Translations (automated) (#32103)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-26 08:47:38 +00:00
Claire
886baa5e35
Fix typo causing incorrect error being raised in blurhash processing failure (#32104) 2024-09-26 07:40:59 +00:00
Christian Schmidt
db332553c9
Rename "Data export" menu item (#32099) 2024-09-25 19:54:28 +00:00
Eugen Rochko
3426ea2912
Add preview of followers removed in domain block modal in web UI (#32032) 2024-09-25 18:13:36 +00:00
Eugen Rochko
28c4eca0af
Change responsive break points on navigation panel in web UI (#32034) 2024-09-25 16:36:19 +00:00
Renaud Chaput
28966fa0a6
Remove deprecated v2_alpha endpoint for grouped notifications (#32089) 2024-09-25 15:21:11 +00:00
Renaud Chaput
739ad0eed2
Keep the status action buttons at their position regardless of the counter size (#32084)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2024-09-25 14:33:58 +00:00
Matt Jankowski
51777fe3e2
Prefer structure checks over multi-line size/parts checks in parsed_body (#32063) 2024-09-25 13:54:22 +00:00
Renaud Chaput
d6f5ee75ab
Add notification grouping for follow notifications (#32085) 2024-09-25 13:36:19 +00:00
Renaud Chaput
3dc4ddc663
Fix search params being dropped when redirected to non-deck path (#31984) 2024-09-25 13:35:37 +00:00
Matt Jankowski
83574f641a
Add coverage and use mailer callback to check functional user in notification mailer (#32055) 2024-09-25 08:07:48 +00:00
Matt Jankowski
c2ef83ea4c
Consolidate shared a scope example parts into one attributes check (#32046) 2024-09-25 07:56:42 +00:00
Matt Jankowski
c3b6a7a297
Reduce factory creation (36 -> 12) in spec/controllers/oauth/* area (#32045) 2024-09-25 07:56:08 +00:00
Matt Jankowski
06ecf9008b
Remove single-use shared examples in controller specs (#32044) 2024-09-25 07:50:15 +00:00
Matt Jankowski
69aa5699ce
Use not-allowed for cursor on disabled buttons (#32076) 2024-09-25 07:43:12 +00:00
github-actions[bot]
4e6fc3a62f
New Crowdin Translations (automated) (#32083)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-25 07:40:14 +00:00
renovate[bot]
a773c239c3
Update dependency aws-sdk-s3 to v1.166.0 (#32079)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-25 07:33:37 +00:00
Eugen Rochko
70988519df
Fix too many requests caused by relationship look-ups in web UI (#32042)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2024-09-24 17:02:36 +00:00
Renaud Chaput
f1b6a611aa
Fix wrapping in dashboard quick access buttons (#32043) 2024-09-24 16:47:45 +00:00
André Menrath
556837f156
Fix the summary of converted object types to be treated as HTML (#28629) 2024-09-24 15:57:53 +00:00
Claire
c36a76b9eb
Fix error when accepting appeal for sensitive posts deleted in the meantime (#32037)
Co-authored-by: David Roetzel <david@roetzel.de>
2024-09-24 15:19:55 +00:00
Claire
0a6b75b71e
Fix multiple bugs in notification requests and notification policies (#32062) 2024-09-24 15:03:38 +00:00
David Roetzel
cfb8fc6222
Increase regexp timeout and allow override (#32056) 2024-09-24 13:16:58 +00:00
Matt Jankowski
19dedd7cfd
Set important mailer headers with after_action callback (#32057) 2024-09-24 13:16:31 +00:00
Matt Jankowski
780e2e9d66
Convert notification mailer spec shared examples to matchers (#32047) 2024-09-24 12:07:16 +00:00
renovate[bot]
7c61533111
Update dependency aws-sdk-s3 to v1.165.0 (#32050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-24 09:54:25 +00:00
github-actions[bot]
11ac5c8929
New Crowdin Translations (automated) (#32052)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-24 09:42:14 +00:00
Claire
c808055fc3
Update dependency webrick (#32054) 2024-09-24 08:16:22 +00:00
Eugen Rochko
d54ce67dc9
Change hide media button to be in top right corner in web UI (#32048) 2024-09-24 08:00:20 +00:00
Matt Jankowski
5dfdec6453
Convert settings/applications controller spec to system/request specs (#32006) 2024-09-23 13:37:32 +00:00
Eugen Rochko
aaab6b7adc
Add reblogs and favourites counts to statuses in ActivityPub (#32007) 2024-09-23 13:14:15 +00:00
Claire
b5bdc69f7b
Change mobile breakpoint back to old version and allow main column to shrink (#32033) 2024-09-23 12:53:35 +00:00
Matt Jankowski
bbf7752256
Combine assertions in Notification model spec (#32015) 2024-09-23 10:45:34 +00:00
Matt Jankowski
2b4bda8004
Add response_avatar_link helper to webfinger request spec (#31999) 2024-09-23 10:44:52 +00:00
Matt Jankowski
447d0a3e88
Remove double no-records cases in api/v1/admin req specs (#32014) 2024-09-23 09:27:53 +00:00
Matt Jankowski
66ed7ea4b5
Move status creation to "with rss" context in accounts request spec (#32020) 2024-09-23 09:20:43 +00:00
Matt Jankowski
cd7b670cd8
Reduce factory creation in User#reset_password! spec (#32021) 2024-09-23 09:18:04 +00:00
Claire
5d6a3f2cb0
Update dependency google-protobuf (#32029) 2024-09-23 09:13:51 +00:00
renovate[bot]
770ec9240a
Update Yarn to v4.5.0 (#31914)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 09:02:16 +00:00
Tim Campbell
11eae691ba
Feature more otel customization (#31998) 2024-09-23 08:55:35 +00:00
github-actions[bot]
ed90d9342e
New Crowdin Translations (automated) (#32011)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-23 08:50:19 +00:00
Matt Jankowski
0ba3ad4a35
Remove body_json_ids from api/v2/admin/accounts spec (#32003) 2024-09-23 08:45:05 +00:00
Matt Jankowski
e0b45b35c9
Combine repeated parsed_body assertions into single (#32002) 2024-09-23 08:42:52 +00:00
Eugen Rochko
5fae1d55e5
Fix OAuth authorization prompt referring to third-party apps (#32005) 2024-09-23 08:42:03 +00:00
renovate[bot]
10d2f83025
Update dependency selenium-webdriver to v4.25.0 (#32008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:41:26 +00:00
renovate[bot]
958f01e722
Update dependency sass to v1.79.3 (#32009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:41:05 +00:00
renovate[bot]
f4632d941a
Update dependency aws-sdk-s3 to v1.164.0 (#32010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:40:46 +00:00
renovate[bot]
c37f9c0d44
Update dependency jsdom to v25.0.1 (#32017)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:36:57 +00:00
renovate[bot]
84d04386dd
Update DefinitelyTyped types (non-major) (#32026)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:35:37 +00:00
renovate[bot]
f294c4a594
Update libretranslate/libretranslate Docker tag to v1.6.1 (#32027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:35:23 +00:00
renovate[bot]
efc0d4d526
Update dependency react-intl to v6.7.0 (#32028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 08:35:11 +00:00
Claire
7ed9c590b9
Fix issue when encountering reblog of deleted post in feed rebuild (#32001) 2024-09-20 14:58:06 +00:00
Claire
ed8b0e4b1e
Fix links for reblogs in moderation interface (#31979) 2024-09-20 13:33:26 +00:00
Matt Jankowski
d55f4fbda1
Add content type checks to api/v2 request specs (#31983) 2024-09-20 13:19:53 +00:00
Matt Jankowski
171394e914
Add coverage for CSV responses for severed relationships (#31962) 2024-09-20 13:13:47 +00:00
Matt Jankowski
66326065b0
Add response.content_type checks for JSON to api/v1 request specs (#31981) 2024-09-20 13:13:04 +00:00
Matt Jankowski
a7dbf6f5a5
Use heredoc/squish for inline css styles in oembed serializer (#31991) 2024-09-20 12:50:51 +00:00
Matt Jankowski
bdf83c353f
Move default embed size knowledge into OEmbedSerializer (#31990)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2024-09-20 12:39:48 +00:00
Claire
8afa3bb2fa
Change Mastodon to issue correctly-signed queries by default (#31994) 2024-09-20 10:10:09 +00:00
Eugen Rochko
e7fd0985c9
Change zoom icon in web UI (#29683) 2024-09-20 09:42:02 +00:00
Matt Jankowski
04a939d640
Add reviewed and unreviewed scopes to Reviewable model concern (#31988) 2024-09-20 08:51:37 +00:00
Matt Jankowski
c922af2737
Add LIMIT constant for api/v1/peers/search endpoint (#31989) 2024-09-20 08:31:58 +00:00
github-actions[bot]
162f9a3c90
New Crowdin Translations (automated) (#31993)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-20 08:31:28 +00:00
renovate[bot]
840fd69730
Update dependency sass to v1.79.2 (#31992)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-20 08:20:27 +00:00
Matt Jankowski
9a03902ab6
Capture actual behavior in v2/notifications "someone else" dismiss scenario (#31985) 2024-09-20 08:16:19 +00:00
renovate[bot]
09459ed000
Update dependency react-select to v5.8.1 (#31982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-20 08:15:14 +00:00
Renaud Chaput
ae03e4ffc6
Update directory page options to use URL params (#31977) 2024-09-19 15:34:08 +00:00
Claire
57a38f071b
Fix custom history.push and history.replace building bogus location if path is omitted (#31980) 2024-09-19 14:58:33 +00:00
Matt Jankowski
5a8f2fe31d
Convert settings/exports controller spec to system/request specs (#31965) 2024-09-19 13:43:40 +00:00
Matt Jankowski
2946a9286b
Use headers shorthand in mailers (#31956) 2024-09-19 13:38:32 +00:00
renovate[bot]
6801afa12f
Update dependency devise-two-factor to v6 [SECURITY] (#31957)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: David Roetzel <david@roetzel.de>
2024-09-19 10:56:09 +00:00
Eugen Rochko
ef4d6ab988
Fix browser glitch caused by two overlapping scroll animations in web UI (#31960) 2024-09-19 10:52:46 +00:00
github-actions[bot]
efdc17513d
New Crowdin Translations (automated) (#31974)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-19 10:34:19 +00:00
Matt Jankowski
5d573c976e
Remove unused E2EE-related methods (#31964) 2024-09-19 10:23:58 +00:00
Matt Jankowski
b071e618e7
Combine API request spec assertions (#31970) 2024-09-19 10:15:21 +00:00
renovate[bot]
1fce55cf5d
Update dependency aws-sdk-s3 to v1.163.0 (#31972)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 09:51:14 +00:00
renovate[bot]
90db524a90
Update dependency puma to v6.4.3 (#31975)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 09:50:58 +00:00
Claire
62a39d60ce
Fix rolling updates by moving DropEndToEndMessageTables to post-deployment migrations (#31963) 2024-09-19 09:50:06 +00:00
Eugen Rochko
29656cb9e0
Fix sass deprecation warning (#31961) 2024-09-18 17:39:32 +00:00
Renaud Chaput
8b70834035
Fix the appearance of avatars when they do not load (#31966) 2024-09-18 17:39:15 +00:00
Matt Jankowski
e3baa1cdda
Add coverage for AccountDeletionRequest class (#31937) 2024-09-18 13:29:57 +00:00
renovate[bot]
42f9f507b6
Update dependency pg to v8.13.0 (#31949)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 13:29:21 +00:00
Matt Jankowski
bf8eaaa9a5
Convert controller spec for security_key_options endpoint to request spec (#31938) 2024-09-18 09:42:36 +00:00
Matt Jankowski
6f836c45aa
Remove crypto values from doorkeeper application/token scopes (#31945) 2024-09-18 09:27:50 +00:00
Matt Jankowski
5405bdd344
Remove unused E2EE messaging code (#31193) 2024-09-18 09:27:43 +00:00
renovate[bot]
2d399f5d4a
Update dependency pg-connection-string to v2.7.0 (#31950)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 09:17:57 +00:00
Christian Schmidt
7740f1a6bb
Mute XHR abort errors (#31952) 2024-09-18 08:43:24 +00:00
renovate[bot]
a791274824
Update dependency sass to v1.79.1 (#31958)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 08:28:42 +00:00
Matt Jankowski
eb16763bff
Use have_http_link_header matcher in api/v1/trends/* specs (#31940) 2024-09-18 08:22:07 +00:00
Matt Jankowski
943738671c
Remove unneeded to_s on Link header comparison in statuses controller spec (#31941) 2024-09-18 08:21:31 +00:00
renovate[bot]
6f3d7516dc
Update dependency dotenv to v3.1.4 (#31953)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 08:10:22 +00:00
github-actions[bot]
bd86c692cf
New Crowdin Translations (automated) (#31959)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-18 08:06:44 +00:00
renovate[bot]
b7548dbf29
Update dependency memory_profiler to v1.1.0 (#31947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 08:05:59 +00:00
Matt Jankowski
a397141d78
Move non-action public method controller callback to private methods (#31933) 2024-09-18 08:05:25 +00:00
renovate[bot]
f3f06dafe3
Update dependency babel-loader to v8.4.1 (#31931)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 08:05:06 +00:00
Claire
3e91c101b3
Bump version to 4.3.0-beta.2 (#31948) 2024-09-17 15:42:45 +00:00
David Roetzel
d8f9db547a
Merge commit from fork
Co-authored-by: Eugen Rochko <eugen@zeonfederated.com>
2024-09-17 16:59:29 +02:00
github-actions[bot]
6a233cbfcf
New Crowdin Translations (automated) (#31946)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-17 13:02:53 +00:00
Claire
d2f9075078
Increase no-gap-breakpoint by 32px to fix overflow (#31889) 2024-09-17 03:19:42 +00:00
Michael Stanclift
5a33a5658b
Fix background of text detection progress (#31943) 2024-09-17 03:19:04 +00:00
Claire
ca8e892c1a
Fix selectSettingsNotificationsExcludedTypes not being memoized properly (#31881) 2024-09-16 14:51:56 +00:00
Claire
6c76a7a907
Fix cancel follow request button sometimes saying “Follow back” (#31934) 2024-09-16 13:20:44 +00:00
Claire
c620452fd7
Enable grouped notifications unconditionally (#31929) 2024-09-16 13:12:10 +00:00
Claire
e0648a916a
Rename /api/v2_alpha/notifications* to /api/v2/notifications* (#31840) 2024-09-16 12:10:02 +00:00
Eugen Rochko
efb0e2c34b
Fix horizontal scrollbar on who to follow carousel in web UI (#31912) 2024-09-16 12:08:37 +00:00
Claire
c0eda832f3
Convert notification requests actions and reducers to Typescript (#31866) 2024-09-16 09:54:03 +00:00
Claire
d5cf27e667
Add global Regexp timeout (#31928) 2024-09-16 09:40:18 +00:00
Matt Jankowski
c54cbf7943
Remove follow creation from ListAccount fabricator (#31902) 2024-09-16 08:56:40 +00:00
github-actions[bot]
474abf3c7f
New Crowdin Translations (automated) (#31911)
Co-authored-by: GitHub Actions <noreply@github.com>
2024-09-16 08:48:20 +00:00
Claire
1d58f93670
Update dependencies omniauth-saml, ruby-xml and ruby-saml (#31926) 2024-09-16 08:48:13 +00:00
Matt Jankowski
bf8b55ce91
Enable Rails/Output in spec/ dir (#31905) 2024-09-16 08:29:06 +00:00
Matt Jankowski
abd2f5654a
Add validation coverage for CustomEmoji shortcode value (#31906) 2024-09-16 07:53:03 +00:00
Matt Jankowski
822e918a56
Add coverage for Bookmark validation and reblog/status check callback (#31907) 2024-09-16 07:52:22 +00:00
renovate[bot]
c24de04f9c
Update dependency postcss to v8.4.47 (#31913)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 07:51:36 +00:00
renovate[bot]
9ea270526c
Update DefinitelyTyped types (non-major) (#31922)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 07:51:13 +00:00
renovate[bot]
2afaa3b3d4
Update dependency husky to v9.1.6 (#31923)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 07:50:51 +00:00
renovate[bot]
0cc05fbb7c
Update dependency i18n to v1.14.6 (#31925)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 07:50:43 +00:00
Claire
4b40d13cb3
Increase preview card image size limit from 2MB to 8MB when using libvips (#31904) 2024-09-14 00:16:02 +00:00
renovate[bot]
5ba3405be4
Update dependency opentelemetry-instrumentation-pg to '~> 0.29.0' (#31897)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-13 12:07:33 +00:00
David Roetzel
c1b2c4fd9a
Strip protocol from attribution domains (#31900) 2024-09-13 11:37:15 +00:00
580 changed files with 5638 additions and 4494 deletions

View file

@ -69,7 +69,7 @@ services:
hard: -1
libretranslate:
image: libretranslate/libretranslate:v1.6.0
image: libretranslate/libretranslate:v1.6.1
restart: unless-stopped
volumes:
- lt-data:/home/libretranslate/.local

View file

@ -7,8 +7,13 @@ RSpec/Focus: # Require full spec run on CI
Exclude: []
Rails/Output: # Remove any `puts` debugging
inherit_mode:
merge:
- Include
Enabled: true
Exclude: []
Include:
- spec/**/*.rb
Rails/FindEach: # Using `each` could impact performance, use `find_each`
Enabled: true

View file

@ -10,21 +10,24 @@ The following changelog entries focus on changes visible to users, administrator
- **Add confirmation interstitial instead of silently redirecting logged-out visitors to remote resources** (#27792, #28902, and #30651 by @ClearlyClaire and @Gargron)\
This fixes a longstanding open redirect in Mastodon, at the cost of added friction when local links to remote resources are shared.
- Change `form-action` Content-Security-Policy directive to be more restrictive (#26897 by @ClearlyClaire)
- Update dependencies
### Added
- **Add experimental server-side notification grouping** (#29889, #30576, #30685, #30688, #30707, #30776, #30779, #30781, #30440, #31062, #31098, #31076, #31111, #31123, #31223, #31214, #31224, #31299, #31325, #31347, #31304, #31326, #31384, #31403, #31433, #31509, #31486, and #31513 by @ClearlyClaire, @mgmn, and @renchap)\
- **Add server-side notification grouping** (#29889, #30576, #30685, #30688, #30707, #30776, #30779, #30781, #30440, #31062, #31098, #31076, #31111, #31123, #31223, #31214, #31224, #31299, #31325, #31347, #31304, #31326, #31384, #31403, #31433, #31509, #31486, #31513, #31592, #31594, #31638, #31746, #31652, #31709, #31725, #31745, #31613, #31657, #31840, #31610 and #31929 by @ClearlyClaire, @Gargron, @mgmn, and @renchap)\
Group notifications of the same type for the same target, so that your notifications no longer get cluttered by boost and favorite notifications as soon as a couple of your posts get traction.\
This is done server-side so that clients can efficiently get relevant groups without having to go through numerous pages of individual notifications.\
As part of this, the visual design of the entire notifications feature has been revamped.\
This feature is intended to eventually replace the existing notifications column, but for this first beta, users will have to enable it in the “Experimental features” section of the notifications column settings.\
The API is not final yet, but it consists of:
- a new `group_key` attribute to `Notification` entities
- `GET /api/v2_alpha/notifications`: https://docs.joinmastodon.org/methods/notifications_alpha/#get-grouped
- `GET /api/v2_alpha/notifications/:group_key`: https://docs.joinmastodon.org/methods/notifications_alpha/#get-notification-group
- `POST /api/v2_alpha/notifications/:group_key/dimsiss`: https://docs.joinmastodon.org/methods/notifications_alpha/#dismiss-group
- `GET /api/v2_alpha/notifications/:unread_count`: https://docs.joinmastodon.org/methods/notifications_alpha/#unread-group-count
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, and #31541 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
- `GET /api/v2/notifications`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-grouped
- `GET /api/v2/notifications/:group_key`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-notification-group
- `GET /api/v2/notifications/:group_key/accounts`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-group-accounts
- `POST /api/v2/notifications/:group_key/dimsiss`: https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group
- `GET /api/v2/notifications/:unread_count`: https://docs.joinmastodon.org/methods/grouped_notifications/#unread-group-count
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, #31541, and #31723 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
The old “Block notifications from non-followers”, “Block notifications from people you don't follow” and “Block direct messages from people you don't follow” notification settings have been replaced by a new set of settings found directly in the notification column.\
You can now separately filter or drop notifications from people you don't follow, people who don't follow you, accounts created within the past 30 days, as well as unsolicited private mentions, and accounts limited by the moderation.\
Instead of being outright dropped, notifications that you chose to filter are put in a separate “Filtered notifications” box that you can review separately without it clogging your main notifications.\
@ -57,19 +60,22 @@ The following changelog entries focus on changes visible to users, administrator
- **Add timeline of public posts about a trending link** (#30381 and #30840 by @Gargron)\
You can now see public posts mentioning currently-trending articles from people who have opted into discovery features.\
This adds a new REST API endpoint: https://docs.joinmastodon.org/methods/timelines/#link
- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, and #30846 by @Gargron)\
- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, #30846, #31819, and #31900 by @Gargron and @oneiros)\
This adds a mechanism to [highlight the author of news articles](https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/) shared on Mastodon.\
Articles hosted outside the fediverse can indicate a fediverse author with a meta tag:
```html
<meta name="fediverse:creator" content="username@domain" />
```
On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors\
Note that this feature is still work in progress and the tagging format and verification mechanisms may change in future releases.
Users can allow arbitrary domains to use `fediverse:creator` to credit them by visiting `/settings/verification`.\
This is federated as a new `attributionDomains` property in the `http://joinmastodon.org/ns` namespace, containing an array of domain names: https://docs.joinmastodon.org/spec/activitypub/#properties-used-1
- **Add in-app notifications for moderation actions and warnings** (#30065, #30082, and #30081 by @ClearlyClaire)\
In addition to email notifications, also notify users of moderation actions or warnings against them directly within the app, so they are less likely to miss important communication from their moderators.\
This adds the `moderation_warning` notification type to the REST API and streaming, with a new [`moderation_warning` attribute](https://docs.joinmastodon.org/entities/Notification/#moderation_warning).
- **Add domain information to profiles in web UI** (#29602 by @Gargron)\
Clicking the domain of a user in their profile will now open a tooltip with a short explanation about servers and federation.
- **Add support for Redis sentinel** (#31694, #31623, #31744, #31767, and #31768 by @ThisIsMissEm and @oneiros)\
See https://docs.joinmastodon.org/admin/scaling/#redis-sentinel
- Add ability to reorder uploaded media before posting in web UI (#28456 by @Gargron)
- Add moderation interface for searching hashtags (#30880 by @ThisIsMissEm)
- Add ability for admins to configure instance favicon and logo (#30040, #30208, #30259, #30375, #30734, #31016, and #30205 by @ClearlyClaire, @FawazFarid, @JasonPunyon, @mgmn, and @renchap)\
@ -77,6 +83,8 @@ The following changelog entries focus on changes visible to users, administrator
- Add `api_versions` to `/api/v2/instance` (#31354 by @ClearlyClaire)\
Add API version number to make it easier for clients to detect compatible features going forward.\
See API documentation at https://docs.joinmastodon.org/entities/Instance/#api-versions
- Add quick links to Administration and Moderation Reports from Web UI (#24838 by @ThisIsMissEm)
- Add link to `/admin/roles` in moderation interface when changing someone's role (#31791 by @ClearlyClaire)
- Add recent audit log entries in federation moderation interface (#27386 by @ThisIsMissEm)
- Add profile setup to onboarding in web UI (#27829, #27876, and #28453 by @Gargron)
- Add prominent share/copy button on profiles in web UI (#27865 and #27889 by @ClearlyClaire and @Gargron)
@ -113,21 +121,24 @@ The following changelog entries focus on changes visible to users, administrator
- Add support for multiple `redirect_uris` when creating OAuth 2.0 Applications (#29192 by @ThisIsMissEm)
- Add Interlingue and Interlingua to interface languages (#28630 and #30828 by @Dhghomon and @renchap)
- Add Kashubian, Pennsylvania Dutch, Vai, Jawi Malay, Mohawk and Low German to posting languages (#26024, #26634, #27136, #29098, #27115, and #27434 by @EngineerDali, @HelgeKrueger, and @gunchleoc)
- Add validations to `Web::PushSubscription` (#30540 and #30542 by @ThisIsMissEm)
- Add option to use native Ruby driver for Redis through `REDIS_DRIVER=ruby` (#30717 by @vmstan)
- Add support for libvips in addition to ImageMagick (#30090, #30590, #30597, #30632, #30857, #30869, and #30858 by @ClearlyClaire, @Gargron, and @mjankowski)\
Server admins can now use libvips as a faster and lighter alternative to ImageMagick for processing user-uploaded images.\
This requires libvips 8.13 or newer, and needs to be enabled with `MASTODON_USE_LIBVIPS=true`.\
This is enabled by default in the official Docker images, and is intended to completely replace ImageMagick in the future.
- Add validations to `Web::PushSubscription` (#30540 and #30542 by @ThisIsMissEm)
- Add anchors to each authorized application in `/oauth/authorized_applications` (#31677 by @fowl2)
- Add active animation to header settings button (#30221, #30307, and #30388 by @daudix)
- Add OpenTelemetry instrumentation (#30130, #30322, #30353, and #30350 by @julianocosta89, @renchap, and @robbkidd)\
See https://docs.joinmastodon.org/admin/config/#otel for documentation
- Add API to get multiple accounts and statuses (#27871 and #30465 by @ClearlyClaire)\
This adds `GET /api/v1/accounts` and `GET /api/v1/statuses` to the REST API, see https://docs.joinmastodon.org/methods/accounts/#index and https://docs.joinmastodon.org/methods/statuses/#index
- Add support for CORS to `POST /oauth/revoke` (#31743 by @ClearlyClaire)
- Add redirection back to previous page after site upload deletion (#30141 by @FawazFarid)
- Add RFC8414 OAuth 2.0 server metadata (#29191 by @ThisIsMissEm)
- Add loading indicator and empty result message to advanced interface search (#30085 by @ClearlyClaire)
- Add `profile` OAuth 2.0 scope, allowing more limited access to user data (#29087 and #30357 by @ThisIsMissEm)
- Add global Regexp timeout (#31928 by @ClearlyClaire)
- Add the role ID to the badge component (#29707 by @renchap)
- Add diagnostic message for failure during CLI search deploy (#29462 by @mjankowski)
- Add pagination `Link` headers on API accounts/statuses when pinned true (#29442 by @mjankowski)
@ -156,14 +167,14 @@ The following changelog entries focus on changes visible to users, administrator
- **Change icons throughout the web interface** (#27385, #27539, #27555, #27579, #27700, #27817, #28519, #28709, #28064, #28775, #28780, #27924, #29294, #29395, #29537, #29569, #29610, #29612, #29649, #29844, #27780, #30974, #30963, #30962, #30961, #31362, #31363, #31359, #31371, #31360, #31512, #31511, and #31525 by @ClearlyClaire, @Gargron, @arbolitoloco1, @mjankowski, @nclm, @renchap, @ronilaukkarinen, and @zunda)\
This changes all the interface icons from FontAwesome to Material Symbols for a more modern look, consistent with the official Mastodon Android app.\
In addition, better care is given to pixel alignment, and icon variants are used to better highlight active/inactive state.
- **Change design of compose form in web UI** (#28119, #29059, #29248, #29372, #29384, #29417, #29456, #29406, #29651, and #29659 by @ClearlyClaire, @Gargron, @eai04191, @hinaloe, and @ronilaukkarinen)\
- **Change design of compose form in web UI** (#28119, #29059, #29248, #29372, #29384, #29417, #29456, #29406, #29651, #29659, and #31889 by @ClearlyClaire, @Gargron, @eai04191, @hinaloe, and @ronilaukkarinen)\
The compose form has been completely redesigned for a more modern and consistent look, as well as spelling out the chosen privacy setting and language name at all times.\
As part of this, the “Unlisted” privacy setting has been renamed to “Quiet public”.
- **Change design of confirmation modals in the web UI** (#29576, #29614, #29640, #29644, #30131, #30884, and #31399 by @ClearlyClaire, @Gargron, and @tribela)\
- **Change design of modals in the web UI** (#29576, #29614, #29640, #29644, #30131, #30884, #31399, #31555, #31752, #31801, #31883, #31844, #31864, and #31943 by @ClearlyClaire, @Gargron, @tribela and @vmstan)\
The mute, block, and domain block confirmation modals have been completely redesigned to be clearer and include more detailed information on the action to be performed.\
They also have a more modern and consistent design, along with other confirmation modals in the application.
- **Change colors throughout the web UI** (#29522, #29584, #29653, #29779, #29803, #29809, #29808, #29828, #31034, #31168, #31266, #31348, #31349, #31361, and #31510 by @ClearlyClaire, @Gargron, @renchap, and @vmstan)
- **Change onboarding prompt to follow suggestions carousel in web UI** (#28878 and #29272 by @Gargron)
- **Change onboarding prompt to follow suggestions carousel in web UI** (#28878, #29272, and #31912 by @Gargron)
- **Change email templates** (#28416, #28755, #28814, #29064, #28883, #29470, #29607, #29761, #29760, and #29879 by @ClearlyClaire, @Gargron, @hteumeuleu, and @mjankowski)\
All emails to end-users have been completely redesigned with a fresh new look, providing more information while making them easier to read and keeping maximum compatibility across mail clients.
- **Change follow recommendations algorithm** (#28314, #28433, #29017, #29108, #29306, #29550, #29619, and #31474 by @ClearlyClaire, @Gargron, @kernal053, @mjankowski, and @wheatear-dev)\
@ -171,19 +182,28 @@ The following changelog entries focus on changes visible to users, administrator
In addition, the implementation has been significantly reworked, and all follow recommendations are now dismissable.\
This change deprecates the `source` attribute in `Suggestion` entities in the REST API, and replaces it with the new [`sources` attribute](https://docs.joinmastodon.org/entities/Suggestion/#sources).
- Change account search algorithm (#30803 by @Gargron)
- **Change streaming server to use its own dependencies and its own docker image** (#24702, #27967, #26850, #28112, #28115, #28137, #28138, #28497, #28548, and #30795 by @TheEssem, @ThisIsMissEm, @jippi, @timetinytim, and @vmstan)\
- **Change streaming server to use its own dependencies and its own docker image** (#24702, #27967, #26850, #28112, #28115, #28137, #28138, #28497, #28548, #30795, #31612, and #31615 by @TheEssem, @ThisIsMissEm, @jippi, @renchap, @timetinytim, and @vmstan)\
In order to reduce the amount of runtime dependencies, the streaming server has been moved into a separate package and Docker image.\
The `mastodon` image does not contain the streaming server anymore, as it has been moved to its own `mastodon-streaming` image.\
Administrators may need to update their setup accordingly.
- Change how content warnings and filters are displayed in web UI (#31365 by @Gargron)
- Change how content warnings and filters are displayed in web UI (#31365, and #31761 by @Gargron)
- Change preview card processing to ignore `undefined` as canonical url (#31882 by @oneiros)
- Change embedded posts to use web UI (#31766 by @Gargron)
- Change inner borders in media galleries in web UI (#31852 by @Gargron)
- Change design of hide media button in web UI (#31807 by @Gargron)
- Change labels on thread indicators in web UI (#31806 by @Gargron)
- Change report action buttons to be disabled when action has already been taken (#31773, #31822, and #31899 by @ClearlyClaire and @ThisIsMissEm)
- Change width of columns in advanced web UI (#31762 by @Gargron)
- Change design of unread conversations in web UI (#31763 by @Gargron)
- Change Web UI to allow viewing and severing relationships with suspended accounts (#27667 by @ClearlyClaire)\
This also adds a `with_suspended` parameter to `GET /api/v1/accounts/relationships` in the REST API.
- Change preview card image size limit from 2MB to 8MB when using libvips (#31904 by @ClearlyClaire)
- Change avatars border radius (#31390 by @renchap)
- Change counters to be displayed on profile timelines in web UI (#30525 by @Gargron)
- Change disabled buttons color in light mode to make the difference more visible (#30998 by @renchap)
- Change design of people tab on explore in web UI (#30059 by @Gargron)
- Change sidebar text in web UI (#30696 by @Gargron)
- Change "Follow" to "Follow back" and "Mutual" when appropriate in web UI (#28452 and #28465 by @Gargron and @renchap)
- Change "Follow" to "Follow back" and "Mutual" when appropriate in web UI (#28452, #28465, and #31934 by @ClearlyClaire, @Gargron and @renchap)
- Change media to be hidden/blurred by default in report modal (#28522 by @ClearlyClaire)
- Change order of the "muting" and "blocking" list options in “Data Exports” (#26088 by @fixermark)
- Change admin and moderation notes character limit from 500 to 2000 characters (#30288 by @ThisIsMissEm)
@ -197,6 +217,7 @@ The following changelog entries focus on changes visible to users, administrator
- Change dropdown menu icon to not be replaced by close icon when open in web UI (#29532 by @Gargron)
- Change back button to always appear in advanced web UI (#29551 and #29669 by @Gargron)
- Change border of active compose field search inputs (#29832 and #29839 by @vmstan)
- Change instances of Nokogiri HTML4 parsing to HTML5 (#31812, #31815, #31813, and #31814 by @flavorjones)
- Change link detection to allow `@` at the end of an URL (#31124 by @adamniedzielski)
- Change User-Agent to use Mastodon as the product, and http.rb as platform details (#31192 by @ClearlyClaire)
- Change layout and wording of the Content Retention server settings page (#27733 by @vmstan)
@ -249,8 +270,17 @@ The following changelog entries focus on changes visible to users, administrator
- Fix various issues when in link preview card generation (#28748, #30017, #30362, #30173, #30853, #30929, #30933, #30957, #30987, and #31144 by @adamniedzielski, @oneiros, @phocks, @timothyjrogers, and @tribela)
- Fix handling of missing links in Webfinger responses (#31030 by @adamniedzielski)
- Fix HTTP 500 error in `/api/v1/polls/:id/votes` when required `choices` parameter is missing (#25598 by @danielmbrasil)
- Fix security context sometimes not being added in LD-Signed activities (#31871 by @ClearlyClaire)
- Fix cross-origin loading of `inert.css` polyfill (#30687 by @louis77)
- Fix cutoff of instance name in sign-up form (#30598 by @oneiros)
- Fix invalid date searches returning 503 errors (#31526 by @notchairmk)
- Fix invalid `visibility` values in `POST /api/v1/statuses` returning 500 errors (#31571 by @c960657)
- Fix some components re-rendering spuriously in web UI (#31879 and #31881 by @ClearlyClaire and @Gargron)
- Fix sort order of moderation notes on Reports and Accounts (#31528 by @ThisIsMissEm)
- Fix email language when recipient has no selected locale (#31747 by @ClearlyClaire)
- Fix frequently-used languages not correctly updating in the web UI (#31386 by @c960657)
- Fix `POST /api/v1/statuses` silently ignoring invalid `media_ids` parameter (#31681 by @c960657)
- Fix handling of the `BIND` environment variable in the streaming server (#31624 by @ThisIsMissEm)
- Fix empty `aria-hidden` attribute value in logo resources area (#30570 by @mjankowski)
- Fix “Redirect URI” field not being marked as required in “New application” form (#30311 by @ThisIsMissEm)
- Fix right-to-left text in preview cards (#30930 by @ClearlyClaire)

View file

@ -47,7 +47,6 @@ gem 'color_diff', '~> 0.1'
gem 'csv', '~> 3.2'
gem 'discard', '~> 1.2'
gem 'doorkeeper', '~> 5.6'
gem 'ed25519', '~> 1.3'
gem 'fast_blank', '~> 1.0'
gem 'fastimage'
gem 'hiredis', '~> 0.6'
@ -111,7 +110,7 @@ group :opentelemetry do
gem 'opentelemetry-instrumentation-http', '~> 0.23.2', require: false
gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false
gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false
gem 'opentelemetry-instrumentation-pg', '~> 0.28.0', require: false
gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false
gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false
gem 'opentelemetry-instrumentation-rails', '~> 0.31.0', require: false
gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false

View file

@ -100,20 +100,20 @@ GEM
attr_required (1.0.2)
awrence (1.2.1)
aws-eventstream (1.3.0)
aws-partitions (1.974.0)
aws-sdk-core (3.205.0)
aws-partitions (1.978.0)
aws-sdk-core (3.209.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.91.0)
aws-sdk-core (~> 3, >= 3.205.0)
aws-sdk-kms (1.94.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.162.0)
aws-sdk-core (~> 3, >= 3.205.0)
aws-sdk-s3 (1.166.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.9.1)
aws-sigv4 (1.10.0)
aws-eventstream (~> 1, >= 1.0.2)
azure-storage-blob (2.0.3)
azure-storage-common (~> 2.0)
@ -197,7 +197,7 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise-two-factor (5.1.0)
devise-two-factor (6.0.0)
activesupport (~> 7.0)
devise (~> 4.0)
railties (~> 7.0)
@ -212,9 +212,8 @@ GEM
domain_name (0.6.20240107)
doorkeeper (5.7.1)
railties (>= 5)
dotenv (3.1.2)
dotenv (3.1.4)
drb (2.2.1)
ed25519 (1.3.0)
elasticsearch (7.17.11)
elasticsearch-api (= 7.17.11)
elasticsearch-transport (= 7.17.11)
@ -290,7 +289,7 @@ GEM
raabro (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
google-protobuf (3.25.4)
google-protobuf (3.25.5)
googleapis-common-protos-types (1.15.0)
google-protobuf (>= 3.18, < 5.a)
haml (6.3.0)
@ -331,7 +330,7 @@ GEM
httplog (1.7.0)
rack (>= 2.0)
rainbow (>= 2.0.0)
i18n (1.14.5)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
i18n-tasks (1.0.14)
activesupport (>= 4.0.2)
@ -407,7 +406,7 @@ GEM
llhttp-ffi (0.5.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
logger (1.6.0)
logger (1.6.1)
lograge (0.14.0)
actionpack (>= 4)
activesupport (>= 4)
@ -429,7 +428,7 @@ GEM
addressable (~> 2.5)
azure-storage-blob (~> 2.0.1)
hashie (~> 5.0)
memory_profiler (1.0.2)
memory_profiler (1.1.0)
mime-types (3.5.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2024.0820)
@ -472,9 +471,9 @@ GEM
omniauth-rails_csrf_protection (1.0.2)
actionpack (>= 4.2)
omniauth (~> 2.0)
omniauth-saml (2.1.0)
omniauth (~> 2.0)
ruby-saml (~> 1.12)
omniauth-saml (2.2.1)
omniauth (~> 2.1)
ruby-saml (~> 1.17)
omniauth_openid_connect (0.6.1)
omniauth (>= 1.9, < 3)
openid_connect (~> 1.1)
@ -502,8 +501,8 @@ GEM
opentelemetry-common (~> 0.20)
opentelemetry-sdk (~> 1.2)
opentelemetry-semantic_conventions
opentelemetry-helpers-sql-obfuscation (0.1.0)
opentelemetry-common (~> 0.20)
opentelemetry-helpers-sql-obfuscation (0.2.0)
opentelemetry-common (~> 0.21)
opentelemetry-instrumentation-action_mailer (0.1.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.1)
@ -528,8 +527,9 @@ GEM
opentelemetry-instrumentation-active_support (0.6.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-base (0.22.3)
opentelemetry-instrumentation-base (0.22.6)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.21)
opentelemetry-registry (~> 0.1)
opentelemetry-instrumentation-concurrent_ruby (0.21.4)
opentelemetry-api (~> 1.0)
@ -549,7 +549,7 @@ GEM
opentelemetry-instrumentation-net_http (0.22.7)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-pg (0.28.0)
opentelemetry-instrumentation-pg (0.29.0)
opentelemetry-api (~> 1.0)
opentelemetry-helpers-sql-obfuscation
opentelemetry-instrumentation-base (~> 0.22.1)
@ -609,7 +609,7 @@ GEM
psych (5.1.2)
stringio
public_suffix (6.0.1)
puma (6.4.2)
puma (6.4.3)
nio4r (~> 2.0)
pundit (2.4.0)
activesupport (>= 3.0.0)
@ -763,7 +763,7 @@ GEM
rubocop-rspec (~> 3, >= 3.0.1)
ruby-prof (1.7.0)
ruby-progressbar (1.13.0)
ruby-saml (1.16.0)
ruby-saml (1.17.0)
nokogiri (>= 1.13.10)
rexml
ruby-vips (2.2.2)
@ -781,7 +781,7 @@ GEM
scenic (1.8.0)
activerecord (>= 4.0.0)
railties (>= 4.0.0)
selenium-webdriver (4.24.0)
selenium-webdriver (4.25.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@ -893,7 +893,7 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.8.1)
webrick (1.8.2)
websocket (1.2.11)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
@ -936,7 +936,6 @@ DEPENDENCIES
discard (~> 1.2)
doorkeeper (~> 5.6)
dotenv
ed25519 (~> 1.3)
email_spec
fabrication (~> 2.30)
faker (~> 3.2)
@ -991,7 +990,7 @@ DEPENDENCIES
opentelemetry-instrumentation-http (~> 0.23.2)
opentelemetry-instrumentation-http_client (~> 0.22.3)
opentelemetry-instrumentation-net_http (~> 0.22.4)
opentelemetry-instrumentation-pg (~> 0.28.0)
opentelemetry-instrumentation-pg (~> 0.29.0)
opentelemetry-instrumentation-rack (~> 0.24.1)
opentelemetry-instrumentation-rails (~> 0.31.0)
opentelemetry-instrumentation-redis (~> 0.25.3)

View file

@ -1,18 +0,0 @@
# frozen_string_literal: true
class ActivityPub::ClaimsController < ActivityPub::BaseController
skip_before_action :authenticate_user!
before_action :require_account_signature!
before_action :set_claim_result
def create
render json: @claim_result, serializer: ActivityPub::OneTimeKeySerializer
end
private
def set_claim_result
@claim_result = ::Keys::ClaimService.new.call(@account.id, params[:id])
end
end

View file

@ -22,8 +22,6 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
@items = @items.map { |item| item.distributable? ? item : ActivityPub::TagManager.instance.uri_for(item) }
when 'tags'
@items = for_signed_account { @account.featured_tags }
when 'devices'
@items = @account.devices
else
not_found
end
@ -31,7 +29,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
def set_size
case params[:id]
when 'featured', 'devices', 'tags'
when 'featured', 'tags'
@size = @items.size
else
not_found
@ -42,7 +40,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
case params[:id]
when 'featured'
@type = :ordered
when 'devices', 'tags'
when 'tags'
@type = :unordered
else
not_found

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
class ActivityPub::LikesController < ActivityPub::BaseController
include Authorization
vary_by -> { 'Signature' if authorized_fetch_mode? }
before_action :require_account_signature!, if: :authorized_fetch_mode?
before_action :set_status
def index
expires_in 0, public: @status.distributable? && public_fetch_mode?
render json: likes_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
end
private
def pundit_user
signed_request_account
end
def set_status
@status = @account.statuses.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def likes_collection_presenter
ActivityPub::CollectionPresenter.new(
id: account_status_likes_url(@account, @status),
type: :unordered,
size: @status.favourites_count
)
end
end

View file

@ -12,7 +12,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
before_action :set_replies
def index
expires_in 0, public: public_fetch_mode?
expires_in 0, public: @status.distributable? && public_fetch_mode?
render json: replies_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json', skip_activities: true
end

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
class ActivityPub::SharesController < ActivityPub::BaseController
include Authorization
vary_by -> { 'Signature' if authorized_fetch_mode? }
before_action :require_account_signature!, if: :authorized_fetch_mode?
before_action :set_status
def index
expires_in 0, public: @status.distributable? && public_fetch_mode?
render json: shares_collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
end
private
def pundit_user
signed_request_account
end
def set_status
@status = @account.statuses.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def shares_collection_presenter
ActivityPub::CollectionPresenter.new(
id: account_status_shares_url(@account, @status),
type: :unordered,
size: @status.reblogs_count
)
end
end

View file

@ -7,7 +7,7 @@ class Api::OEmbedController < Api::BaseController
before_action :require_public_status!
def show
render json: @status, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
render json: @status, serializer: OEmbedSerializer, width: params[:maxwidth], height: params[:maxheight]
end
private
@ -23,12 +23,4 @@ class Api::OEmbedController < Api::BaseController
def status_finder
StatusFinder.new(params[:url])
end
def maxwidth_or_default
(params[:maxwidth].presence || 400).to_i
end
def maxheight_or_default
params[:maxheight].present? ? params[:maxheight].to_i : nil
end
end

View file

@ -1,30 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::DeliveriesController < Api::BaseController
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
before_action :set_current_device
def create
devices.each do |device_params|
DeliverToDeviceService.new.call(current_account, @current_device, device_params)
end
render_empty
end
private
def set_current_device
@current_device = Device.find_by!(access_token: doorkeeper_token)
end
def resource_params
params.require(:device)
params.permit(device: [:account_id, :device_id, :type, :body, :hmac])
end
def devices
Array(resource_params[:device])
end
end

View file

@ -1,47 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
LIMIT = 80
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
before_action :set_current_device
before_action :set_encrypted_messages, only: :index
after_action :insert_pagination_headers, only: :index
def index
render json: @encrypted_messages, each_serializer: REST::EncryptedMessageSerializer
end
def clear
@current_device.encrypted_messages.up_to(params[:up_to_id]).delete_all
render_empty
end
private
def set_current_device
@current_device = Device.find_by!(access_token: doorkeeper_token)
end
def set_encrypted_messages
@encrypted_messages = @current_device.encrypted_messages.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def next_path
api_v1_crypto_encrypted_messages_url pagination_params(max_id: pagination_max_id) if records_continue?
end
def prev_path
api_v1_crypto_encrypted_messages_url pagination_params(min_id: pagination_since_id) unless @encrypted_messages.empty?
end
def pagination_collection
@encrypted_messages
end
def records_continue?
@encrypted_messages.size == limit_param(LIMIT)
end
end

View file

@ -1,25 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
before_action :set_claim_results
def create
render json: @claim_results, each_serializer: REST::Keys::ClaimResultSerializer
end
private
def set_claim_results
@claim_results = devices.filter_map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }
end
def resource_params
params.permit(device: [:account_id, :device_id])
end
def devices
Array(resource_params[:device])
end
end

View file

@ -1,17 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::Keys::CountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
before_action :set_current_device
def show
render json: { one_time_keys: @current_device.one_time_keys.count }
end
private
def set_current_device
@current_device = Device.find_by!(access_token: doorkeeper_token)
end
end

View file

@ -1,26 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::Keys::QueriesController < Api::BaseController
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
before_action :set_accounts
before_action :set_query_results
def create
render json: @query_results, each_serializer: REST::Keys::QueryResultSerializer
end
private
def set_accounts
@accounts = Account.where(id: account_ids).includes(:devices)
end
def set_query_results
@query_results = @accounts.filter_map { |account| ::Keys::QueryService.new.call(account) }
end
def account_ids
Array(params[:id]).map(&:to_i)
end
end

View file

@ -1,29 +0,0 @@
# frozen_string_literal: true
class Api::V1::Crypto::Keys::UploadsController < Api::BaseController
before_action -> { doorkeeper_authorize! :crypto }
before_action :require_user!
def create
device = Device.find_or_initialize_by(access_token: doorkeeper_token)
device.transaction do
device.account = current_account
device.update!(resource_params[:device])
if resource_params[:one_time_keys].present? && resource_params[:one_time_keys].is_a?(Enumerable)
resource_params[:one_time_keys].each do |one_time_key_params|
device.one_time_keys.create!(one_time_key_params)
end
end
end
render json: device, serializer: REST::Keys::DeviceSerializer
end
private
def resource_params
params.permit(device: [:device_id, :name, :fingerprint_key, :identity_key], one_time_keys: [:key_id, :key, :signature])
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
class Api::V1::DomainBlocks::PreviewsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :write, :'write:blocks' }
before_action :require_user!
before_action :set_domain
before_action :set_domain_block_preview
def show
render json: @domain_block_preview, serializer: REST::DomainBlockPreviewSerializer
end
private
def set_domain
@domain = TagManager.instance.normalize_domain(params[:domain])
end
def set_domain_block_preview
@domain_block_preview = with_read_replica do
DomainBlockPreviewPresenter.new(
following_count: current_account.following.where(domain: @domain).count,
followers_count: current_account.followers.where(domain: @domain).count
)
end
end
end

View file

@ -7,6 +7,8 @@ class Api::V1::Peers::SearchController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode?
skip_around_action :set_locale
LIMIT = 10
vary_by ''
def index
@ -35,10 +37,10 @@ class Api::V1::Peers::SearchController < Api::BaseController
field: 'accounts_count',
modifier: 'log2p',
},
}).limit(10).pluck(:domain)
}).limit(LIMIT).pluck(:domain)
else
domain = normalized_domain
@domains = Instance.searchable.domain_starts_with(domain).limit(10).pluck(:domain)
@domains = Instance.searchable.domain_starts_with(domain).limit(LIMIT).pluck(:domain)
end
rescue Addressable::URI::InvalidURIError
@domains = []

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V2Alpha::Notifications::AccountsController < Api::BaseController
class Api::V2::Notifications::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }
before_action :require_user!
before_action :set_notifications!
@ -33,11 +33,11 @@ class Api::V2Alpha::Notifications::AccountsController < Api::BaseController
end
def next_path
api_v2_alpha_notification_accounts_url pagination_params(max_id: pagination_max_id) if records_continue?
api_v2_notification_accounts_url pagination_params(max_id: pagination_max_id) if records_continue?
end
def prev_path
api_v2_alpha_notification_accounts_url pagination_params(min_id: pagination_since_id) unless @paginated_notifications.empty?
api_v2_notification_accounts_url pagination_params(min_id: pagination_since_id) unless @paginated_notifications.empty?
end
def pagination_collection

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V2Alpha::NotificationsController < Api::BaseController
class Api::V2::NotificationsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :dismiss]
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :dismiss]
before_action :require_user!
@ -21,7 +21,7 @@ class Api::V2Alpha::NotificationsController < Api::BaseController
ActiveRecord::Associations::Preloader.new(records: @presenter.accounts, associations: [:account_stat, { user: :role }]).call
end
MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#index rendering') do |span|
MastodonOTELTracer.in_span('Api::V2::NotificationsController#index rendering') do |span|
statuses = @grouped_notifications.filter_map { |group| group.target_status&.id }
span.add_attributes(
@ -64,7 +64,7 @@ class Api::V2Alpha::NotificationsController < Api::BaseController
private
def load_notifications
MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_notifications') do
MastodonOTELTracer.in_span('Api::V2::NotificationsController#load_notifications') do
notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_grouped_paginated_by_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params.slice(:max_id, :since_id, :min_id, :grouped_types).permit(:max_id, :since_id, :min_id, grouped_types: [])
@ -79,7 +79,7 @@ class Api::V2Alpha::NotificationsController < Api::BaseController
def load_grouped_notifications
return [] if @notifications.empty?
MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_grouped_notifications') do
MastodonOTELTracer.in_span('Api::V2::NotificationsController#load_grouped_notifications') do
NotificationGroup.from_notifications(@notifications, pagination_range: (@notifications.last.id)..(@notifications.first.id), grouped_types: params[:grouped_types])
end
end
@ -101,11 +101,11 @@ class Api::V2Alpha::NotificationsController < Api::BaseController
end
def next_path
api_v2_alpha_notifications_url pagination_params(max_id: pagination_max_id) unless @notifications.empty?
api_v2_notifications_url pagination_params(max_id: pagination_max_id) unless @notifications.empty?
end
def prev_path
api_v2_alpha_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty?
api_v2_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty?
end
def pagination_collection

View file

@ -9,7 +9,7 @@ class Api::Web::EmbedsController < Api::Web::BaseController
return not_found if @status.hidden?
if @status.local?
render json: @status, serializer: OEmbedSerializer, width: 400
render json: @status, serializer: OEmbedSerializer
else
return not_found unless user_signed_in?

View file

@ -20,11 +20,6 @@ class Auth::SessionsController < Devise::SessionsController
p.form_action(false)
end
def check_suspicious!
user = find_user
@login_is_suspicious = suspicious_sign_in?(user) unless user.nil?
end
def create
super do |resource|
# We only need to call this if this hasn't already been
@ -101,6 +96,11 @@ class Auth::SessionsController < Devise::SessionsController
private
def check_suspicious!
user = find_user
@login_is_suspicious = suspicious_sign_in?(user) unless user.nil?
end
def home_paths(resource)
paths = [about_path, '/explore']

View file

@ -31,7 +31,7 @@ module WebAppControllerConcern
def redirect_unauthenticated_to_permalinks!
return if user_signed_in? && current_account.moved_to_account_id.nil?
permalink_redirector = PermalinkRedirector.new(request.path)
permalink_redirector = PermalinkRedirector.new(request.original_fullpath)
return if permalink_redirector.redirect_path.blank?
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?

View file

@ -23,23 +23,6 @@ module ContextHelper
indexable: { 'toot' => 'http://joinmastodon.org/ns#', 'indexable' => 'toot:indexable' },
memorial: { 'toot' => 'http://joinmastodon.org/ns#', 'memorial' => 'toot:memorial' },
voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' },
olm: {
'toot' => 'http://joinmastodon.org/ns#',
'Device' => 'toot:Device',
'Ed25519Signature' => 'toot:Ed25519Signature',
'Ed25519Key' => 'toot:Ed25519Key',
'Curve25519Key' => 'toot:Curve25519Key',
'EncryptedMessage' => 'toot:EncryptedMessage',
'publicKeyBase64' => 'toot:publicKeyBase64',
'deviceId' => 'toot:deviceId',
'claim' => { '@type' => '@id', '@id' => 'toot:claim' },
'fingerprintKey' => { '@type' => '@id', '@id' => 'toot:fingerprintKey' },
'identityKey' => { '@type' => '@id', '@id' => 'toot:identityKey' },
'devices' => { '@type' => '@id', '@id' => 'toot:devices' },
'messageFranking' => 'toot:messageFranking',
'messageType' => 'toot:messageType',
'cipherText' => 'toot:cipherText',
},
suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' },
attribution_domains: { 'toot' => 'http://joinmastodon.org/ns#', 'attributionDomains' => { '@id' => 'toot:attributionDomains', '@type' => '@id' } },
}.freeze

View file

@ -0,0 +1,31 @@
import { useMemo, useCallback } from 'react';
import { useLocation, useHistory } from 'react-router';
export function useSearchParams() {
const { search } = useLocation();
return useMemo(() => new URLSearchParams(search), [search]);
}
export function useSearchParam(name: string, defaultValue?: string) {
const searchParams = useSearchParams();
const history = useHistory();
const value = searchParams.get(name) ?? defaultValue;
const setValue = useCallback(
(value: string | null) => {
if (value === null) {
searchParams.delete(name);
} else {
searchParams.set(name, value);
}
history.push({ search: searchParams.toString() });
},
[history, name, searchParams],
);
return [value, setValue] as const;
}

View file

@ -1,4 +1,5 @@
import { browserHistory } from 'mastodon/components/router';
import { debounceWithDispatchAndArguments } from 'mastodon/utils/debounce';
import api, { getLinks } from '../api';
@ -449,6 +450,20 @@ export function expandFollowingFail(id, error) {
};
}
const debouncedFetchRelationships = debounceWithDispatchAndArguments((dispatch, ...newAccountIds) => {
if (newAccountIds.length === 0) {
return;
}
dispatch(fetchRelationshipsRequest(newAccountIds));
api().get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
dispatch(fetchRelationshipsSuccess({ relationships: response.data }));
}).catch(error => {
dispatch(fetchRelationshipsFail(error));
});
}, { delay: 500 });
export function fetchRelationships(accountIds) {
return (dispatch, getState) => {
const state = getState();
@ -460,13 +475,7 @@ export function fetchRelationships(accountIds) {
return;
}
dispatch(fetchRelationshipsRequest(newAccountIds));
api().get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
dispatch(fetchRelationshipsSuccess({ relationships: response.data }));
}).catch(error => {
dispatch(fetchRelationshipsFail(error));
});
debouncedFetchRelationships(dispatch, ...newAccountIds);
};
}

View file

@ -1,5 +1,7 @@
import { defineMessages } from 'react-intl';
import { AxiosError } from 'axios';
const messages = defineMessages({
unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
@ -50,6 +52,11 @@ export const showAlertForError = (error, skipNotFound = false) => {
});
}
// An aborted request, e.g. due to reloading the browser window, it not really error
if (error.code === AxiosError.ECONNABORTED) {
return { type: ALERT_NOOP };
}
console.error(error);
return showAlert({

View file

@ -2,7 +2,6 @@ import { debounce } from 'lodash';
import type { MarkerJSON } from 'mastodon/api_types/markers';
import { getAccessToken } from 'mastodon/initial_state';
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import type { AppDispatch, RootState } from 'mastodon/store';
import { createAppAsyncThunk } from 'mastodon/store/typed_functions';
@ -76,12 +75,7 @@ interface MarkerParam {
}
function getLastNotificationId(state: RootState): string | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return selectUseGroupedNotifications(state)
? state.notificationGroups.lastReadId
: // @ts-expect-error state.notifications is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
state.getIn(['notifications', 'lastReadId']);
return state.notificationGroups.lastReadId;
}
const buildPostMarkersParams = (state: RootState) => {

View file

@ -2,7 +2,7 @@ import { createAction } from '@reduxjs/toolkit';
import {
apiClearNotifications,
apiFetchNotifications,
apiFetchNotificationGroups,
} from 'mastodon/api/notifications';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
import type {
@ -68,10 +68,15 @@ function dispatchAssociatedRecords(
dispatch(importFetchedStatuses(fetchedStatuses));
}
const supportedGroupedNotificationTypes = ['favourite', 'reblog'];
export const fetchNotifications = createDataLoadingThunk(
'notificationGroups/fetch',
async (_params, { getState }) =>
apiFetchNotifications({ exclude_types: getExcludedTypes(getState()) }),
apiFetchNotificationGroups({
grouped_types: supportedGroupedNotificationTypes,
exclude_types: getExcludedTypes(getState()),
}),
({ notifications, accounts, statuses }, { dispatch }) => {
dispatch(importFetchedAccounts(accounts));
dispatch(importFetchedStatuses(statuses));
@ -92,7 +97,8 @@ export const fetchNotifications = createDataLoadingThunk(
export const fetchNotificationsGap = createDataLoadingThunk(
'notificationGroups/fetchGap',
async (params: { gap: NotificationGap }, { getState }) =>
apiFetchNotifications({
apiFetchNotificationGroups({
grouped_types: supportedGroupedNotificationTypes,
max_id: params.gap.maxId,
exclude_types: getExcludedTypes(getState()),
}),
@ -108,7 +114,8 @@ export const fetchNotificationsGap = createDataLoadingThunk(
export const pollRecentNotifications = createDataLoadingThunk(
'notificationGroups/pollRecentNotifications',
async (_params, { getState }) => {
return apiFetchNotifications({
return apiFetchNotificationGroups({
grouped_types: supportedGroupedNotificationTypes,
max_id: undefined,
exclude_types: getExcludedTypes(getState()),
// In slow mode, we don't want to include notifications that duplicate the already-displayed ones

View file

@ -17,6 +17,6 @@ export const updateNotificationsPolicy = createDataLoadingThunk(
(policy: Partial<NotificationPolicy>) => apiUpdateNotificationsPolicy(policy),
);
export const decreasePendingNotificationsCount = createAction<number>(
'notificationPolicy/decreasePendingNotificationCount',
export const decreasePendingRequestsCount = createAction<number>(
'notificationPolicy/decreasePendingRequestsCount',
);

View file

@ -0,0 +1,214 @@
import {
apiFetchNotificationRequest,
apiFetchNotificationRequests,
apiFetchNotifications,
apiAcceptNotificationRequest,
apiDismissNotificationRequest,
apiAcceptNotificationRequests,
apiDismissNotificationRequests,
} from 'mastodon/api/notifications';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
import type {
ApiNotificationGroupJSON,
ApiNotificationJSON,
} from 'mastodon/api_types/notifications';
import type { ApiStatusJSON } from 'mastodon/api_types/statuses';
import type { AppDispatch } from 'mastodon/store';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
import { importFetchedAccounts, importFetchedStatuses } from './importer';
import { decreasePendingRequestsCount } from './notification_policies';
// TODO: refactor with notification_groups
function dispatchAssociatedRecords(
dispatch: AppDispatch,
notifications: ApiNotificationGroupJSON[] | ApiNotificationJSON[],
) {
const fetchedAccounts: ApiAccountJSON[] = [];
const fetchedStatuses: ApiStatusJSON[] = [];
notifications.forEach((notification) => {
if (notification.type === 'admin.report') {
fetchedAccounts.push(notification.report.target_account);
}
if (notification.type === 'moderation_warning') {
fetchedAccounts.push(notification.moderation_warning.target_account);
}
if ('status' in notification && notification.status) {
fetchedStatuses.push(notification.status);
}
});
if (fetchedAccounts.length > 0)
dispatch(importFetchedAccounts(fetchedAccounts));
if (fetchedStatuses.length > 0)
dispatch(importFetchedStatuses(fetchedStatuses));
}
export const fetchNotificationRequests = createDataLoadingThunk(
'notificationRequests/fetch',
async (_params, { getState }) => {
let sinceId = undefined;
if (getState().notificationRequests.items.length > 0) {
sinceId = getState().notificationRequests.items[0]?.id;
}
return apiFetchNotificationRequests({
since_id: sinceId,
});
},
({ requests, links }, { dispatch }) => {
const next = links.refs.find((link) => link.rel === 'next');
dispatch(importFetchedAccounts(requests.map((request) => request.account)));
return { requests, next: next?.uri };
},
{
condition: (_params, { getState }) =>
!getState().notificationRequests.isLoading,
},
);
export const fetchNotificationRequest = createDataLoadingThunk(
'notificationRequest/fetch',
async ({ id }: { id: string }) => apiFetchNotificationRequest(id),
{
condition: ({ id }, { getState }) =>
!(
getState().notificationRequests.current.item?.id === id ||
getState().notificationRequests.current.isLoading
),
},
);
export const expandNotificationRequests = createDataLoadingThunk(
'notificationRequests/expand',
async (_, { getState }) => {
const nextUrl = getState().notificationRequests.next;
if (!nextUrl) throw new Error('missing URL');
return apiFetchNotificationRequests(undefined, nextUrl);
},
({ requests, links }, { dispatch }) => {
const next = links.refs.find((link) => link.rel === 'next');
dispatch(importFetchedAccounts(requests.map((request) => request.account)));
return { requests, next: next?.uri };
},
{
condition: (_, { getState }) =>
!!getState().notificationRequests.next &&
!getState().notificationRequests.isLoading,
},
);
export const fetchNotificationsForRequest = createDataLoadingThunk(
'notificationRequest/fetchNotifications',
async ({ accountId }: { accountId: string }, { getState }) => {
const sinceId =
// @ts-expect-error current.notifications.items is not yet typed
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
getState().notificationRequests.current.notifications.items[0]?.get(
'id',
) as string | undefined;
return apiFetchNotifications({
since_id: sinceId,
account_id: accountId,
});
},
({ notifications, links }, { dispatch }) => {
const next = links.refs.find((link) => link.rel === 'next');
dispatchAssociatedRecords(dispatch, notifications);
return { notifications, next: next?.uri };
},
{
condition: ({ accountId }, { getState }) => {
const current = getState().notificationRequests.current;
return !(
current.item?.account_id === accountId &&
current.notifications.isLoading
);
},
},
);
export const expandNotificationsForRequest = createDataLoadingThunk(
'notificationRequest/expandNotifications',
async (_, { getState }) => {
const nextUrl = getState().notificationRequests.current.notifications.next;
if (!nextUrl) throw new Error('missing URL');
return apiFetchNotifications(undefined, nextUrl);
},
({ notifications, links }, { dispatch }) => {
const next = links.refs.find((link) => link.rel === 'next');
dispatchAssociatedRecords(dispatch, notifications);
return { notifications, next: next?.uri };
},
{
condition: ({ accountId }: { accountId: string }, { getState }) => {
const url = getState().notificationRequests.current.notifications.next;
return (
!!url &&
!getState().notificationRequests.current.notifications.isLoading &&
getState().notificationRequests.current.item?.account_id === accountId
);
},
},
);
export const acceptNotificationRequest = createDataLoadingThunk(
'notificationRequest/accept',
({ id }: { id: string }) => apiAcceptNotificationRequest(id),
(_data, { dispatch, discardLoadData }) => {
dispatch(decreasePendingRequestsCount(1));
// The payload is not used in any functions
return discardLoadData;
},
);
export const dismissNotificationRequest = createDataLoadingThunk(
'notificationRequest/dismiss',
({ id }: { id: string }) => apiDismissNotificationRequest(id),
(_data, { dispatch, discardLoadData }) => {
dispatch(decreasePendingRequestsCount(1));
// The payload is not used in any functions
return discardLoadData;
},
);
export const acceptNotificationRequests = createDataLoadingThunk(
'notificationRequests/acceptBulk',
({ ids }: { ids: string[] }) => apiAcceptNotificationRequests(ids),
(_data, { dispatch, discardLoadData, actionArg: { ids } }) => {
dispatch(decreasePendingRequestsCount(ids.length));
// The payload is not used in any functions
return discardLoadData;
},
);
export const dismissNotificationRequests = createDataLoadingThunk(
'notificationRequests/dismissBulk',
({ ids }: { ids: string[] }) => apiDismissNotificationRequests(ids),
(_data, { dispatch, discardLoadData, actionArg: { ids } }) => {
dispatch(decreasePendingRequestsCount(ids.length));
// The payload is not used in any functions
return discardLoadData;
},
);

View file

@ -10,7 +10,7 @@ import api, { getLinks } from '../api';
import { unescapeHTML } from '../utils/html';
import { requestNotificationPermission } from '../utils/notifications';
import { fetchFollowRequests, fetchRelationships } from './accounts';
import { fetchFollowRequests } from './accounts';
import {
importFetchedAccount,
importFetchedAccounts,
@ -18,7 +18,6 @@ import {
importFetchedStatuses,
} from './importer';
import { submitMarkers } from './markers';
import { decreasePendingNotificationsCount } from './notification_policies';
import { notificationsUpdate } from "./notifications_typed";
import { register as registerPushNotifications } from './push_notifications';
import { saveSettings } from './settings';
@ -44,26 +43,6 @@ export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ';
export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const NOTIFICATIONS_SET_BROWSER_PERMISSION = 'NOTIFICATIONS_SET_BROWSER_PERMISSION';
export const NOTIFICATION_REQUESTS_FETCH_REQUEST = 'NOTIFICATION_REQUESTS_FETCH_REQUEST';
export const NOTIFICATION_REQUESTS_FETCH_SUCCESS = 'NOTIFICATION_REQUESTS_FETCH_SUCCESS';
export const NOTIFICATION_REQUESTS_FETCH_FAIL = 'NOTIFICATION_REQUESTS_FETCH_FAIL';
export const NOTIFICATION_REQUESTS_EXPAND_REQUEST = 'NOTIFICATION_REQUESTS_EXPAND_REQUEST';
export const NOTIFICATION_REQUESTS_EXPAND_SUCCESS = 'NOTIFICATION_REQUESTS_EXPAND_SUCCESS';
export const NOTIFICATION_REQUESTS_EXPAND_FAIL = 'NOTIFICATION_REQUESTS_EXPAND_FAIL';
export const NOTIFICATION_REQUEST_FETCH_REQUEST = 'NOTIFICATION_REQUEST_FETCH_REQUEST';
export const NOTIFICATION_REQUEST_FETCH_SUCCESS = 'NOTIFICATION_REQUEST_FETCH_SUCCESS';
export const NOTIFICATION_REQUEST_FETCH_FAIL = 'NOTIFICATION_REQUEST_FETCH_FAIL';
export const NOTIFICATION_REQUEST_ACCEPT_REQUEST = 'NOTIFICATION_REQUEST_ACCEPT_REQUEST';
export const NOTIFICATION_REQUEST_ACCEPT_SUCCESS = 'NOTIFICATION_REQUEST_ACCEPT_SUCCESS';
export const NOTIFICATION_REQUEST_ACCEPT_FAIL = 'NOTIFICATION_REQUEST_ACCEPT_FAIL';
export const NOTIFICATION_REQUEST_DISMISS_REQUEST = 'NOTIFICATION_REQUEST_DISMISS_REQUEST';
export const NOTIFICATION_REQUEST_DISMISS_SUCCESS = 'NOTIFICATION_REQUEST_DISMISS_SUCCESS';
export const NOTIFICATION_REQUEST_DISMISS_FAIL = 'NOTIFICATION_REQUEST_DISMISS_FAIL';
export const NOTIFICATION_REQUESTS_ACCEPT_REQUEST = 'NOTIFICATION_REQUESTS_ACCEPT_REQUEST';
export const NOTIFICATION_REQUESTS_ACCEPT_SUCCESS = 'NOTIFICATION_REQUESTS_ACCEPT_SUCCESS';
export const NOTIFICATION_REQUESTS_ACCEPT_FAIL = 'NOTIFICATION_REQUESTS_ACCEPT_FAIL';
@ -72,33 +51,11 @@ export const NOTIFICATION_REQUESTS_DISMISS_REQUEST = 'NOTIFICATION_REQUESTS_DISM
export const NOTIFICATION_REQUESTS_DISMISS_SUCCESS = 'NOTIFICATION_REQUESTS_DISMISS_SUCCESS';
export const NOTIFICATION_REQUESTS_DISMISS_FAIL = 'NOTIFICATION_REQUESTS_DISMISS_FAIL';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST = 'NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS = 'NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS';
export const NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL = 'NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS';
export const NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL = 'NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL';
defineMessages({
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
group: { id: 'notifications.group', defaultMessage: '{count} notifications' },
});
const fetchRelatedRelationships = (dispatch, notifications) => {
const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id);
if (accountIds.length > 0) {
dispatch(fetchRelationships(accountIds));
}
};
const selectNotificationCountForRequest = (state, id) => {
const requests = state.getIn(['notificationRequests', 'items']);
const thisRequest = requests.find(request => request.get('id') === id);
return thisRequest ? thisRequest.get('notifications_count') : 0;
};
export const loadPending = () => ({
type: NOTIFICATIONS_LOAD_PENDING,
});
@ -141,8 +98,6 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
dispatch(notificationsUpdate({ notification, preferPendingItems, playSound: playSound && !filtered}));
fetchRelatedRelationships(dispatch, [notification]);
} else if (playSound && !filtered) {
dispatch({
type: NOTIFICATIONS_UPDATE_NOOP,
@ -234,7 +189,6 @@ export function expandNotifications({ maxId = undefined, forceLoad = false }) {
dispatch(importFetchedAccounts(response.data.filter(item => item.report).map(item => item.report.target_account)));
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems));
fetchRelatedRelationships(dispatch, response.data);
dispatch(submitMarkers());
} catch(error) {
dispatch(expandNotificationsFail(error, isLoadingMore));
@ -343,296 +297,3 @@ export function setBrowserPermission (value) {
value,
};
}
export const fetchNotificationRequests = () => (dispatch, getState) => {
const params = {};
if (getState().getIn(['notificationRequests', 'isLoading'])) {
return;
}
if (getState().getIn(['notificationRequests', 'items'])?.size > 0) {
params.since_id = getState().getIn(['notificationRequests', 'items', 0, 'id']);
}
dispatch(fetchNotificationRequestsRequest());
api().get('/api/v1/notifications/requests', { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchNotificationRequestsSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(fetchNotificationRequestsFail(err));
});
};
export const fetchNotificationRequestsRequest = () => ({
type: NOTIFICATION_REQUESTS_FETCH_REQUEST,
});
export const fetchNotificationRequestsSuccess = (requests, next) => ({
type: NOTIFICATION_REQUESTS_FETCH_SUCCESS,
requests,
next,
});
export const fetchNotificationRequestsFail = error => ({
type: NOTIFICATION_REQUESTS_FETCH_FAIL,
error,
});
export const expandNotificationRequests = () => (dispatch, getState) => {
const url = getState().getIn(['notificationRequests', 'next']);
if (!url || getState().getIn(['notificationRequests', 'isLoading'])) {
return;
}
dispatch(expandNotificationRequestsRequest());
api().get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(expandNotificationRequestsSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(expandNotificationRequestsFail(err));
});
};
export const expandNotificationRequestsRequest = () => ({
type: NOTIFICATION_REQUESTS_EXPAND_REQUEST,
});
export const expandNotificationRequestsSuccess = (requests, next) => ({
type: NOTIFICATION_REQUESTS_EXPAND_SUCCESS,
requests,
next,
});
export const expandNotificationRequestsFail = error => ({
type: NOTIFICATION_REQUESTS_EXPAND_FAIL,
error,
});
export const fetchNotificationRequest = id => (dispatch, getState) => {
const current = getState().getIn(['notificationRequests', 'current']);
if (current.getIn(['item', 'id']) === id || current.get('isLoading')) {
return;
}
dispatch(fetchNotificationRequestRequest(id));
api().get(`/api/v1/notifications/requests/${id}`).then(({ data }) => {
dispatch(fetchNotificationRequestSuccess(data));
}).catch(err => {
dispatch(fetchNotificationRequestFail(id, err));
});
};
export const fetchNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_FETCH_REQUEST,
id,
});
export const fetchNotificationRequestSuccess = request => ({
type: NOTIFICATION_REQUEST_FETCH_SUCCESS,
request,
});
export const fetchNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_FETCH_FAIL,
id,
error,
});
export const acceptNotificationRequest = (id) => (dispatch, getState) => {
const count = selectNotificationCountForRequest(getState(), id);
dispatch(acceptNotificationRequestRequest(id));
api().post(`/api/v1/notifications/requests/${id}/accept`).then(() => {
dispatch(acceptNotificationRequestSuccess(id));
dispatch(decreasePendingNotificationsCount(count));
}).catch(err => {
dispatch(acceptNotificationRequestFail(id, err));
});
};
export const acceptNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_ACCEPT_REQUEST,
id,
});
export const acceptNotificationRequestSuccess = id => ({
type: NOTIFICATION_REQUEST_ACCEPT_SUCCESS,
id,
});
export const acceptNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_ACCEPT_FAIL,
id,
error,
});
export const dismissNotificationRequest = (id) => (dispatch, getState) => {
const count = selectNotificationCountForRequest(getState(), id);
dispatch(dismissNotificationRequestRequest(id));
api().post(`/api/v1/notifications/requests/${id}/dismiss`).then(() =>{
dispatch(dismissNotificationRequestSuccess(id));
dispatch(decreasePendingNotificationsCount(count));
}).catch(err => {
dispatch(dismissNotificationRequestFail(id, err));
});
};
export const dismissNotificationRequestRequest = id => ({
type: NOTIFICATION_REQUEST_DISMISS_REQUEST,
id,
});
export const dismissNotificationRequestSuccess = id => ({
type: NOTIFICATION_REQUEST_DISMISS_SUCCESS,
id,
});
export const dismissNotificationRequestFail = (id, error) => ({
type: NOTIFICATION_REQUEST_DISMISS_FAIL,
id,
error,
});
export const acceptNotificationRequests = (ids) => (dispatch, getState) => {
const count = ids.reduce((count, id) => count + selectNotificationCountForRequest(getState(), id), 0);
dispatch(acceptNotificationRequestsRequest(ids));
api().post(`/api/v1/notifications/requests/accept`, { id: ids }).then(() => {
dispatch(acceptNotificationRequestsSuccess(ids));
dispatch(decreasePendingNotificationsCount(count));
}).catch(err => {
dispatch(acceptNotificationRequestFail(ids, err));
});
};
export const acceptNotificationRequestsRequest = ids => ({
type: NOTIFICATION_REQUESTS_ACCEPT_REQUEST,
ids,
});
export const acceptNotificationRequestsSuccess = ids => ({
type: NOTIFICATION_REQUESTS_ACCEPT_SUCCESS,
ids,
});
export const acceptNotificationRequestsFail = (ids, error) => ({
type: NOTIFICATION_REQUESTS_ACCEPT_FAIL,
ids,
error,
});
export const dismissNotificationRequests = (ids) => (dispatch, getState) => {
const count = ids.reduce((count, id) => count + selectNotificationCountForRequest(getState(), id), 0);
dispatch(acceptNotificationRequestsRequest(ids));
api().post(`/api/v1/notifications/requests/dismiss`, { id: ids }).then(() => {
dispatch(dismissNotificationRequestsSuccess(ids));
dispatch(decreasePendingNotificationsCount(count));
}).catch(err => {
dispatch(dismissNotificationRequestFail(ids, err));
});
};
export const dismissNotificationRequestsRequest = ids => ({
type: NOTIFICATION_REQUESTS_DISMISS_REQUEST,
ids,
});
export const dismissNotificationRequestsSuccess = ids => ({
type: NOTIFICATION_REQUESTS_DISMISS_SUCCESS,
ids,
});
export const dismissNotificationRequestsFail = (ids, error) => ({
type: NOTIFICATION_REQUESTS_DISMISS_FAIL,
ids,
error,
});
export const fetchNotificationsForRequest = accountId => (dispatch, getState) => {
const current = getState().getIn(['notificationRequests', 'current']);
const params = { account_id: accountId };
if (current.getIn(['item', 'account']) === accountId) {
if (current.getIn(['notifications', 'isLoading'])) {
return;
}
if (current.getIn(['notifications', 'items'])?.size > 0) {
params.since_id = current.getIn(['notifications', 'items', 0, 'id']);
}
}
dispatch(fetchNotificationsForRequestRequest());
api().get('/api/v1/notifications', { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
dispatch(importFetchedAccounts(response.data.filter(item => item.report).map(item => item.report.target_account)));
dispatch(fetchNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(fetchNotificationsForRequestFail(err));
});
};
export const fetchNotificationsForRequestRequest = () => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_REQUEST,
});
export const fetchNotificationsForRequestSuccess = (notifications, next) => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_SUCCESS,
notifications,
next,
});
export const fetchNotificationsForRequestFail = (error) => ({
type: NOTIFICATIONS_FOR_REQUEST_FETCH_FAIL,
error,
});
export const expandNotificationsForRequest = () => (dispatch, getState) => {
const url = getState().getIn(['notificationRequests', 'current', 'notifications', 'next']);
if (!url || getState().getIn(['notificationRequests', 'current', 'notifications', 'isLoading'])) {
return;
}
dispatch(expandNotificationsForRequestRequest());
api().get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
dispatch(importFetchedAccounts(response.data.filter(item => item.report).map(item => item.report.target_account)));
dispatch(expandNotificationsForRequestSuccess(response.data, next?.uri));
}).catch(err => {
dispatch(expandNotificationsForRequestFail(err));
});
};
export const expandNotificationsForRequestRequest = () => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_REQUEST,
});
export const expandNotificationsForRequestSuccess = (notifications, next) => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_SUCCESS,
notifications,
next,
});
export const expandNotificationsForRequestFail = (error) => ({
type: NOTIFICATIONS_FOR_REQUEST_EXPAND_FAIL,
error,
});

View file

@ -1,14 +1,10 @@
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import { createAppAsyncThunk } from 'mastodon/store';
import { fetchNotifications } from './notification_groups';
import { expandNotifications } from './notifications';
export const initializeNotifications = createAppAsyncThunk(
'notifications/initialize',
(_, { dispatch, getState }) => {
if (selectUseGroupedNotifications(getState()))
void dispatch(fetchNotifications());
else void dispatch(expandNotifications({}));
(_, { dispatch }) => {
void dispatch(fetchNotifications());
},
);

View file

@ -1,7 +1,5 @@
// @ts-check
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import { getLocale } from '../locales';
import { connectStream } from '../stream';
@ -105,18 +103,14 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const notificationJSON = JSON.parse(data.payload);
dispatch(updateNotifications(notificationJSON, messages, locale));
// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
dispatch(processNewNotificationForGroups(notificationJSON));
}
dispatch(processNewNotificationForGroups(notificationJSON));
break;
}
case 'notifications_merged':
const state = getState();
if (state.notifications.top || !state.notifications.mounted)
dispatch(expandNotifications({ forceLoad: true, maxId: undefined }));
if (selectUseGroupedNotifications(state)) {
dispatch(refreshStaleNotificationGroups());
}
dispatch(refreshStaleNotificationGroups());
break;
case 'conversation':
// @ts-expect-error
@ -141,21 +135,15 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
/**
* @param {Function} dispatch
* @param {Function} getState
*/
async function refreshHomeTimelineAndNotification(dispatch, getState) {
async function refreshHomeTimelineAndNotification(dispatch) {
await dispatch(expandHomeTimeline({ maxId: undefined }));
// TODO: remove this once the groups feature replaces the previous one
if(selectUseGroupedNotifications(getState())) {
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}
} else {
await dispatch(expandNotifications({}));
// TODO: polling for merged notifications
try {
await dispatch(pollRecentGroupNotifications());
} catch {
// TODO
}
await dispatch(fetchAnnouncements());

View file

@ -42,6 +42,9 @@ const authorizationTokenFromInitialState = (): RawAxiosRequestHeaders => {
// eslint-disable-next-line import/no-default-export
export default function api(withAuthorization = true) {
return axios.create({
transitional: {
clarifyTimeoutError: true,
},
headers: {
...csrfHeader,
...(withAuthorization ? authorizationTokenFromInitialState() : {}),
@ -67,6 +70,7 @@ export async function apiRequest<ApiResponse = unknown>(
args: {
params?: RequestParamsOrData;
data?: RequestParamsOrData;
timeout?: number;
} = {},
) {
const { data } = await api().request<ApiResponse>({

View file

@ -1,14 +1,44 @@
import api, { apiRequest, getLinks } from 'mastodon/api';
import type { ApiNotificationGroupsResultJSON } from 'mastodon/api_types/notifications';
import api, {
apiRequest,
getLinks,
apiRequestGet,
apiRequestPost,
} from 'mastodon/api';
import type {
ApiNotificationGroupsResultJSON,
ApiNotificationRequestJSON,
ApiNotificationJSON,
} from 'mastodon/api_types/notifications';
export const apiFetchNotifications = async (params?: {
export const apiFetchNotifications = async (
params?: {
account_id?: string;
since_id?: string;
},
url?: string,
) => {
const response = await api().request<ApiNotificationJSON[]>({
method: 'GET',
url: url ?? '/api/v1/notifications',
params,
});
return {
notifications: response.data,
links: getLinks(response),
};
};
export const apiFetchNotificationGroups = async (params?: {
url?: string;
grouped_types?: string[];
exclude_types?: string[];
max_id?: string;
since_id?: string;
}) => {
const response = await api().request<ApiNotificationGroupsResultJSON>({
method: 'GET',
url: '/api/v2_alpha/notifications',
url: '/api/v2/notifications',
params,
});
@ -24,3 +54,43 @@ export const apiFetchNotifications = async (params?: {
export const apiClearNotifications = () =>
apiRequest<undefined>('POST', 'v1/notifications/clear');
export const apiFetchNotificationRequests = async (
params?: {
since_id?: string;
},
url?: string,
) => {
const response = await api().request<ApiNotificationRequestJSON[]>({
method: 'GET',
url: url ?? '/api/v1/notifications/requests',
params,
});
return {
requests: response.data,
links: getLinks(response),
};
};
export const apiFetchNotificationRequest = async (id: string) => {
return apiRequestGet<ApiNotificationRequestJSON>(
`v1/notifications/requests/${id}`,
);
};
export const apiAcceptNotificationRequest = async (id: string) => {
return apiRequestPost(`v1/notifications/requests/${id}/accept`);
};
export const apiDismissNotificationRequest = async (id: string) => {
return apiRequestPost(`v1/notifications/requests/${id}/dismiss`);
};
export const apiAcceptNotificationRequests = async (id: string[]) => {
return apiRequestPost('v1/notifications/requests/accept', { id });
};
export const apiDismissNotificationRequests = async (id: string[]) => {
return apiRequestPost('v1/notifications/requests/dismiss', { id });
};

View file

@ -149,3 +149,12 @@ export interface ApiNotificationGroupsResultJSON {
statuses: ApiStatusJSON[];
notification_groups: ApiNotificationGroupJSON[];
}
export interface ApiNotificationRequestJSON {
id: string;
created_at: string;
updated_at: string;
notifications_count: string;
account: ApiAccountJSON;
last_status?: ApiStatusJSON;
}

View file

@ -7,6 +7,7 @@ interface BaseProps
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
block?: boolean;
secondary?: boolean;
dangerous?: boolean;
}
interface PropsChildren extends PropsWithChildren<BaseProps> {
@ -26,6 +27,7 @@ export const Button: React.FC<Props> = ({
disabled,
block,
secondary,
dangerous,
className,
title,
text,
@ -46,6 +48,7 @@ export const Button: React.FC<Props> = ({
className={classNames('button', className, {
'button-secondary': secondary,
'button--block': block,
'button--dangerous': dangerous,
})}
disabled={disabled}
onClick={handleClick}

View file

@ -75,10 +75,10 @@ export const FollowButton: React.FC<{
label = <LoadingIndicator />;
} else if (relationship.following && relationship.followed_by) {
label = intl.formatMessage(messages.mutual);
} else if (!relationship.following && relationship.followed_by) {
label = intl.formatMessage(messages.followBack);
} else if (relationship.following || relationship.requested) {
label = intl.formatMessage(messages.unfollow);
} else if (relationship.followed_by) {
label = intl.formatMessage(messages.followBack);
} else {
label = intl.formatMessage(messages.follow);
}

View file

@ -148,7 +148,7 @@ class ModalRoot extends PureComponent {
return (
<div className='modal-root' ref={this.setRef}>
<div style={{ pointerEvents: visible ? 'auto' : 'none' }}>
<div role='presentation' className='modal-root__overlay' onClick={onClose} style={{ backgroundColor: backgroundColor ? `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, 0.7)` : null }} />
<div role='presentation' className='modal-root__overlay' onClick={onClose} style={{ backgroundColor: backgroundColor ? `rgba(${backgroundColor.r}, ${backgroundColor.g}, ${backgroundColor.b}, 0.9)` : null }} />
<div role='dialog' className='modal-root__container'>{children}</div>
</div>
</div>

View file

@ -4,22 +4,22 @@ import AccountNavigation from 'mastodon/features/account/navigation';
import Trends from 'mastodon/features/getting_started/containers/trends_container';
import { showTrends } from 'mastodon/initial_state';
const DefaultNavigation: React.FC = () =>
showTrends ? (
<>
<div className='flex-spacer' />
<Trends />
</>
) : null;
const DefaultNavigation: React.FC = () => (showTrends ? <Trends /> : null);
export const NavigationPortal: React.FC = () => (
<Switch>
<Route path='/@:acct' exact component={AccountNavigation} />
<Route path='/@:acct/tagged/:tagged?' exact component={AccountNavigation} />
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
<Route path='/@:acct/followers' exact component={AccountNavigation} />
<Route path='/@:acct/following' exact component={AccountNavigation} />
<Route path='/@:acct/media' exact component={AccountNavigation} />
<Route component={DefaultNavigation} />
</Switch>
<div className='navigation-panel__portal'>
<Switch>
<Route path='/@:acct' exact component={AccountNavigation} />
<Route
path='/@:acct/tagged/:tagged?'
exact
component={AccountNavigation}
/>
<Route path='/@:acct/with_replies' exact component={AccountNavigation} />
<Route path='/@:acct/followers' exact component={AccountNavigation} />
<Route path='/@:acct/following' exact component={AccountNavigation} />
<Route path='/@:acct/media' exact component={AccountNavigation} />
<Route component={DefaultNavigation} />
</Switch>
</div>
);

View file

@ -51,7 +51,8 @@ function normalizePath(
if (
layoutFromWindow() === 'multi-column' &&
!location.pathname?.startsWith('/deck')
location.pathname &&
!location.pathname.startsWith('/deck')
) {
location.pathname = `/deck${location.pathname}`;
}

View file

@ -375,20 +375,29 @@ class StatusActionBar extends ImmutablePureComponent {
return (
<div className='status__action-bar'>
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />
<DropdownMenuContainer
scrollKey={scrollKey}
status={status}
items={menu}
icon='ellipsis-h'
iconComponent={MoreHorizIcon}
direction='right'
title={intl.formatMessage(messages.more)}
/>
<div className='status__action-bar__button-wrapper'>
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
</div>
<div className='status__action-bar__button-wrapper'>
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
</div>
<div className='status__action-bar__button-wrapper'>
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
</div>
<div className='status__action-bar__button-wrapper'>
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />
</div>
<div className='status__action-bar__button-wrapper'>
<DropdownMenuContainer
scrollKey={scrollKey}
status={status}
items={menu}
icon='ellipsis-h'
iconComponent={MoreHorizIcon}
direction='right'
title={intl.formatMessage(messages.more)}
/>
</div>
</div>
);
}

View file

@ -92,10 +92,10 @@ const messageForFollowButton = relationship => {
if (relationship.get('following') && relationship.get('followed_by')) {
return messages.mutual;
} else if (!relationship.get('following') && relationship.get('followed_by')) {
return messages.followBack;
} else if (relationship.get('following') || relationship.get('requested')) {
return messages.unfollow;
} else if (relationship.get('followed_by')) {
return messages.followBack;
} else {
return messages.follow;
}

View file

@ -43,10 +43,7 @@ class AccountNavigation extends PureComponent {
}
return (
<>
<div className='flex-spacer' />
<FeaturedTags accountId={accountId} tagged={tagged} />
</>
<FeaturedTags accountId={accountId} tagged={tagged} />
);
}

View file

@ -1,5 +1,5 @@
import type { ChangeEventHandler } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { defineMessages, useIntl } from 'react-intl';
@ -23,6 +23,8 @@ import { RadioButton } from 'mastodon/components/radio_button';
import ScrollContainer from 'mastodon/containers/scroll_container';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
import { useSearchParam } from '../../../hooks/useSearchParam';
import { AccountCard } from './components/account_card';
const messages = defineMessages({
@ -47,18 +49,19 @@ export const Directory: React.FC<{
const intl = useIntl();
const dispatch = useAppDispatch();
const [state, setState] = useState<{
order: string | null;
local: boolean | null;
}>({
order: null,
local: null,
});
const column = useRef<Column>(null);
const order = state.order ?? params?.order ?? 'active';
const local = state.local ?? params?.local ?? false;
const [orderParam, setOrderParam] = useSearchParam('order');
const [localParam, setLocalParam] = useSearchParam('local');
let localParamBool: boolean | undefined;
if (localParam === 'false') {
localParamBool = false;
}
const order = orderParam ?? params?.order ?? 'active';
const local = localParamBool ?? params?.local ?? true;
const handlePin = useCallback(() => {
if (columnId) {
@ -101,10 +104,10 @@ export const Directory: React.FC<{
if (columnId) {
dispatch(changeColumnParams(columnId, ['order'], e.target.value));
} else {
setState((s) => ({ order: e.target.value, local: s.local }));
setOrderParam(e.target.value);
}
},
[dispatch, columnId],
[dispatch, columnId, setOrderParam],
);
const handleChangeLocal = useCallback<ChangeEventHandler<HTMLInputElement>>(
@ -113,11 +116,13 @@ export const Directory: React.FC<{
dispatch(
changeColumnParams(columnId, ['local'], e.target.value === '1'),
);
} else if (e.target.value === '1') {
setLocalParam('true');
} else {
setState((s) => ({ local: e.target.value === '1', order: s.order }));
setLocalParam('false');
}
},
[dispatch, columnId],
[dispatch, columnId, setLocalParam],
);
const handleLoadMore = useCallback(() => {

View file

@ -6,7 +6,6 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { forceGroupedNotifications } from 'mastodon/initial_state';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'mastodon/permissions';
import ClearColumnButton from './clear_column_button';
@ -36,7 +35,6 @@ class ColumnSettings extends PureComponent {
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
const unreadMarkersShowStr = <FormattedMessage id='notifications.column_settings.unread_notifications.highlight' defaultMessage='Highlight unread notifications' />;
const groupingShowStr = <FormattedMessage id='notifications.column_settings.beta.grouping' defaultMessage='Group notifications' />;
const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
const soundStr = <FormattedMessage id='notifications.column_settings.sound' defaultMessage='Play sound' />;
@ -68,18 +66,6 @@ class ColumnSettings extends PureComponent {
<PolicyControls />
{!forceGroupedNotifications && (
<section role='group' aria-labelledby='notifications-beta'>
<h3 id='notifications-beta'>
<FormattedMessage id='notifications.column_settings.beta.category' defaultMessage='Experimental features' />
</h3>
<div className='column-settings__row'>
<SettingToggle id='unread-notification-markers' prefix='notifications' settings={settings} settingPath={['groupingBeta']} onChange={onChange} label={groupingShowStr} />
</div>
</section>
)}
<section role='group' aria-labelledby='notifications-unread-markers'>
<h3 id='notifications-unread-markers'>
<FormattedMessage id='notifications.column_settings.unread_notifications.category' defaultMessage='Unread notifications' />

View file

@ -31,7 +31,7 @@ export const FilteredNotificationsIconButton: React.FC<{
history.push('/notifications/requests');
}, [history]);
if (policy === null || policy.summary.pending_notifications_count === 0) {
if (policy === null || policy.summary.pending_requests_count <= 0) {
return null;
}
@ -70,7 +70,7 @@ export const FilteredNotificationsBanner: React.FC = () => {
};
}, [dispatch]);
if (policy === null || policy.summary.pending_notifications_count === 0) {
if (policy === null || policy.summary.pending_requests_count <= 0) {
return null;
}

View file

@ -12,7 +12,7 @@ import DeleteIcon from '@/material-icons/400-24px/delete.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { initBlockModal } from 'mastodon/actions/blocks';
import { initMuteModal } from 'mastodon/actions/mutes';
import { acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
import { acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notification_requests';
import { initReport } from 'mastodon/actions/reports';
import { Avatar } from 'mastodon/components/avatar';
import { CheckBox } from 'mastodon/components/check_box';
@ -40,11 +40,11 @@ export const NotificationRequest = ({ id, accountId, notificationsCount, checked
const { push: historyPush } = useHistory();
const handleDismiss = useCallback(() => {
dispatch(dismissNotificationRequest(id));
dispatch(dismissNotificationRequest({ id }));
}, [dispatch, id]);
const handleAccept = useCallback(() => {
dispatch(acceptNotificationRequest(id));
dispatch(acceptNotificationRequest({ id }));
}, [dispatch, id]);
const handleMute = useCallback(() => {

View file

@ -10,7 +10,13 @@ import { useSelector, useDispatch } from 'react-redux';
import DeleteIcon from '@/material-icons/400-24px/delete.svg?react';
import DoneIcon from '@/material-icons/400-24px/done.svg?react';
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
import { fetchNotificationRequest, fetchNotificationsForRequest, expandNotificationsForRequest, acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
import {
fetchNotificationRequest,
fetchNotificationsForRequest,
expandNotificationsForRequest,
acceptNotificationRequest,
dismissNotificationRequest,
} from 'mastodon/actions/notification_requests';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
import { IconButton } from 'mastodon/components/icon_button';
@ -44,28 +50,28 @@ export const NotificationRequest = ({ multiColumn, params: { id } }) => {
const columnRef = useRef();
const intl = useIntl();
const dispatch = useDispatch();
const notificationRequest = useSelector(state => state.getIn(['notificationRequests', 'current', 'item', 'id']) === id ? state.getIn(['notificationRequests', 'current', 'item']) : null);
const accountId = notificationRequest?.get('account');
const notificationRequest = useSelector(state => state.notificationRequests.current.item?.id === id ? state.notificationRequests.current.item : null);
const accountId = notificationRequest?.account_id;
const account = useSelector(state => state.getIn(['accounts', accountId]));
const notifications = useSelector(state => state.getIn(['notificationRequests', 'current', 'notifications', 'items']));
const isLoading = useSelector(state => state.getIn(['notificationRequests', 'current', 'notifications', 'isLoading']));
const hasMore = useSelector(state => !!state.getIn(['notificationRequests', 'current', 'notifications', 'next']));
const removed = useSelector(state => state.getIn(['notificationRequests', 'current', 'removed']));
const notifications = useSelector(state => state.notificationRequests.current.notifications.items);
const isLoading = useSelector(state => state.notificationRequests.current.notifications.isLoading);
const hasMore = useSelector(state => !!state.notificationRequests.current.notifications.next);
const removed = useSelector(state => state.notificationRequests.current.removed);
const handleHeaderClick = useCallback(() => {
columnRef.current?.scrollTop();
}, [columnRef]);
const handleLoadMore = useCallback(() => {
dispatch(expandNotificationsForRequest());
}, [dispatch]);
dispatch(expandNotificationsForRequest({ accountId }));
}, [dispatch, accountId]);
const handleDismiss = useCallback(() => {
dispatch(dismissNotificationRequest(id));
dispatch(dismissNotificationRequest({ id }));
}, [dispatch, id]);
const handleAccept = useCallback(() => {
dispatch(acceptNotificationRequest(id));
dispatch(acceptNotificationRequest({ id }));
}, [dispatch, id]);
const handleMoveUp = useCallback(id => {
@ -79,12 +85,12 @@ export const NotificationRequest = ({ multiColumn, params: { id } }) => {
}, [columnRef, notifications]);
useEffect(() => {
dispatch(fetchNotificationRequest(id));
dispatch(fetchNotificationRequest({ id }));
}, [dispatch, id]);
useEffect(() => {
if (accountId) {
dispatch(fetchNotificationsForRequest(accountId));
dispatch(fetchNotificationsForRequest({ accountId }));
}
}, [dispatch, accountId]);

View file

@ -11,7 +11,12 @@ import ArrowDropDownIcon from '@/material-icons/400-24px/arrow_drop_down.svg?rea
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { openModal } from 'mastodon/actions/modal';
import { fetchNotificationRequests, expandNotificationRequests, acceptNotificationRequests, dismissNotificationRequests } from 'mastodon/actions/notifications';
import {
fetchNotificationRequests,
expandNotificationRequests,
acceptNotificationRequests,
dismissNotificationRequests,
} from 'mastodon/actions/notification_requests';
import { changeSetting } from 'mastodon/actions/settings';
import { CheckBox } from 'mastodon/components/check_box';
import Column from 'mastodon/components/column';
@ -84,7 +89,7 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM
message: intl.formatMessage(messages.confirmAcceptMultipleMessage, { count: selectedItems.length }),
confirm: intl.formatMessage(messages.confirmAcceptMultipleButton, { count: selectedItems.length}),
onConfirm: () =>
dispatch(acceptNotificationRequests(selectedItems)),
dispatch(acceptNotificationRequests({ ids: selectedItems })),
},
}));
}, [dispatch, intl, selectedItems]);
@ -97,7 +102,7 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM
message: intl.formatMessage(messages.confirmDismissMultipleMessage, { count: selectedItems.length }),
confirm: intl.formatMessage(messages.confirmDismissMultipleButton, { count: selectedItems.length}),
onConfirm: () =>
dispatch(dismissNotificationRequests(selectedItems)),
dispatch(dismissNotificationRequests({ ids: selectedItems })),
},
}));
}, [dispatch, intl, selectedItems]);
@ -161,9 +166,9 @@ export const NotificationRequests = ({ multiColumn }) => {
const columnRef = useRef();
const intl = useIntl();
const dispatch = useDispatch();
const isLoading = useSelector(state => state.getIn(['notificationRequests', 'isLoading']));
const notificationRequests = useSelector(state => state.getIn(['notificationRequests', 'items']));
const hasMore = useSelector(state => !!state.getIn(['notificationRequests', 'next']));
const isLoading = useSelector(state => state.notificationRequests.isLoading);
const notificationRequests = useSelector(state => state.notificationRequests.items);
const hasMore = useSelector(state => !!state.notificationRequests.next);
const [selectionMode, setSelectionMode] = useState(false);
const [checkedRequestIds, setCheckedRequestIds] = useState([]);
@ -182,7 +187,7 @@ export const NotificationRequests = ({ multiColumn }) => {
else
ids.push(id);
setSelectAllChecked(ids.length === notificationRequests.size);
setSelectAllChecked(ids.length === notificationRequests.length);
return [...ids];
});
@ -193,7 +198,7 @@ export const NotificationRequests = ({ multiColumn }) => {
if(checked)
setCheckedRequestIds([]);
else
setCheckedRequestIds(notificationRequests.map(request => request.get('id')).toArray());
setCheckedRequestIds(notificationRequests.map(request => request.id));
return !checked;
});
@ -217,7 +222,7 @@ export const NotificationRequests = ({ multiColumn }) => {
multiColumn={multiColumn}
showBackButton
appendContent={
notificationRequests.size > 0 && (
notificationRequests.length > 0 && (
<SelectRow selectionMode={selectionMode} setSelectionMode={setSelectionMode} selectAllChecked={selectAllChecked} toggleSelectAll={toggleSelectAll} selectedItems={checkedRequestIds} />
)}
>
@ -236,12 +241,12 @@ export const NotificationRequests = ({ multiColumn }) => {
>
{notificationRequests.map(request => (
<NotificationRequest
key={request.get('id')}
id={request.get('id')}
accountId={request.get('account')}
notificationsCount={request.get('notifications_count')}
key={request.id}
id={request.id}
accountId={request.account_id}
notificationsCount={request.notifications_count}
showCheckbox={selectionMode}
checked={checkedRequestIds.includes(request.get('id'))}
checked={checkedRequestIds.includes(request.id)}
toggleCheck={handleCheck}
/>
))}

View file

@ -1,13 +1,8 @@
import Notifications from 'mastodon/features/notifications';
import Notifications_v2 from 'mastodon/features/notifications_v2';
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import { useAppSelector } from 'mastodon/store';
export const NotificationsWrapper = (props) => {
const optedInGroupedNotifications = useAppSelector(selectUseGroupedNotifications);
return (
optedInGroupedNotifications ? <Notifications_v2 {...props} /> : <Notifications {...props} />
<Notifications_v2 {...props} />
);
};

View file

@ -99,7 +99,7 @@ export const BlockModal = ({ accountId, acct }) => {
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
</button>
<Button onClick={handleClick} autoFocus>
<Button onClick={handleClick} dangerous autoFocus>
<FormattedMessage id='confirmations.block.confirm' defaultMessage='Block' />
</Button>
</div>

View file

@ -3,11 +3,11 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useRouteMatch, NavLink } from 'react-router-dom';
import { Icon } from 'mastodon/components/icon';
import { Icon } from 'mastodon/components/icon';
const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text, to, href, method, badge, transparent, ...other }) => {
const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text, to, href, method, badge, transparent, optional, ...other }) => {
const match = useRouteMatch(to);
const className = classNames('column-link', { 'column-link--transparent': transparent });
const className = classNames('column-link', { 'column-link--transparent': transparent, 'column-link--optional': optional });
const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
const iconElement = (typeof icon === 'string' || iconComponent) ? <Icon id={icon} icon={iconComponent} className='column-link__icon' /> : icon;
const activeIconElement = activeIcon ?? (activeIconComponent ? <Icon id={icon} icon={activeIconComponent} className='column-link__icon' /> : iconElement);
@ -43,6 +43,7 @@ ColumnLink.propTypes = {
method: PropTypes.string,
badge: PropTypes.node,
transparent: PropTypes.bool,
optional: PropTypes.bool,
};
export default ColumnLink;

View file

@ -4,8 +4,6 @@ import { Children, cloneElement, useCallback } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { supportsPassiveEvents } from 'detect-passive-events';
import { scrollRight } from '../../../scroll';
import BundleContainer from '../containers/bundle_container';
import {
@ -63,7 +61,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
children: PropTypes.node,
};
// Corresponds to (max-width: $no-gap-breakpoint + 285px - 1px) in SCSS
// Corresponds to (max-width: $no-gap-breakpoint - 1px) in SCSS
mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1174px)');
state = {
@ -71,10 +69,6 @@ export default class ColumnsArea extends ImmutablePureComponent {
};
componentDidMount() {
if (!this.props.singleColumn) {
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
}
if (this.mediaQuery) {
if (this.mediaQuery.addEventListener) {
this.mediaQuery.addEventListener('change', this.handleLayoutChange);
@ -87,23 +81,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
}
UNSAFE_componentWillUpdate(nextProps) {
if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) {
this.node.removeEventListener('wheel', this.handleWheel);
}
}
componentDidUpdate(prevProps) {
if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) {
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
}
}
componentWillUnmount () {
if (!this.props.singleColumn) {
this.node.removeEventListener('wheel', this.handleWheel);
}
if (this.mediaQuery) {
if (this.mediaQuery.removeEventListener) {
this.mediaQuery.removeEventListener('change', this.handleLayoutChange);
@ -116,7 +94,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
handleChildrenContentChange() {
if (!this.props.singleColumn) {
const modifier = this.isRtlLayout ? -1 : 1;
this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier);
scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier);
}
}
@ -124,14 +102,6 @@ export default class ColumnsArea extends ImmutablePureComponent {
this.setState({ renderComposePanel: !e.matches });
};
handleWheel = () => {
if (typeof this._interruptScrollAnimation !== 'function') {
return;
}
this._interruptScrollAnimation();
};
setRef = (node) => {
this.node = node;
};

View file

@ -1,106 +0,0 @@
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { useDispatch } from 'react-redux';
import CampaignIcon from '@/material-icons/400-24px/campaign.svg?react';
import DomainDisabledIcon from '@/material-icons/400-24px/domain_disabled.svg?react';
import HistoryIcon from '@/material-icons/400-24px/history.svg?react';
import PersonRemoveIcon from '@/material-icons/400-24px/person_remove.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
import { blockAccount } from 'mastodon/actions/accounts';
import { blockDomain } from 'mastodon/actions/domain_blocks';
import { closeModal } from 'mastodon/actions/modal';
import { Button } from 'mastodon/components/button';
import { Icon } from 'mastodon/components/icon';
export const DomainBlockModal = ({ domain, accountId, acct }) => {
const dispatch = useDispatch();
const handleClick = useCallback(() => {
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
dispatch(blockDomain(domain));
}, [dispatch, domain]);
const handleSecondaryClick = useCallback(() => {
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
dispatch(blockAccount(accountId));
}, [dispatch, accountId]);
const handleCancel = useCallback(() => {
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
}, [dispatch]);
return (
<div className='modal-root__modal safety-action-modal'>
<div className='safety-action-modal__top'>
<div className='safety-action-modal__header'>
<div className='safety-action-modal__header__icon'>
<Icon icon={DomainDisabledIcon} />
</div>
<div>
<h1><FormattedMessage id='domain_block_modal.title' defaultMessage='Block domain?' /></h1>
<div>{domain}</div>
</div>
</div>
<div className='safety-action-modal__bullet-points'>
<div>
<div className='safety-action-modal__bullet-points__icon'><Icon icon={CampaignIcon} /></div>
<div><FormattedMessage id='domain_block_modal.they_wont_know' defaultMessage="They won't know they've been blocked." /></div>
</div>
<div>
<div className='safety-action-modal__bullet-points__icon'><Icon icon={VisibilityOffIcon} /></div>
<div><FormattedMessage id='domain_block_modal.you_wont_see_posts' defaultMessage="You won't see posts or notifications from users on this server." /></div>
</div>
<div>
<div className='safety-action-modal__bullet-points__icon'><Icon icon={PersonRemoveIcon} /></div>
<div><FormattedMessage id='domain_block_modal.you_will_lose_followers' defaultMessage='All your followers from this server will be removed.' /></div>
</div>
<div>
<div className='safety-action-modal__bullet-points__icon'><Icon icon={ReplyIcon} /></div>
<div><FormattedMessage id='domain_block_modal.they_cant_follow' defaultMessage='Nobody from this server can follow you.' /></div>
</div>
<div>
<div className='safety-action-modal__bullet-points__icon'><Icon icon={HistoryIcon} /></div>
<div><FormattedMessage id='domain_block_modal.they_can_interact_with_old_posts' defaultMessage='People from this server can interact with your old posts.' /></div>
</div>
</div>
</div>
<div className='safety-action-modal__bottom'>
<div className='safety-action-modal__actions'>
<Button onClick={handleSecondaryClick} secondary>
<FormattedMessage id='domain_block_modal.block_account_instead' defaultMessage='Block @{name} instead' values={{ name: acct.split('@')[0] }} />
</Button>
<div className='spacer' />
<button onClick={handleCancel} className='link-button'>
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
</button>
<Button onClick={handleClick} autoFocus>
<FormattedMessage id='domain_block_modal.block' defaultMessage='Block server' />
</Button>
</div>
</div>
</div>
);
};
DomainBlockModal.propTypes = {
domain: PropTypes.string.isRequired,
accountId: PropTypes.string.isRequired,
acct: PropTypes.string.isRequired,
};
export default DomainBlockModal;

View file

@ -0,0 +1,204 @@
import { useCallback, useEffect, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import CampaignIcon from '@/material-icons/400-24px/campaign.svg?react';
import DomainDisabledIcon from '@/material-icons/400-24px/domain_disabled.svg?react';
import HistoryIcon from '@/material-icons/400-24px/history.svg?react';
import PersonRemoveIcon from '@/material-icons/400-24px/person_remove.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
import { blockAccount } from 'mastodon/actions/accounts';
import { blockDomain } from 'mastodon/actions/domain_blocks';
import { closeModal } from 'mastodon/actions/modal';
import { apiRequest } from 'mastodon/api';
import { Button } from 'mastodon/components/button';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { ShortNumber } from 'mastodon/components/short_number';
import { useAppDispatch } from 'mastodon/store';
interface DomainBlockPreviewResponse {
following_count: number;
followers_count: number;
}
export const DomainBlockModal: React.FC<{
domain: string;
accountId: string;
acct: string;
}> = ({ domain, accountId, acct }) => {
const dispatch = useAppDispatch();
const [loading, setLoading] = useState(true);
const [preview, setPreview] = useState<DomainBlockPreviewResponse | null>(
null,
);
const handleClick = useCallback(() => {
if (loading) {
return; // Prevent destructive action before the preview finishes loading or times out
}
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
dispatch(blockDomain(domain));
}, [dispatch, loading, domain]);
const handleSecondaryClick = useCallback(() => {
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
dispatch(blockAccount(accountId));
}, [dispatch, accountId]);
const handleCancel = useCallback(() => {
dispatch(closeModal({ modalType: undefined, ignoreFocus: false }));
}, [dispatch]);
useEffect(() => {
setLoading(true);
apiRequest<DomainBlockPreviewResponse>('GET', 'v1/domain_blocks/preview', {
params: { domain },
timeout: 5000,
})
.then((data) => {
setPreview(data);
setLoading(false);
return '';
})
.catch(() => {
setLoading(false);
});
}, [setPreview, setLoading, domain]);
return (
<div className='modal-root__modal safety-action-modal' aria-live='polite'>
<div className='safety-action-modal__top'>
<div className='safety-action-modal__header'>
<div className='safety-action-modal__header__icon'>
<Icon id='' icon={DomainDisabledIcon} />
</div>
<div>
<h1>
<FormattedMessage
id='domain_block_modal.title'
defaultMessage='Block domain?'
/>
</h1>
<div>{domain}</div>
</div>
</div>
<div className='safety-action-modal__bullet-points'>
{preview && preview.followers_count + preview.following_count > 0 && (
<div>
<div className='safety-action-modal__bullet-points__icon'>
<Icon id='' icon={PersonRemoveIcon} />
</div>
<div>
<strong>
<FormattedMessage
id='domain_block_modal.you_will_lose_num_followers'
defaultMessage='You will lose {followersCount, plural, one {{followersCountDisplay} follower} other {{followersCountDisplay} followers}} and {followingCount, plural, one {{followingCountDisplay} person you follow} other {{followingCountDisplay} people you follow}}.'
values={{
followersCount: preview.followers_count,
followersCountDisplay: (
<ShortNumber value={preview.followers_count} />
),
followingCount: preview.following_count,
followingCountDisplay: (
<ShortNumber value={preview.following_count} />
),
}}
/>
</strong>
</div>
</div>
)}
<div className='safety-action-modal__bullet-points--deemphasized'>
<div className='safety-action-modal__bullet-points__icon'>
<Icon id='' icon={CampaignIcon} />
</div>
<div>
<FormattedMessage
id='domain_block_modal.they_wont_know'
defaultMessage="They won't know they've been blocked."
/>
</div>
</div>
<div className='safety-action-modal__bullet-points--deemphasized'>
<div className='safety-action-modal__bullet-points__icon'>
<Icon id='' icon={VisibilityOffIcon} />
</div>
<div>
<FormattedMessage
id='domain_block_modal.you_wont_see_posts'
defaultMessage="You won't see posts or notifications from users on this server."
/>
</div>
</div>
<div className='safety-action-modal__bullet-points--deemphasized'>
<div className='safety-action-modal__bullet-points__icon'>
<Icon id='' icon={ReplyIcon} />
</div>
<div>
<FormattedMessage
id='domain_block_modal.they_cant_follow'
defaultMessage='Nobody from this server can follow you.'
/>
</div>
</div>
<div className='safety-action-modal__bullet-points--deemphasized'>
<div className='safety-action-modal__bullet-points__icon'>
<Icon id='' icon={HistoryIcon} />
</div>
<div>
<FormattedMessage
id='domain_block_modal.they_can_interact_with_old_posts'
defaultMessage='People from this server can interact with your old posts.'
/>
</div>
</div>
</div>
</div>
<div className='safety-action-modal__bottom'>
<div className='safety-action-modal__actions'>
<Button onClick={handleSecondaryClick} secondary>
<FormattedMessage
id='domain_block_modal.block_account_instead'
defaultMessage='Block @{name} instead'
values={{ name: acct.split('@')[0] }}
/>
</Button>
<div className='spacer' />
<button onClick={handleCancel} className='link-button'>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'
/>
</button>
<Button onClick={handleClick} dangerous aria-busy={loading}>
{loading ? (
<LoadingIndicator />
) : (
<FormattedMessage
id='domain_block_modal.block'
defaultMessage='Block server'
/>
)}
</Button>
</div>
</div>
</div>
);
};
// eslint-disable-next-line import/no-default-export
export default DomainBlockModal;

View file

@ -17,7 +17,7 @@ export default class ImageLoader extends PureComponent {
width: PropTypes.number,
height: PropTypes.number,
onClick: PropTypes.func,
zoomButtonHidden: PropTypes.bool,
zoomedIn: PropTypes.bool,
};
static defaultProps = {
@ -134,7 +134,7 @@ export default class ImageLoader extends PureComponent {
};
render () {
const { alt, lang, src, width, height, onClick } = this.props;
const { alt, lang, src, width, height, onClick, zoomedIn } = this.props;
const { loading } = this.state;
const className = classNames('image-loader', {
@ -149,6 +149,7 @@ export default class ImageLoader extends PureComponent {
<div className='loading-bar__container' style={{ width: this.state.width || width }}>
<LoadingBar className='loading-bar' loading={1} />
</div>
<canvas
className='image-loader__preview-canvas'
ref={this.setCanvasRef}
@ -164,7 +165,7 @@ export default class ImageLoader extends PureComponent {
onClick={onClick}
width={width}
height={height}
zoomButtonHidden={this.props.zoomButtonHidden}
zoomedIn={zoomedIn}
/>
)}
</div>

View file

@ -12,6 +12,8 @@ import ReactSwipeableViews from 'react-swipeable-views';
import ChevronLeftIcon from '@/material-icons/400-24px/chevron_left.svg?react';
import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import FitScreenIcon from '@/material-icons/400-24px/fit_screen.svg?react';
import ActualSizeIcon from '@/svg-icons/actual_size.svg?react';
import { getAverageFromBlurhash } from 'mastodon/blurhash';
import { GIFV } from 'mastodon/components/gifv';
import { Icon } from 'mastodon/components/icon';
@ -26,6 +28,8 @@ const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
next: { id: 'lightbox.next', defaultMessage: 'Next' },
zoomIn: { id: 'lightbox.zoom_in', defaultMessage: 'Zoom to actual size' },
zoomOut: { id: 'lightbox.zoom_out', defaultMessage: 'Zoom to fit' },
});
class MediaModal extends ImmutablePureComponent {
@ -46,30 +50,39 @@ class MediaModal extends ImmutablePureComponent {
state = {
index: null,
navigationHidden: false,
zoomButtonHidden: false,
zoomedIn: false,
};
handleZoomClick = () => {
this.setState(prevState => ({
zoomedIn: !prevState.zoomedIn,
}));
};
handleSwipe = (index) => {
this.setState({ index: index % this.props.media.size });
this.setState({
index: index % this.props.media.size,
zoomedIn: false,
});
};
handleTransitionEnd = () => {
this.setState({
zoomButtonHidden: false,
zoomedIn: false,
});
};
handleNextClick = () => {
this.setState({
index: (this.getIndex() + 1) % this.props.media.size,
zoomButtonHidden: true,
zoomedIn: false,
});
};
handlePrevClick = () => {
this.setState({
index: (this.props.media.size + this.getIndex() - 1) % this.props.media.size,
zoomButtonHidden: true,
zoomedIn: false,
});
};
@ -78,7 +91,7 @@ class MediaModal extends ImmutablePureComponent {
this.setState({
index: index % this.props.media.size,
zoomButtonHidden: true,
zoomedIn: false,
});
};
@ -130,15 +143,22 @@ class MediaModal extends ImmutablePureComponent {
return this.state.index !== null ? this.state.index : this.props.index;
}
toggleNavigation = () => {
handleToggleNavigation = () => {
this.setState(prevState => ({
navigationHidden: !prevState.navigationHidden,
}));
};
setRef = c => {
this.setState({
viewportWidth: c?.clientWidth,
viewportHeight: c?.clientHeight,
});
};
render () {
const { media, statusId, lang, intl, onClose } = this.props;
const { navigationHidden } = this.state;
const { navigationHidden, zoomedIn, viewportWidth, viewportHeight } = this.state;
const index = this.getIndex();
@ -160,8 +180,8 @@ class MediaModal extends ImmutablePureComponent {
alt={description}
lang={lang}
key={image.get('url')}
onClick={this.toggleNavigation}
zoomButtonHidden={this.state.zoomButtonHidden}
onClick={this.handleToggleNavigation}
zoomedIn={zoomedIn}
/>
);
} else if (image.get('type') === 'video') {
@ -230,9 +250,12 @@ class MediaModal extends ImmutablePureComponent {
));
}
const currentMedia = media.get(index);
const zoomable = currentMedia.get('type') === 'image' && (currentMedia.getIn(['meta', 'original', 'width']) > viewportWidth || currentMedia.getIn(['meta', 'original', 'height']) > viewportHeight);
return (
<div className='modal-root__modal media-modal'>
<div className='media-modal__closer' role='presentation' onClick={onClose} >
<div className='modal-root__modal media-modal' ref={this.setRef}>
<div className='media-modal__closer' role='presentation' onClick={onClose}>
<ReactSwipeableViews
style={swipeableViewsStyle}
containerStyle={containerStyle}
@ -246,7 +269,10 @@ class MediaModal extends ImmutablePureComponent {
</div>
<div className={navigationClassName}>
<IconButton className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' iconComponent={CloseIcon} onClick={onClose} size={40} />
<div className='media-modal__buttons'>
{zoomable && <IconButton title={intl.formatMessage(zoomedIn ? messages.zoomOut : messages.zoomIn)} iconComponent={zoomedIn ? FitScreenIcon : ActualSizeIcon} onClick={this.handleZoomClick} />}
<IconButton title={intl.formatMessage(messages.close)} icon='times' iconComponent={CloseIcon} onClick={onClose} />
</div>
{leftNav}
{rightNav}

View file

@ -38,7 +38,6 @@ import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
import { transientSingleColumn } from 'mastodon/is_mobile';
import { canManageReports, canViewAdminDashboard } from 'mastodon/permissions';
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
import { selectUseGroupedNotifications } from 'mastodon/selectors/settings';
import ColumnLink from './column_link';
import DisabledAccountBanner from './disabled_account_banner';
@ -67,19 +66,17 @@ const messages = defineMessages({
});
const NotificationsLink = () => {
const optedInGroupedNotifications = useSelector(selectUseGroupedNotifications);
const count = useSelector(state => state.getIn(['notifications', 'unread']));
const intl = useIntl();
const newCount = useSelector(selectUnreadNotificationGroupsCount);
const count = useSelector(selectUnreadNotificationGroupsCount);
const intl = useIntl();
return (
<ColumnLink
key='notifications'
transparent
to='/notifications'
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={optedInGroupedNotifications ? newCount : count} className='column-link__icon' />}
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={optedInGroupedNotifications ? newCount : count} className='column-link__icon' />}
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={count} className='column-link__icon' />}
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={count} className='column-link__icon' />}
text={intl.formatMessage(messages.notifications)}
/>
);
@ -125,14 +122,17 @@ class NavigationPanel extends Component {
let banner = undefined;
if(transientSingleColumn)
banner = (<div className='switch-to-advanced'>
{intl.formatMessage(messages.openedInClassicInterface)}
{" "}
<a href={`/deck${location.pathname}`} className='switch-to-advanced__toggle'>
{intl.formatMessage(messages.advancedInterface)}
</a>
</div>);
if (transientSingleColumn) {
banner = (
<div className='switch-to-advanced'>
{intl.formatMessage(messages.openedInClassicInterface)}
{" "}
<a href={`/deck${location.pathname}`} className='switch-to-advanced__toggle'>
{intl.formatMessage(messages.advancedInterface)}
</a>
</div>
);
}
return (
<div className='navigation-panel'>
@ -146,57 +146,59 @@ class NavigationPanel extends Component {
</div>
}
{signedIn && (
<>
<ColumnLink transparent to='/home' icon='home' iconComponent={HomeIcon} activeIconComponent={HomeActiveIcon} text={intl.formatMessage(messages.home)} />
<NotificationsLink />
<FollowRequestsLink />
</>
)}
<div className='navigation-panel__menu'>
{signedIn && (
<>
<ColumnLink transparent to='/home' icon='home' iconComponent={HomeIcon} activeIconComponent={HomeActiveIcon} text={intl.formatMessage(messages.home)} />
<NotificationsLink />
<FollowRequestsLink />
</>
)}
{trendsEnabled ? (
<ColumnLink transparent to='/explore' icon='explore' iconComponent={ExploreIcon} activeIconComponent={ExploreActiveIcon} text={intl.formatMessage(messages.explore)} />
) : (
<ColumnLink transparent to='/search' icon='search' iconComponent={SearchIcon} text={intl.formatMessage(messages.search)} />
)}
{trendsEnabled ? (
<ColumnLink transparent to='/explore' icon='explore' iconComponent={ExploreIcon} activeIconComponent={ExploreActiveIcon} text={intl.formatMessage(messages.explore)} />
) : (
<ColumnLink transparent to='/search' icon='search' iconComponent={SearchIcon} text={intl.formatMessage(messages.search)} />
)}
{(signedIn || timelinePreview) && (
<>
{(signedIn || timelinePreview) && (
<ColumnLink transparent to='/public/local' isActive={this.isFirehoseActive} icon='globe' iconComponent={PublicIcon} text={intl.formatMessage(messages.firehose)} />
<ColumnLink transparent to='/tags/furry' icon='pets' iconComponent={FurryIcon} text={intl.formatMessage(messages.furry)} />
</>
)}
)}
{!signedIn && (
<div className='navigation-panel__sign-in-banner'>
{!signedIn && (
<div className='navigation-panel__sign-in-banner'>
<hr />
{ disabledAccountId ? <DisabledAccountBanner /> : <SignInBanner /> }
</div>
)}
{signedIn && (
<>
<ColumnLink transparent to='/conversations' icon='at' iconComponent={AlternateEmailIcon} text={intl.formatMessage(messages.direct)} />
<ColumnLink transparent to='/bookmarks' icon='bookmarks' iconComponent={BookmarksIcon} activeIconComponent={BookmarksActiveIcon} text={intl.formatMessage(messages.bookmarks)} />
<ColumnLink transparent to='/favourites' icon='star' iconComponent={StarIcon} activeIconComponent={StarActiveIcon} text={intl.formatMessage(messages.favourites)} />
<ColumnLink transparent to='/lists' icon='list-ul' iconComponent={ListAltIcon} activeIconComponent={ListAltActiveIcon} text={intl.formatMessage(messages.lists)} />
<ListPanel />
<hr />
<ColumnLink transparent href='/settings/preferences' icon='cog' iconComponent={SettingsIcon} text={intl.formatMessage(messages.preferences)} />
{canManageReports(permissions) && <ColumnLink optional transparent href='/admin/reports' icon='flag' iconComponent={ModerationIcon} text={intl.formatMessage(messages.moderation)} />}
{canViewAdminDashboard(permissions) && <ColumnLink optional transparent href='/admin/dashboard' icon='tachometer' iconComponent={AdministrationIcon} text={intl.formatMessage(messages.administration)} />}
</>
)}
<div className='navigation-panel__legal'>
<hr />
{ disabledAccountId ? <DisabledAccountBanner /> : <SignInBanner /> }
<ColumnLink transparent to='/about' icon='ellipsis-h' iconComponent={MoreHorizIcon} text={intl.formatMessage(messages.about)} />
</div>
)}
{signedIn && (
<>
<ColumnLink transparent to='/conversations' icon='at' iconComponent={AlternateEmailIcon} text={intl.formatMessage(messages.direct)} />
<ColumnLink transparent to='/bookmarks' icon='bookmarks' iconComponent={BookmarksIcon} activeIconComponent={BookmarksActiveIcon} text={intl.formatMessage(messages.bookmarks)} />
<ColumnLink transparent to='/favourites' icon='star' iconComponent={StarIcon} activeIconComponent={StarActiveIcon} text={intl.formatMessage(messages.favourites)} />
<ColumnLink transparent to='/lists' icon='list-ul' iconComponent={ListAltIcon} activeIconComponent={ListAltActiveIcon} text={intl.formatMessage(messages.lists)} />
<ListPanel />
<hr />
<ColumnLink transparent href='/settings/preferences' icon='cog' iconComponent={SettingsIcon} text={intl.formatMessage(messages.preferences)} />
{canManageReports(permissions) && <ColumnLink transparent href='/admin/reports' icon='flag' iconComponent={ModerationIcon} text={intl.formatMessage(messages.moderation)} />}
{canViewAdminDashboard(permissions) && <ColumnLink transparent href='/admin/dashboard' icon='tachometer' iconComponent={AdministrationIcon} text={intl.formatMessage(messages.administration)} />}
</>
)}
<div className='navigation-panel__legal'>
<hr />
<ColumnLink transparent to='/about' icon='ellipsis-h' iconComponent={MoreHorizIcon} text={intl.formatMessage(messages.about)} />
</div>
<div className='flex-spacer' />
<NavigationPortal />
</div>
);

View file

@ -1,17 +1,6 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import FullscreenExitIcon from '@/material-icons/400-24px/fullscreen_exit.svg?react';
import RectangleIcon from '@/material-icons/400-24px/rectangle.svg?react';
import { IconButton } from 'mastodon/components/icon_button';
const messages = defineMessages({
compress: { id: 'lightbox.compress', defaultMessage: 'Compress image view box' },
expand: { id: 'lightbox.expand', defaultMessage: 'Expand image view box' },
});
const MIN_SCALE = 1;
const MAX_SCALE = 4;
const NAV_BAR_HEIGHT = 66;
@ -104,8 +93,7 @@ class ZoomableImage extends PureComponent {
width: PropTypes.number,
height: PropTypes.number,
onClick: PropTypes.func,
zoomButtonHidden: PropTypes.bool,
intl: PropTypes.object.isRequired,
zoomedIn: PropTypes.bool,
};
static defaultProps = {
@ -131,8 +119,6 @@ class ZoomableImage extends PureComponent {
translateX: null,
translateY: null,
},
zoomState: 'expand', // 'expand' 'compress'
navigationHidden: false,
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
dragged: false,
lockScroll: { x: 0, y: 0 },
@ -169,35 +155,20 @@ class ZoomableImage extends PureComponent {
this.container.addEventListener('DOMMouseScroll', handler);
this.removers.push(() => this.container.removeEventListener('DOMMouseScroll', handler));
this.initZoomMatrix();
this._initZoomMatrix();
}
componentWillUnmount () {
this.removeEventListeners();
this._removeEventListeners();
}
componentDidUpdate () {
this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
if (this.state.scale === MIN_SCALE) {
this.container.style.removeProperty('cursor');
componentDidUpdate (prevProps) {
if (prevProps.zoomedIn !== this.props.zoomedIn) {
this._toggleZoom();
}
}
UNSAFE_componentWillReceiveProps () {
// reset when slide to next image
if (this.props.zoomButtonHidden) {
this.setState({
scale: MIN_SCALE,
lockTranslate: { x: 0, y: 0 },
}, () => {
this.container.scrollLeft = 0;
this.container.scrollTop = 0;
});
}
}
removeEventListeners () {
_removeEventListeners () {
this.removers.forEach(listeners => listeners());
this.removers = [];
}
@ -220,9 +191,6 @@ class ZoomableImage extends PureComponent {
};
mouseDownHandler = e => {
this.container.style.cursor = 'grabbing';
this.container.style.userSelect = 'none';
this.setState({ dragPosition: {
left: this.container.scrollLeft,
top: this.container.scrollTop,
@ -246,9 +214,6 @@ class ZoomableImage extends PureComponent {
};
mouseUpHandler = () => {
this.container.style.cursor = 'grab';
this.container.style.removeProperty('user-select');
this.image.removeEventListener('mousemove', this.mouseMoveHandler);
this.image.removeEventListener('mouseup', this.mouseUpHandler);
};
@ -276,13 +241,13 @@ class ZoomableImage extends PureComponent {
const _MAX_SCALE = Math.max(MAX_SCALE, this.state.zoomMatrix.rate);
const scale = clamp(MIN_SCALE, _MAX_SCALE, this.state.scale * distance / this.lastDistance);
this.zoom(scale, midpoint);
this._zoom(scale, midpoint);
this.lastMidpoint = midpoint;
this.lastDistance = distance;
};
zoom(nextScale, midpoint) {
_zoom(nextScale, midpoint) {
const { scale, zoomMatrix } = this.state;
const { scrollLeft, scrollTop } = this.container;
@ -318,14 +283,13 @@ class ZoomableImage extends PureComponent {
if (dragged) return;
const handler = this.props.onClick;
if (handler) handler();
this.setState({ navigationHidden: !this.state.navigationHidden });
};
handleMouseDown = e => {
e.preventDefault();
};
initZoomMatrix = () => {
_initZoomMatrix = () => {
const { width, height } = this.props;
const { clientWidth, clientHeight } = this.container;
const { offsetWidth, offsetHeight } = this.image;
@ -357,10 +321,7 @@ class ZoomableImage extends PureComponent {
});
};
handleZoomClick = e => {
e.preventDefault();
e.stopPropagation();
_toggleZoom () {
const { scale, zoomMatrix } = this.state;
if ( scale >= zoomMatrix.rate ) {
@ -394,10 +355,7 @@ class ZoomableImage extends PureComponent {
this.container.scrollTop = zoomMatrix.scrollTop;
});
}
this.container.style.cursor = 'grab';
this.container.style.removeProperty('user-select');
};
}
setContainerRef = c => {
this.container = c;
@ -408,52 +366,37 @@ class ZoomableImage extends PureComponent {
};
render () {
const { alt, lang, src, width, height, intl } = this.props;
const { scale, lockTranslate } = this.state;
const { alt, lang, src, width, height } = this.props;
const { scale, lockTranslate, dragged } = this.state;
const overflow = scale === MIN_SCALE ? 'hidden' : 'scroll';
const zoomButtonShouldHide = this.state.navigationHidden || this.props.zoomButtonHidden || this.state.zoomMatrix.rate <= MIN_SCALE ? 'media-modal__zoom-button--hidden' : '';
const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
const cursor = scale === MIN_SCALE ? null : (dragged ? 'grabbing' : 'grab');
return (
<>
<IconButton
className={`media-modal__zoom-button ${zoomButtonShouldHide}`}
title={zoomButtonTitle}
icon={this.state.zoomState}
iconComponent={this.state.zoomState === 'compress' ? FullscreenExitIcon : RectangleIcon}
onClick={this.handleZoomClick}
size={40}
<div
className='zoomable-image'
ref={this.setContainerRef}
style={{ overflow, cursor, userSelect: 'none' }}
>
<img
role='presentation'
ref={this.setImageRef}
alt={alt}
title={alt}
lang={lang}
src={src}
width={width}
height={height}
style={{
fontSize: '30px', /* Fontawesome's fa-compress fa-expand is larger than fa-close */
transform: `scale(${scale}) translate(-${lockTranslate.x}px, -${lockTranslate.y}px)`,
transformOrigin: '0 0',
}}
draggable={false}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
/>
<div
className='zoomable-image'
ref={this.setContainerRef}
style={{ overflow }}
>
<img
role='presentation'
ref={this.setImageRef}
alt={alt}
title={alt}
lang={lang}
src={src}
width={width}
height={height}
style={{
transform: `scale(${scale}) translate(-${lockTranslate.x}px, -${lockTranslate.y}px)`,
transformOrigin: '0 0',
}}
draggable={false}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
/>
</div>
</>
</div>
);
}
}
export default injectIntl(ZoomableImage);
export default ZoomableImage;

View file

@ -186,7 +186,7 @@ class SwitchingColumnsArea extends PureComponent {
{redirect}
{singleColumn ? <Redirect from='/deck' to='/home' exact /> : null}
{singleColumn && pathName.startsWith('/deck/') ? <Redirect from={pathName} to={pathName.slice(5)} /> : null}
{singleColumn && pathName.startsWith('/deck/') ? <Redirect from={pathName} to={{...this.props.location, pathname: pathName.slice(5)}} /> : null}
{/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */}
{!singleColumn && pathName === '/getting-started' ? <Redirect from='/getting-started' to='/deck/getting-started' exact /> : null}
{!singleColumn && pathName === '/home' ? <Redirect from='/home' to='/deck/getting-started' exact /> : null}

View file

@ -43,7 +43,6 @@
* @property {boolean=} use_pending_items
* @property {string} version
* @property {string} sso_redirect
* @property {boolean} force_grouped_notifications
*/
/**
@ -119,7 +118,6 @@ export const criticalUpdatesPending = initialState?.critical_updates_pending;
// @ts-expect-error
export const statusPageUrl = getMeta('status_page_url');
export const sso_redirect = getMeta('sso_redirect');
export const forceGroupedNotifications = getMeta('force_grouped_notifications');
/**
* @returns {string | undefined}

View file

@ -288,8 +288,6 @@
"keyboard_shortcuts.unfocus": "Retirar lo foco d'a caixa de redacción/busqueda",
"keyboard_shortcuts.up": "Ir enta alto en a lista",
"lightbox.close": "Zarrar",
"lightbox.compress": "Comprimir quadro de visualización d'imachen",
"lightbox.expand": "Expandir quadro de visualización d'imachen",
"lightbox.next": "Siguient",
"lightbox.previous": "Anterior",
"limited_account_hint.action": "Amostrar perfil de totz modos",

View file

@ -36,6 +36,7 @@
"account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.",
"account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two {مُتابعانِ اِثنان} few {{counter} مُتابِعين} many {{counter} مُتابِعًا} other {{counter} مُتابع}}",
"account.following": "الاشتراكات",
"account.following_counter": "{count, plural, zero{لا يُتابِع أحدًا} one {يُتابِعُ واحد} two{يُتابِعُ اِثنان} few{يُتابِعُ {counter}} many{يُتابِعُ {counter}} other {يُتابِعُ {counter}}}",
"account.follows.empty": "لا يُتابع هذا المُستخدمُ أيَّ أحدٍ حتى الآن.",
"account.go_to_profile": "اذهب إلى الملف الشخصي",
"account.hide_reblogs": "إخفاء المعاد نشرها مِن @{name}",
@ -219,7 +220,6 @@
"domain_block_modal.they_cant_follow": "لا أحد من هذا الخادم يمكنه متابعتك.",
"domain_block_modal.they_wont_know": "لن يَعرف أنه قد تم حظره.",
"domain_block_modal.title": "أتريد حظر النطاق؟",
"domain_block_modal.you_will_lose_followers": "سيتم إزالة جميع متابعيك من هذا الخادم.",
"domain_block_modal.you_wont_see_posts": "لن ترى منشورات أو إشعارات من المستخدمين على هذا الخادم.",
"domain_pill.activitypub_lets_connect": "يتيح لك التواصل والتفاعل مع الناس ليس فقط على ماستدون، ولكن عبر تطبيقات اجتماعية مختلفة أيضا.",
"domain_pill.activitypub_like_language": "إنّ ActivityPub مثل لغة ماستدون التي يتحدث بها مع شبكات اجتماعية أخرى.",
@ -309,7 +309,7 @@
"follow_request.authorize": "ترخيص",
"follow_request.reject": "رفض",
"follow_requests.unlocked_explanation": "حتى وإن كان حسابك غير مقفل، يعتقد فريق {domain} أنك قد ترغب في مراجعة طلبات المتابعة من هذه الحسابات يدوياً.",
"follow_suggestions.curated_suggestion": "اختيار الموظفين",
"follow_suggestions.curated_suggestion": "انتقاه الفريق",
"follow_suggestions.dismiss": "لا تُظهرها مجدّدًا",
"follow_suggestions.featured_longer": "مختار يدوياً من قِبل فريق {domain}",
"follow_suggestions.friends_of_friends_longer": "مشهور بين الأشخاص الذين تتابعهم",
@ -419,8 +419,6 @@
"keyboard_shortcuts.unfocus": "لإلغاء التركيز على حقل النص أو نافذة البحث",
"keyboard_shortcuts.up": "للانتقال إلى أعلى القائمة",
"lightbox.close": "إغلاق",
"lightbox.compress": "ضغط مربع عرض الصورة",
"lightbox.expand": "توسيع مربع عرض الصور",
"lightbox.next": "التالي",
"lightbox.previous": "العودة",
"limited_account_hint.action": "إظهار الملف التعريفي على أي حال",
@ -528,8 +526,6 @@
"notifications.column_settings.admin.report": "التبليغات الجديدة:",
"notifications.column_settings.admin.sign_up": "التسجيلات الجديدة:",
"notifications.column_settings.alert": "إشعارات سطح المكتب",
"notifications.column_settings.beta.category": "ميزات تجريبية",
"notifications.column_settings.beta.grouping": "جمّع الإشعارات",
"notifications.column_settings.favourite": "المفضلة:",
"notifications.column_settings.filter_bar.advanced": "عرض جميع الفئات",
"notifications.column_settings.filter_bar.category": "شريط التصفية السريعة",
@ -754,7 +750,7 @@
"status.edit": "تعديل",
"status.edited": "آخر تعديل يوم {date}",
"status.edited_x_times": "عُدّل {count, plural, zero {} one {مرةً واحدة} two {مرّتان} few {{count} مرات} many {{count} مرة} other {{count} مرة}}",
"status.embed": "الحصول على شفرة الإدماج",
"status.embed": "الحصول على شيفرة الدمج",
"status.favourite": "فضّل",
"status.favourites": "{count, plural, zero {}one {مفضلة واحدة} two {مفضلتان} few {# مفضلات} many {# مفضلات} other {# مفضلات}}",
"status.filter": "تصفية هذا المنشور",
@ -775,7 +771,7 @@
"status.reblog": "إعادة النشر",
"status.reblog_private": "إعادة النشر إلى الجمهور الأصلي",
"status.reblogged_by": "شارَكَه {name}",
"status.reblogs": "{count, plural, one {تعزيز واحد} two {تعزيزتان} few {# تعزيزات} many {# تعزيزات} other {# تعزيزات}}",
"status.reblogs": "{count, plural, one {إعادة نشر واحدة} two {معاد نشرها مرتان} few {# إعادات نشر} many {# إعادات نشر} other {# إعادة نشر}}",
"status.reblogs.empty": "لم يقم أي أحد بمشاركة هذا المنشور بعد. عندما يقوم أحدهم بذلك سوف يظهر هنا.",
"status.redraft": "إزالة وإعادة الصياغة",
"status.remove_bookmark": "احذفه مِن الفواصل المرجعية",

View file

@ -297,7 +297,6 @@
"notifications.clear": "Borrar los avisos",
"notifications.column_settings.admin.report": "Informes nuevos:",
"notifications.column_settings.admin.sign_up": "Rexistros nuevos:",
"notifications.column_settings.beta.category": "Funciones esperimentales",
"notifications.column_settings.follow": "Siguidores nuevos:",
"notifications.column_settings.follow_request": "Solicitúes de siguimientu nueves:",
"notifications.column_settings.mention": "Menciones:",

View file

@ -219,7 +219,6 @@
"domain_block_modal.they_cant_follow": "Ніхто з гэтага сервера не зможа падпісацца на вас.",
"domain_block_modal.they_wont_know": "Карыстальнік не будзе ведаць пра блакіроўку.",
"domain_block_modal.title": "Заблакіраваць дамен?",
"domain_block_modal.you_will_lose_followers": "Усе падпісчыкі з гэтага сервера будуць выдаленыя.",
"domain_block_modal.you_wont_see_posts": "Вы не ўбачыце допісаў і апавяшчэнняў ад карыстальнікаў з гэтага сервера.",
"domain_pill.activitypub_lets_connect": "Ён дазваляе вам узаемадзейнічаць не толькі з карыстальнікамі Mastodon, але і розных іншых сацыяльных платформ.",
"domain_pill.activitypub_like_language": "ActivityPub — гэта мова, на якой Mastodon размаўляе з іншымі сацыяльнымі сеткамі.",
@ -412,8 +411,6 @@
"keyboard_shortcuts.unfocus": "Расфакусаваць тэкставую вобласць/пошукавы радок",
"keyboard_shortcuts.up": "Перамясціцца ўверх па спісе",
"lightbox.close": "Закрыць",
"lightbox.compress": "Сціснуць бачную вобласць выявы",
"lightbox.expand": "Павялічыць бачную вобласць выявы",
"lightbox.next": "Далей",
"lightbox.previous": "Назад",
"limited_account_hint.action": "Усе роўна паказваць профіль",
@ -523,8 +520,6 @@
"notifications.column_settings.admin.report": "Новыя скаргі:",
"notifications.column_settings.admin.sign_up": "Новыя ўваходы:",
"notifications.column_settings.alert": "Апавяшчэнні на працоўным стале",
"notifications.column_settings.beta.category": "Эксперыментальныя функцыі",
"notifications.column_settings.beta.grouping": "Групаваць апавяшчэннi",
"notifications.column_settings.favourite": "Упадабанае:",
"notifications.column_settings.filter_bar.advanced": "Паказаць усе катэгорыі",
"notifications.column_settings.filter_bar.category": "Панэль хуткай фільтрацыі",

View file

@ -220,7 +220,6 @@
"domain_block_modal.they_cant_follow": "Никого от този сървър не може да ви последва.",
"domain_block_modal.they_wont_know": "Няма да узнаят, че са били блокирани.",
"domain_block_modal.title": "Блокирате ли домейн?",
"domain_block_modal.you_will_lose_followers": "Всичките ви последователи от този сървър ще се премахнат.",
"domain_block_modal.you_wont_see_posts": "Няма да виждате публикации или известия от потребителите на този сървър.",
"domain_pill.activitypub_lets_connect": "Позволява ви да се свързвате и взаимодействате с хора не само в Mastodon, но и през различни социални приложения.",
"domain_pill.activitypub_like_language": "ActivityPub е като език на Mastodon, говорещ с други социални мрежи.",
@ -419,8 +418,6 @@
"keyboard_shortcuts.unfocus": "Разфокусиране на текстовото поле за съставяне/търсене",
"keyboard_shortcuts.up": "Преместване нагоре в списъка",
"lightbox.close": "Затваряне",
"lightbox.compress": "Свиване на полето за преглед на образи",
"lightbox.expand": "Разгъване на полето за преглед на образи",
"lightbox.next": "Напред",
"lightbox.previous": "Назад",
"limited_account_hint.action": "Показване на профила въпреки това",
@ -540,8 +537,6 @@
"notifications.column_settings.admin.report": "Нови доклади:",
"notifications.column_settings.admin.sign_up": "Нови регистрации:",
"notifications.column_settings.alert": "Известия на работния плот",
"notifications.column_settings.beta.category": "Експериментални функции",
"notifications.column_settings.beta.grouping": "Групови известия",
"notifications.column_settings.favourite": "Любими:",
"notifications.column_settings.filter_bar.advanced": "Показване на всички категории",
"notifications.column_settings.filter_bar.category": "Лента за бърз филтър",

View file

@ -338,8 +338,6 @@
"keyboard_shortcuts.unfocus": "Difokus an dachenn testenn/klask",
"keyboard_shortcuts.up": "Pignat er roll",
"lightbox.close": "Serriñ",
"lightbox.compress": "Bihanaat boest hewel ar skeudenn",
"lightbox.expand": "Ledanaat boest hewel ar skeudenn",
"lightbox.next": "Da-heul",
"lightbox.previous": "A-raok",
"limited_account_hint.action": "Diskouez an aelad memes tra",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Ningú d'aquest servidor us pot seguir.",
"domain_block_modal.they_wont_know": "No sabran que són blocats.",
"domain_block_modal.title": "Bloquem el domini?",
"domain_block_modal.you_will_lose_followers": "S'eliminaran tots els vostres seguidors d'aquest servidor.",
"domain_block_modal.you_will_lose_num_followers": "Perdreu {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidors}} i {followingCount, plural, one {{followingCountDisplay} persona} other {{followingCountDisplay} persones}} que seguiu.",
"domain_block_modal.you_wont_see_posts": "No veureu ni les publicacions ni les notificacions dels usuaris d'aquest servidor.",
"domain_pill.activitypub_lets_connect": "Us permet connectar i interactuar amb persones a Mastodon i també a d'altres apps socials.",
"domain_pill.activitypub_like_language": "ActivityPub és el llenguatge que Mastodon parla amb altres xarxes socials.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Descentra l'àrea de composició de text/cerca",
"keyboard_shortcuts.up": "Apuja a la llista",
"lightbox.close": "Tanca",
"lightbox.compress": "Comprimeix el quadre de visualització dimatge",
"lightbox.expand": "Amplia el quadre de visualització dimatge",
"lightbox.next": "Següent",
"lightbox.previous": "Anterior",
"lightbox.zoom_in": "Amplia fins a la mida real",
"lightbox.zoom_out": "Amplia fins a encabir",
"limited_account_hint.action": "Mostra el perfil de totes maneres",
"limited_account_hint.title": "Aquest perfil l'han amagat els moderadors de {domain}.",
"link_preview.author": "Per {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Nous informes:",
"notifications.column_settings.admin.sign_up": "Registres nous:",
"notifications.column_settings.alert": "Notificacions d'escriptori",
"notifications.column_settings.beta.category": "Característiques experimentals",
"notifications.column_settings.beta.grouping": "Notificacions de grup",
"notifications.column_settings.favourite": "Favorits:",
"notifications.column_settings.filter_bar.advanced": "Mostra totes les categories",
"notifications.column_settings.filter_bar.category": "Barra ràpida de filtres",
@ -789,6 +787,7 @@
"status.edit": "Edita",
"status.edited": "Darrera edició {date}",
"status.edited_x_times": "Editat {count, plural, one {{count} vegada} other {{count} vegades}}",
"status.embed": "Obté el codi encastat",
"status.favourite": "Favorit",
"status.favourites": "{count, plural, one {favorit} other {favorits}}",
"status.filter": "Filtra aquest tut",

View file

@ -335,8 +335,6 @@
"keyboard_shortcuts.unfocus": "بۆ دروستکردنی ناوچەی دەق/گەڕان",
"keyboard_shortcuts.up": "بۆ ئەوەی لە لیستەکەدا بڕۆیت",
"lightbox.close": "دابخە",
"lightbox.compress": "سندوقی نیشاندانی وێنە بپەستێنە",
"lightbox.expand": "فراوانکردنی سندوقی بینینی وێنە",
"lightbox.next": "داهاتوو",
"lightbox.previous": "پێشوو",
"limited_account_hint.action": "بەهەر حاڵ پڕۆفایلی پیشان بدە",

View file

@ -196,8 +196,6 @@
"keyboard_shortcuts.unfocus": "ùn fucalizà più l'area di testu",
"keyboard_shortcuts.up": "cullà indè a lista",
"lightbox.close": "Chjudà",
"lightbox.compress": "Cumprime a finestra d'affissera di i ritratti",
"lightbox.expand": "Ingrandà a finestra d'affissera di i ritratti",
"lightbox.next": "Siguente",
"lightbox.previous": "Pricidente",
"lists.account.add": "Aghjunghje à a lista",

View file

@ -220,7 +220,6 @@
"domain_block_modal.they_cant_follow": "Nikdo z tohoto serveru vás nemůže sledovat.",
"domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován*a.",
"domain_block_modal.title": "Blokovat doménu?",
"domain_block_modal.you_will_lose_followers": "Všichni vaši sledující z tohoto serveru budou odstraněni.",
"domain_block_modal.you_wont_see_posts": "Neuvidíte příspěvky ani upozornění od uživatelů z tohoto serveru.",
"domain_pill.activitypub_lets_connect": "Umožňuje vám spojit se a komunikovat s lidmi nejen na Mastodonu, ale i s dalšími sociálními aplikacemi.",
"domain_pill.activitypub_like_language": "ActivityPub je jako jazyk, kterým Mastodon mluví s jinými sociálními sítěmi.",
@ -410,8 +409,6 @@
"keyboard_shortcuts.unfocus": "Zrušit zaměření na nový příspěvek/hledání",
"keyboard_shortcuts.up": "Posunout v seznamu nahoru",
"lightbox.close": "Zavřít",
"lightbox.compress": "Sbalit pole zobrazení obrázku",
"lightbox.expand": "Rozbalit pole zobrazení obrázku",
"lightbox.next": "Další",
"lightbox.previous": "Předchozí",
"limited_account_hint.action": "Přesto profil zobrazit",
@ -509,8 +506,6 @@
"notifications.column_settings.admin.report": "Nová hlášení:",
"notifications.column_settings.admin.sign_up": "Nové registrace:",
"notifications.column_settings.alert": "Oznámení na počítači",
"notifications.column_settings.beta.category": "Experimentální funkce",
"notifications.column_settings.beta.grouping": "Seskupit notifikace",
"notifications.column_settings.favourite": "Oblíbené:",
"notifications.column_settings.filter_bar.advanced": "Zobrazit všechny kategorie",
"notifications.column_settings.filter_bar.category": "Panel rychlého filtrování",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Ni all neb o'r gweinydd hwn eich dilyn.",
"domain_block_modal.they_wont_know": "Fyddan nhw ddim yn gwybod eu bod wedi cael eu blocio.",
"domain_block_modal.title": "Blocio parth?",
"domain_block_modal.you_will_lose_followers": "Bydd eich holl ddilynwyr o'r gweinydd hwn yn cael eu tynnu.",
"domain_block_modal.you_wont_see_posts": "Fyddwch chi ddim yn gweld postiadau na hysbysiadau gan ddefnyddwyr ar y gweinydd hwn.",
"domain_pill.activitypub_lets_connect": "Mae'n caniatáu ichi gysylltu a rhyngweithio â phobl nid yn unig ar Mastodon, ond ar draws gwahanol apiau cymdeithasol hefyd.",
"domain_pill.activitypub_like_language": "Mae ActivityPub fel yr iaith y mae Mastodon yn ei siarad â rhwydweithiau cymdeithasol eraill.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Dad-ffocysu ardal cyfansoddi testun/chwilio",
"keyboard_shortcuts.up": "Symud yn uwch yn y rhestr",
"lightbox.close": "Cau",
"lightbox.compress": "Cywasgu blwch gweld delwedd",
"lightbox.expand": "Ehangu blwch gweld delwedd",
"lightbox.next": "Nesaf",
"lightbox.previous": "Blaenorol",
"lightbox.zoom_in": "Chwyddo i faint gwirioneddol",
"lightbox.zoom_out": "Chwyddo i ffitio",
"limited_account_hint.action": "Dangos y proffil beth bynnag",
"limited_account_hint.title": "Mae'r proffil hwn wedi cael ei guddio gan gymedrolwyr {domain}.",
"link_preview.author": "Gan {name}",
@ -559,8 +558,6 @@
"notifications.column_settings.admin.report": "Adroddiadau newydd:",
"notifications.column_settings.admin.sign_up": "Cofrestriadau newydd:",
"notifications.column_settings.alert": "Hysbysiadau bwrdd gwaith",
"notifications.column_settings.beta.category": "Nodweddion arbrofol",
"notifications.column_settings.beta.grouping": "Grŵpio hysbysiadau",
"notifications.column_settings.favourite": "Ffefrynnau:",
"notifications.column_settings.filter_bar.advanced": "Dangos pob categori",
"notifications.column_settings.filter_bar.category": "Bar hidlo cyflym",
@ -789,6 +786,7 @@
"status.edit": "Golygu",
"status.edited": "Golygwyd ddiwethaf {date}",
"status.edited_x_times": "Golygwyd {count, plural, one {count} two {count} other {{count} gwaith}}",
"status.embed": "Cael y cod mewnblannu",
"status.favourite": "Ffafrio",
"status.favourites": "{count, plural, one {ffefryn} other {ffefryn}}",
"status.filter": "Hidlo'r postiad hwn",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Ingen fra denne server kan følge dig.",
"domain_block_modal.they_wont_know": "Vedkommende ser ikke den aktive blokering.",
"domain_block_modal.title": "Blokér domæne?",
"domain_block_modal.you_will_lose_followers": "Alle følgerne fra denne server fjernes.",
"domain_block_modal.you_will_lose_num_followers": "Man vil miste {followersCount, plural, one {{followersCountDisplay} følger} other {{followersCountDisplay} følgere}} og {followingCount, plural, one {{followingCountDisplay} person, man følger} other {{followingCountDisplay} personer, man følger}}.",
"domain_block_modal.you_wont_see_posts": "Indlæg eller notifikationer fra brugere på denne server vises ikke.",
"domain_pill.activitypub_lets_connect": "Det muliggør at komme i forbindelse og interagere med folk ikke kun på Mastodon, men også på tværs af forskellige sociale apps.",
"domain_pill.activitypub_like_language": "ActivityPub er \"sproget\", Mastodon taler med andre sociale netværk.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Fjern fokus fra tekstskrivningsområde/søgning",
"keyboard_shortcuts.up": "Flyt opad på listen",
"lightbox.close": "Luk",
"lightbox.compress": "Komprimér billedvisningsfelt",
"lightbox.expand": "Udvid billedvisningsfelt",
"lightbox.next": "Næste",
"lightbox.previous": "Forrige",
"lightbox.zoom_in": "Zoom til faktisk størrelse",
"lightbox.zoom_out": "Zoom for at tilpasse",
"limited_account_hint.action": "Vis profil alligevel",
"limited_account_hint.title": "Denne profil er blevet skjult af {domain}-moderatorerne.",
"link_preview.author": "Af {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Nye anmeldelser:",
"notifications.column_settings.admin.sign_up": "Nye tilmeldinger:",
"notifications.column_settings.alert": "Computernotifikationer",
"notifications.column_settings.beta.category": "Eksperimentelle funktioner",
"notifications.column_settings.beta.grouping": "Gruppér notifikationer",
"notifications.column_settings.favourite": "Favoritter:",
"notifications.column_settings.filter_bar.advanced": "Vis alle kategorier",
"notifications.column_settings.filter_bar.category": "Hurtigfiltreringsbjælke",

View file

@ -155,7 +155,7 @@
"compose_form.lock_disclaimer.lock": "geschützt",
"compose_form.placeholder": "Was gibts Neues?",
"compose_form.poll.duration": "Umfragedauer",
"compose_form.poll.multiple": "Mul­ti­ple-Choice",
"compose_form.poll.multiple": "Mehrfachauswahl",
"compose_form.poll.option_placeholder": "Option {number}",
"compose_form.poll.single": "Einfachauswahl",
"compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben",
@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Niemand von diesem Server wird dir folgen können.",
"domain_block_modal.they_wont_know": "Es wird nicht erkennbar sein, dass diese Domain blockiert wurde.",
"domain_block_modal.title": "Domain blockieren?",
"domain_block_modal.you_will_lose_followers": "Alle Follower von diesem Server werden entfernt.",
"domain_block_modal.you_will_lose_num_followers": "Du wirst {followersCount, plural, one {{followersCountDisplay} Follower} other {{followersCountDisplay} Follower}} verlieren und {followingCount, plural, one {{followingCountDisplay} Profil} other {{followingCountDisplay} Profilen}} entfolgen.",
"domain_block_modal.you_wont_see_posts": "Du wirst keine Beiträge oder Benachrichtigungen von Profilen auf diesem Server sehen.",
"domain_pill.activitypub_lets_connect": "Somit kannst du dich nicht nur auf Mastodon mit Leuten verbinden und mit ihnen interagieren, sondern über alle sozialen Apps hinweg.",
"domain_pill.activitypub_like_language": "ActivityPub ist sozusagen die Sprache, die Mastodon mit anderen sozialen Netzwerken spricht.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Eingabefeld/Suche nicht mehr fokussieren",
"keyboard_shortcuts.up": "Ansicht nach oben bewegen",
"lightbox.close": "Schließen",
"lightbox.compress": "Bildansicht verkleinern",
"lightbox.expand": "Bildansicht vergrößern",
"lightbox.next": "Vor",
"lightbox.previous": "Zurück",
"lightbox.zoom_in": "In Originalgröße anzeigen",
"lightbox.zoom_out": "In angepasster Größe anzeigen",
"limited_account_hint.action": "Profil trotzdem anzeigen",
"limited_account_hint.title": "Dieses Profil wurde von den Moderator*innen von {domain} ausgeblendet.",
"link_preview.author": "Von {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Neue Meldungen:",
"notifications.column_settings.admin.sign_up": "Neue Registrierungen:",
"notifications.column_settings.alert": "Desktop-Benachrichtigungen",
"notifications.column_settings.beta.category": "Experimentelle Funktionen",
"notifications.column_settings.beta.grouping": "Benachrichtigungen gruppieren",
"notifications.column_settings.favourite": "Favoriten:",
"notifications.column_settings.filter_bar.advanced": "Alle Filterkategorien anzeigen",
"notifications.column_settings.filter_bar.category": "Filterleiste",
@ -777,7 +775,7 @@
"status.admin_domain": "{domain} moderieren",
"status.admin_status": "Beitrag moderieren",
"status.block": "@{name} blockieren",
"status.bookmark": "Beitrag als Lesezeichen setzen",
"status.bookmark": "Lesezeichen setzen",
"status.cancel_reblog_private": "Beitrag nicht mehr teilen",
"status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
"status.continued_thread": "Fortgeführter Thread",

View file

@ -97,6 +97,8 @@
"block_modal.title": "Αποκλεισμός χρήστη;",
"block_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.",
"boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις την επόμενη φορά",
"boost_modal.reblog": "Ενίσχυση ανάρτησης;",
"boost_modal.undo_reblog": "Αναίρεση ενίσχυσης;",
"bundle_column_error.copy_stacktrace": "Αντιγραφή αναφοράς σφάλματος",
"bundle_column_error.error.body": "Δεν ήταν δυνατή η απόδοση της σελίδας που ζήτησες. Μπορεί να οφείλεται σε σφάλμα στον κώδικά μας ή σε πρόβλημα συμβατότητας του προγράμματος περιήγησης.",
"bundle_column_error.error.title": "Ωχ όχι!",
@ -192,6 +194,8 @@
"confirmations.unfollow.confirm": "Άρση ακολούθησης",
"confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};",
"confirmations.unfollow.title": "Άρση ακολούθησης;",
"content_warning.hide": "Απόκρυψη ανάρτησης",
"content_warning.show": "Εμφάνιση ούτως ή άλλως",
"conversation.delete": "Διαγραφή συζήτησης",
"conversation.mark_as_read": "Σήμανση ως αναγνωσμένο",
"conversation.open": "Προβολή συνομιλίας",
@ -217,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Κανείς από αυτόν τον διακομιστή δεν μπορεί να σε ακολουθήσει.",
"domain_block_modal.they_wont_know": "Δεν θα ξέρουν ότι έχουν αποκλειστεί.",
"domain_block_modal.title": "Αποκλεισμός τομέα;",
"domain_block_modal.you_will_lose_followers": "Οι ακόλουθοί σου από αυτόν τον διακομιστή θα αφαιρεθούν.",
"domain_block_modal.you_wont_see_posts": "Δεν θα βλέπεις αναρτήσεις ή ειδοποιήσεις από χρήστες σε αυτόν το διακομιστή.",
"domain_pill.activitypub_lets_connect": "Σού επιτρέπει να συνδεθείς και να αλληλεπιδράσεις με τους ανθρώπους όχι μόνο στο Mastodon, αλλά και σε διαφορετικές κοινωνικές εφαρμογές.",
"domain_pill.activitypub_like_language": "Το ActivityPub είναι σαν τη γλώσσα Mastodon μιλάει με άλλα κοινωνικά δίκτυα.",
@ -299,6 +302,7 @@
"filter_modal.select_filter.subtitle": "Χρησιμοποιήστε μια υπάρχουσα κατηγορία ή δημιουργήστε μια νέα",
"filter_modal.select_filter.title": "Φιλτράρισμα αυτής της ανάρτησης",
"filter_modal.title.status": "Φιλτράρισμα μιας ανάρτησης",
"filter_warning.matches_filter": "Ταιριάζει με το φίλτρο “{title}”",
"filtered_notifications_banner.pending_requests": "Από {count, plural, =0 {κανένα} one {ένα άτομο} other {# άτομα}} που μπορεί να ξέρεις",
"filtered_notifications_banner.title": "Φιλτραρισμένες ειδοποιήσεις",
"firehose.all": "Όλα",
@ -427,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Αποεστίαση του πεδίου σύνθεσης/αναζήτησης",
"keyboard_shortcuts.up": "Μετακίνηση προς τα πάνω στη λίστα",
"lightbox.close": "Κλείσιμο",
"lightbox.compress": "Συμπίεση πλαισίου προβολής εικόνας",
"lightbox.expand": "Ανάπτυξη πλαισίου εμφάνισης εικόνας",
"lightbox.next": "Επόμενο",
"lightbox.previous": "Προηγούμενο",
"lightbox.zoom_in": "Εστίαση στο πραγματικό μέγεθος",
"lightbox.zoom_out": "Εστίαση για προσαρμογή",
"limited_account_hint.action": "Εμφάνιση προφίλ ούτως ή άλλως",
"limited_account_hint.title": "Αυτό το προφίλ έχει αποκρυφτεί από τους διαχειριστές του διακομιστή {domain}.",
"link_preview.author": "Από {name}",
@ -452,6 +456,7 @@
"lists.subheading": "Οι λίστες σου",
"load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}",
"loading_indicator.label": "Φόρτωση…",
"media_gallery.hide": "Απόκρυψη",
"moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.",
"mute_modal.hide_from_notifications": "Απόκρυψη από ειδοποιήσεις",
"mute_modal.hide_options": "Απόκρυψη επιλογών",
@ -463,6 +468,7 @@
"mute_modal.you_wont_see_mentions": "Δε θα βλέπεις τις αναρτήσεις που τον αναφέρουν.",
"mute_modal.you_wont_see_posts": "Μπορεί ακόμα να δει τις αναρτήσεις σου, αλλά δε θα βλέπεις τις δικές του.",
"navigation_bar.about": "Σχετικά με",
"navigation_bar.administration": "Διαχείριση",
"navigation_bar.advanced_interface": "Άνοιγμα σε προηγμένη διεπαφή ιστού",
"navigation_bar.blocks": "Αποκλεισμένοι χρήστες",
"navigation_bar.bookmarks": "Σελιδοδείκτες",
@ -479,6 +485,7 @@
"navigation_bar.follows_and_followers": "Ακολουθείς και σε ακολουθούν",
"navigation_bar.lists": "Λίστες",
"navigation_bar.logout": "Αποσύνδεση",
"navigation_bar.moderation": "Συντονισμός",
"navigation_bar.mutes": "Αποσιωπημένοι χρήστες",
"navigation_bar.opened_in_classic_interface": "Δημοσιεύσεις, λογαριασμοί και άλλες συγκεκριμένες σελίδες ανοίγονται από προεπιλογή στην κλασική διεπαφή ιστού.",
"navigation_bar.personal": "Προσωπικά",
@ -551,8 +558,6 @@
"notifications.column_settings.admin.report": "Νέες αναφορές:",
"notifications.column_settings.admin.sign_up": "Νέες εγγραφές:",
"notifications.column_settings.alert": "Ειδοποιήσεις επιφάνειας εργασίας",
"notifications.column_settings.beta.category": "Πειραματικές λειτουργίες",
"notifications.column_settings.beta.grouping": "Ομαδοποίηση ειδοποιήσεων",
"notifications.column_settings.favourite": "Αγαπημένα:",
"notifications.column_settings.filter_bar.advanced": "Εμφάνιση όλων των κατηγοριών",
"notifications.column_settings.filter_bar.category": "Μπάρα γρήγορου φίλτρου",
@ -772,6 +777,7 @@
"status.bookmark": "Σελιδοδείκτης",
"status.cancel_reblog_private": "Ακύρωση ενίσχυσης",
"status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί",
"status.continued_thread": "Συνεχιζόμενο νήματος",
"status.copy": "Αντιγραφή συνδέσμου ανάρτησης",
"status.delete": "Διαγραφή",
"status.detailed_status": "Προβολή λεπτομερούς συζήτησης",
@ -780,6 +786,7 @@
"status.edit": "Επεξεργασία",
"status.edited": "Τελευταία επεξεργασία {date}",
"status.edited_x_times": "Επεξεργάστηκε {count, plural, one {{count} φορά} other {{count} φορές}}",
"status.embed": "Απόκτηση κώδικα ενσωμάτωσης",
"status.favourite": "Αγαπημένα",
"status.favourites": "{count, plural, one {# αγαπημένο} other {# αγαπημένα}}",
"status.filter": "Φιλτράρισμα αυτής της ανάρτησης",
@ -804,6 +811,7 @@
"status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.",
"status.redraft": "Σβήσε & ξαναγράψε",
"status.remove_bookmark": "Αφαίρεση σελιδοδείκτη",
"status.replied_in_thread": "Απαντήθηκε σε νήμα",
"status.replied_to": "Απάντησε στον {name}",
"status.reply": "Απάντησε",
"status.replyAll": "Απάντησε στο νήμα συζήτησης",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Nobody from this server can follow you.",
"domain_block_modal.they_wont_know": "They won't know they've been blocked.",
"domain_block_modal.title": "Block domain?",
"domain_block_modal.you_will_lose_followers": "All your followers from this server will be removed.",
"domain_block_modal.you_wont_see_posts": "You won't see posts or notifications from users on this server.",
"domain_pill.activitypub_lets_connect": "It lets you connect and interact with people not just on Mastodon, but across different social apps too.",
"domain_pill.activitypub_like_language": "ActivityPub is like the language Mastodon speaks with other social networks.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "Move up in the list",
"lightbox.close": "Close",
"lightbox.compress": "Compress image view box",
"lightbox.expand": "Expand image view box",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
"lightbox.zoom_in": "Zoom to actual size",
"lightbox.zoom_out": "Zoom to fit",
"limited_account_hint.action": "Show profile anyway",
"limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.",
"link_preview.author": "By {name}",
@ -559,8 +558,6 @@
"notifications.column_settings.admin.report": "New reports:",
"notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.beta.category": "Experimental features",
"notifications.column_settings.beta.grouping": "Group notifications",
"notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
"notifications.column_settings.filter_bar.category": "Quick filter bar",
@ -789,6 +786,7 @@
"status.edit": "Edit",
"status.edited": "Last edited {date}",
"status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}",
"status.embed": "Get embed code",
"status.favourite": "Favourite",
"status.favourites": "{count, plural, one {favorite} other {favorites}}",
"status.filter": "Filter this post",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Nobody from this server can follow you.",
"domain_block_modal.they_wont_know": "They won't know they've been blocked.",
"domain_block_modal.title": "Block domain?",
"domain_block_modal.you_will_lose_followers": "All your followers from this server will be removed.",
"domain_block_modal.you_will_lose_num_followers": "You will lose {followersCount, plural, one {{followersCountDisplay} follower} other {{followersCountDisplay} followers}} and {followingCount, plural, one {{followingCountDisplay} person you follow} other {{followingCountDisplay} people you follow}}.",
"domain_block_modal.you_wont_see_posts": "You won't see posts or notifications from users on this server.",
"domain_pill.activitypub_lets_connect": "It lets you connect and interact with people not just on Mastodon, but across different social apps too.",
"domain_pill.activitypub_like_language": "ActivityPub is like the language Mastodon speaks with other social networks.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Unfocus compose textarea/search",
"keyboard_shortcuts.up": "Move up in the list",
"lightbox.close": "Close",
"lightbox.compress": "Compress image view box",
"lightbox.expand": "Expand image view box",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
"lightbox.zoom_in": "Zoom to actual size",
"lightbox.zoom_out": "Zoom to fit",
"limited_account_hint.action": "Show profile anyway",
"limited_account_hint.title": "This profile has been hidden by the moderators of {domain}.",
"link_preview.author": "By {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "New reports:",
"notifications.column_settings.admin.sign_up": "New sign-ups:",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.beta.category": "Experimental features",
"notifications.column_settings.beta.grouping": "Group notifications",
"notifications.column_settings.favourite": "Favorites:",
"notifications.column_settings.filter_bar.advanced": "Display all categories",
"notifications.column_settings.filter_bar.category": "Quick filter bar",

View file

@ -97,6 +97,8 @@
"block_modal.title": "Ĉu bloki uzanton?",
"block_modal.you_wont_see_mentions": "Vi ne vidos afiŝojn, ke mencii ilin.",
"boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje",
"boost_modal.reblog": "Ĉu diskonigi afiŝon?",
"boost_modal.undo_reblog": "Ĉu ĉesi diskonigi afiŝon?",
"bundle_column_error.copy_stacktrace": "Kopii la eraran raporton",
"bundle_column_error.error.body": "La petita paĝo ne povas redonitis. Eble estas eraro.",
"bundle_column_error.error.title": "Ho, ve!",
@ -188,8 +190,12 @@
"confirmations.redraft.title": "Ĉu forigi kaj redakcii afiŝon?",
"confirmations.reply.confirm": "Respondi",
"confirmations.reply.message": "Respondi nun anstataŭigos la skribatan afiŝon. Ĉu vi certas, ke vi volas daŭrigi?",
"confirmations.reply.title": "Ĉu superskribi afiŝon?",
"confirmations.unfollow.confirm": "Ne plu sekvi",
"confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?",
"confirmations.unfollow.title": "Ĉu ĉesi sekvi uzanton?",
"content_warning.hide": "Kaŝi afiŝon",
"content_warning.show": "Montri ĉiukaze",
"conversation.delete": "Forigi konversacion",
"conversation.mark_as_read": "Marki legita",
"conversation.open": "Vidi konversacion",
@ -209,6 +215,27 @@
"dismissable_banner.explore_statuses": "Ĉi tioj estas afiŝoj de socia reto kiu populariĝas hodiau.",
"dismissable_banner.explore_tags": "Ĉi tiuj kradvostoj populariĝas en ĉi tiu kaj aliaj serviloj en la malcentraliza reto nun.",
"dismissable_banner.public_timeline": "Ĉi tioj estas plej lastaj publikaj afiŝoj de personoj ĉe socia reto kiu personoj ĉe {domain} sekvas.",
"domain_block_modal.block": "Bloki servilon",
"domain_block_modal.block_account_instead": "Bloki @{name} anstataŭe",
"domain_block_modal.they_can_interact_with_old_posts": "Homoj de ĉi tiu servilo povas interagi kun viaj malnovaj afiŝoj.",
"domain_block_modal.they_cant_follow": "Neniu el ĉi tiu servilo povas sekvi vin.",
"domain_block_modal.they_wont_know": "Ili ne scios, ke ili estas blokitaj.",
"domain_block_modal.title": "Ĉu bloki la domajnon?",
"domain_block_modal.you_will_lose_num_followers": "Vi perdos {followersCount, plural, one {{followersCountDisplay} sekvanton} other {{followersCountDisplay} sekvantojn}} kaj {followingCount, plural, one {{followingCountDisplay} homon, kiu vi sekvas} other {{followingCountDisplay} homojn, kiuj vi sekvas}}.",
"domain_block_modal.you_wont_see_posts": "Vi ne vidos afiŝojn aŭ sciigojn de uzantoj sur ĉi tiu servilo.",
"domain_pill.activitypub_lets_connect": "Ĝi ebligas vin konekti kaj interagi kun homoj ne nur sur Mastodon, sed ankaŭ tra diversaj sociaj apoj.",
"domain_pill.activitypub_like_language": "ActivityPub estas kiel la lingvo kiun Mastodon parolas kun aliaj sociaj retoj.",
"domain_pill.server": "Servilo",
"domain_pill.their_handle": "Ilia identigo:",
"domain_pill.their_server": "Ilia cifereca hejmo, kie ĉiuj iliaj afiŝoj loĝas.",
"domain_pill.their_username": "Ilia unika identigilo sur ilia servilo. Eblas trovi uzantojn kun la sama uzantnomo sur malsamaj serviloj.",
"domain_pill.username": "Uzantnomo",
"domain_pill.whats_in_a_handle": "Kio estas en identigo?",
"domain_pill.who_they_are": "Ĉar identigoj diras, kiu iu estas kaj kie ili estas, vi povas interagi kun homoj tra la socia reto de <button>ActivityPub-funkciigitaj platformoj</button>.",
"domain_pill.who_you_are": "Ĉar via identigo diras kiu vi estas kaj kie vi estas, homoj povas interagi kun vi tra la socia reto de <button>ActivityPub-funkciigitaj platformoj</button>.",
"domain_pill.your_handle": "Via identigo:",
"domain_pill.your_server": "Via cifereca hejmo, kie loĝas ĉiuj viaj afiŝoj. Ĉu vi ne ŝatas ĉi tiun? Transloku servilojn iam ajn kaj alportu ankaŭ viajn sekvantojn.",
"domain_pill.your_username": "Via unika identigilo sur ĉi tiu servilo. Eblas trovi uzantojn kun la sama uzantnomo sur malsamaj serviloj.",
"embed.instructions": "Enkorpigu ĉi tiun afiŝon en vian retejon per kopio de la suba kodo.",
"embed.preview": "Ĝi aperos tiel:",
"emoji_button.activity": "Agadoj",
@ -245,6 +272,7 @@
"empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn afiŝojn, ili aperos ĉi tie.",
"empty_column.lists": "Vi ankoraŭ ne havas liston. Kiam vi kreos iun, ĝi aperos ĉi tie.",
"empty_column.mutes": "Vi ne ankoraŭ silentigis iun uzanton.",
"empty_column.notification_requests": "Ĉio klara! Estas nenio tie ĉi. Kiam vi ricevas novajn sciigojn, ili aperos ĉi tie laŭ viaj agordoj.",
"empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.",
"empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj serviloj por plenigi la publikan tempolinion",
"error.unexpected_crash.explanation": "Pro eraro en nia kodo, aŭ problemo de kongruo en via retumilo, ĉi tiu paĝo ne povis esti montrata ĝuste.",
@ -275,12 +303,30 @@
"filter_modal.select_filter.subtitle": "Uzu ekzistantan kategorion aŭ kreu novan",
"filter_modal.select_filter.title": "Filtri ĉi tiun afiŝon",
"filter_modal.title.status": "Filtri mesaĝon",
"filter_warning.matches_filter": "Filtrilo de kongruoj “{title}”",
"filtered_notifications_banner.pending_requests": "El {count, plural, =0 {neniu} one {unu persono} other {# homoj}} vi eble konas",
"filtered_notifications_banner.title": "Filtritaj sciigoj",
"firehose.all": "Ĉiuj",
"firehose.local": "Ĉi tiu servilo",
"firehose.remote": "Aliaj serviloj",
"follow_request.authorize": "Rajtigi",
"follow_request.reject": "Rifuzi",
"follow_requests.unlocked_explanation": "Kvankam via konto ne estas ŝlosita, la dungitaro de {domain} opinias, ke vi eble volas revizii petojn pri sekvado de ĉi tiuj kontoj permane.",
"follow_suggestions.curated_suggestion": "Elekto de stabo",
"follow_suggestions.dismiss": "Ne montri denove",
"follow_suggestions.featured_longer": "Mane elektita de la teamo de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populara inter homoj, kiujn vi sekvas",
"follow_suggestions.hints.featured": "Ĉi tiu profilo estis mane elektita de la teamo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Ĉi tiu profilo estas populara inter la homoj, kiujn vi sekvas.",
"follow_suggestions.hints.most_followed": "Ĉi tiu profilo estas unu el la plej sekvataj en {domain}.",
"follow_suggestions.hints.most_interactions": "Ĉi tiu profilo lastatempe ricevis multe da atento sur {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Ĉi tiu profilo similas al la profiloj kiujn vi plej lastatempe sekvis.",
"follow_suggestions.personalized_suggestion": "Agordita propono",
"follow_suggestions.popular_suggestion": "Popularaj proponoj",
"follow_suggestions.popular_suggestion_longer": "Populara en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Simile al profiloj, kiujn vi lastatempe sekvis",
"follow_suggestions.view_all": "Vidi ĉiujn",
"follow_suggestions.who_to_follow": "Kiun sekvi",
"followed_tags": "Sekvataj kradvortoj",
"footer.about": "Pri",
"footer.directory": "Profilujo",
@ -307,6 +353,14 @@
"hashtag.follow": "Sekvi la kradvorton",
"hashtag.unfollow": "Ne plu sekvi la kradvorton",
"hashtags.and_other": "…kaj {count, plural,other {# pli}}",
"hints.profiles.followers_may_be_missing": "Sekvantoj por ĉi tiu profilo eble mankas.",
"hints.profiles.follows_may_be_missing": "Sekvatoj de ĉi tiu profilo eble mankas.",
"hints.profiles.posts_may_be_missing": "Iuj afiŝoj de ĉi tiu profilo eble mankas.",
"hints.profiles.see_more_followers": "Vidi pli da sekvantoj sur {domain}",
"hints.profiles.see_more_follows": "Vidi pli da sekvatoj sur {domain}",
"hints.profiles.see_more_posts": "Vidi pli da afiŝoj sur {domain}",
"hints.threads.replies_may_be_missing": "Respondoj de aliaj serviloj eble mankas.",
"hints.threads.see_more": "Vidi pli da respondoj sur {domain}",
"home.column_settings.show_reblogs": "Montri diskonigojn",
"home.column_settings.show_replies": "Montri respondojn",
"home.hide_announcements": "Kaŝi la anoncojn",
@ -314,6 +368,17 @@
"home.pending_critical_update.link": "Vidi ĝisdatigojn",
"home.pending_critical_update.title": "Kritika sekurĝisdatigo estas disponebla!",
"home.show_announcements": "Montri anoncojn",
"ignore_notifications_modal.disclaimer": "Mastodon ne povas informi uzantojn, ke vi ignoris iliajn sciigojn. Ignori sciigojn ne malhelpos la mesaĝojn mem esti senditaj.",
"ignore_notifications_modal.filter_instead": "Filtri anstataŭe",
"ignore_notifications_modal.filter_to_act_users": "Vi ankoraŭ povos akcepti, malakcepti aŭ raporti uzantojn",
"ignore_notifications_modal.filter_to_avoid_confusion": "Filtrado helpas eviti eblan konfuzon",
"ignore_notifications_modal.filter_to_review_separately": "Vi povas revizii filtritajn sciigojn aparte",
"ignore_notifications_modal.ignore": "Ignori sciigojn",
"ignore_notifications_modal.limited_accounts_title": "Ĉu ignori sciigojn de moderigitaj kontoj?",
"ignore_notifications_modal.new_accounts_title": "Ĉu ignori sciigojn de novaj kontoj?",
"ignore_notifications_modal.not_followers_title": "Ĉu ignori sciigojn de homoj, kiuj ne sekvas vin?",
"ignore_notifications_modal.not_following_title": "Ĉu ignori sciigojn de homoj, kiujn vi ne sekvas?",
"ignore_notifications_modal.private_mentions_title": "Ĉu ignori sciigojn de nepetitaj privataj mencioj?",
"interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumiti ĉi tiun afiŝon por sciigi la afiŝanton ke vi aprezigas ŝin kaj konservas por la estonteco.",
"interaction_modal.description.follow": "Kun konto ĉe Mastodon, vi povos sekvi {name} por vidi ties mesaĝojn en via hejmo.",
"interaction_modal.description.reblog": "Kun konto ĉe Mastodon, vi povas diskonigi ĉi tiun afiŝon, por ke viaj propraj sekvantoj vidu ĝin.",
@ -367,13 +432,15 @@
"keyboard_shortcuts.unfocus": "malenfokusigi la tekstujon aŭ la serĉilon",
"keyboard_shortcuts.up": "iri supren en la listo",
"lightbox.close": "Fermi",
"lightbox.compress": "Kunpremi bildan vidkeston",
"lightbox.expand": "Pligrandigi bildan vidkeston",
"lightbox.next": "Antaŭen",
"lightbox.previous": "Malantaŭen",
"lightbox.zoom_in": "Zomi al reala grandeco",
"lightbox.zoom_out": "Zomi por konveni",
"limited_account_hint.action": "Montru profilon ĉiukaze",
"limited_account_hint.title": "La profilo estas kaŝita de la moderigantoj de {domain}.",
"link_preview.author": "De {name}",
"link_preview.more_from_author": "Pli de {name}",
"link_preview.shares": "{count, plural, one {{counter} afiŝo} other {{counter} afiŝoj}}",
"lists.account.add": "Aldoni al la listo",
"lists.account.remove": "Forigi de la listo",
"lists.delete": "Forigi la liston",
@ -390,8 +457,19 @@
"lists.subheading": "Viaj listoj",
"load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}",
"loading_indicator.label": "Ŝargado…",
"media_gallery.hide": "Kaŝi",
"moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.",
"mute_modal.hide_from_notifications": "Kaŝi de sciigoj",
"mute_modal.hide_options": "Kaŝi agordojn",
"mute_modal.indefinite": "Ĝis mi malsilentas ilin",
"mute_modal.show_options": "Montri agordojn",
"mute_modal.they_can_mention_and_follow": "Ili povas mencii kaj sekvi vin, sed vi ne vidos ilin.",
"mute_modal.they_wont_know": "Ili ne scios, ke ili estas silentigitaj.",
"mute_modal.title": "Ĉu silentigi uzanton?",
"mute_modal.you_wont_see_mentions": "Vi ne vidos afiŝojn, kiuj mencias ilin.",
"mute_modal.you_wont_see_posts": "Ili ankoraŭ povas vidi viajn afiŝojn, sed vi ne vidos iliajn.",
"navigation_bar.about": "Pri",
"navigation_bar.administration": "Administrado",
"navigation_bar.advanced_interface": "Malfermi altnivelan retpaĝan interfacon",
"navigation_bar.blocks": "Blokitaj uzantoj",
"navigation_bar.bookmarks": "Legosignoj",
@ -408,6 +486,7 @@
"navigation_bar.follows_and_followers": "Sekvatoj kaj sekvantoj",
"navigation_bar.lists": "Listoj",
"navigation_bar.logout": "Adiaŭi",
"navigation_bar.moderation": "Modereco",
"navigation_bar.mutes": "Silentigitaj uzantoj",
"navigation_bar.opened_in_classic_interface": "Afiŝoj, kontoj, kaj aliaj specifaj paĝoj kiuj estas malfermititaj defaulta en la klasika reta interfaco.",
"navigation_bar.personal": "Persone",
@ -418,20 +497,71 @@
"navigation_bar.security": "Sekureco",
"not_signed_in_indicator.not_signed_in": "Necesas saluti por aliri tiun rimedon.",
"notification.admin.report": "{name} raportis {target}",
"notification.admin.report_account": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target} por {category}",
"notification.admin.report_account_other": "{name} raportis {count, plural, one {afiŝon} other {# afiŝojn}} de {target}",
"notification.admin.report_statuses": "{name} raportis {target} por {category}",
"notification.admin.report_statuses_other": "{name} raportis {target}",
"notification.admin.sign_up": "{name} kreis konton",
"notification.admin.sign_up.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} kreis konton",
"notification.favourite": "{name} stelumis vian afiŝon",
"notification.favourite.name_and_others_with_link": "{name} kaj <a>{count, plural, one {# alia} other {# aliaj}}</a> ŝatis vian afiŝon",
"notification.follow": "{name} eksekvis vin",
"notification.follow.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} sekvis vin",
"notification.follow_request": "{name} petis sekvi vin",
"notification.follow_request.name_and_others": "{name} kaj {count, plural, one {# alia} other {# aliaj}} petis sekvi vin",
"notification.label.mention": "Mencii",
"notification.label.private_mention": "Privata mencio",
"notification.label.private_reply": "Privata respondo",
"notification.label.reply": "Respondi",
"notification.mention": "Mencii",
"notification.moderation-warning.learn_more": "Lerni pli",
"notification.moderation_warning": "Vi ricevis moderigan averton",
"notification.moderation_warning.action_delete_statuses": "Kelkaj el viaj afiŝoj estis forigitaj.",
"notification.moderation_warning.action_disable": "Via konto estas malŝaltita.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Kelkaj el viaj afiŝoj estis markitaj kiel sentemaj.",
"notification.moderation_warning.action_none": "Via konto ricevis moderigan averton.",
"notification.moderation_warning.action_sensitive": "Viaj afiŝoj estos markitaj kiel sentemaj ekde nun.",
"notification.moderation_warning.action_silence": "Via konto estis limigita.",
"notification.moderation_warning.action_suspend": "Via konto estas malakceptita.",
"notification.own_poll": "Via enketo finiĝis",
"notification.poll": "Balotenketo, en kiu vi voĉdonis, finiĝis",
"notification.reblog": "{name} diskonigis vian afiŝon",
"notification.reblog.name_and_others_with_link": "{name} kaj <a>{count, plural, one {# alia} other {# aliaj}}</a> diskonigis vian afiŝon",
"notification.relationships_severance_event": "Perditaj konektoj kun {name}",
"notification.relationships_severance_event.account_suspension": "Administranto de {from} malakceptis {target}, kio signifas, ke vi ne plu povas ricevi ĝisdatigojn de ili aŭ interagi kun ili.",
"notification.relationships_severance_event.domain_block": "Administranto de {from} blokis {target}, inkluzive de {followersCount} de viaj sekvantoj kaj {followingCount, plural, one {# konto} other {# kontoj}} kiujn vi sekvas.",
"notification.relationships_severance_event.learn_more": "Lerni pli",
"notification.relationships_severance_event.user_domain_block": "Vi blokis {target}, forigante {followersCount} de viaj sekvantoj kaj {followingCount, plural, one {# konto} other {# kontoj}} kiujn vi sekvas.",
"notification.status": "{name} ĵus afiŝis",
"notification.update": "{name} redaktis afiŝon",
"notification_requests.accept": "Akcepti",
"notification_requests.accept_multiple": "{count, plural, one {Akcepti # peton…} other {Akcepti # petojn…}}",
"notification_requests.confirm_accept_multiple.button": "{count, plural, one {Akcepti peton} other {Akcepti petojn}}",
"notification_requests.confirm_accept_multiple.message": "Vi estas akceptonta {count, plural, one {unu sciigan peton} other {# sciigajn petojn}}. Ĉu vi certas, ke vi volas daŭrigi?",
"notification_requests.confirm_accept_multiple.title": "Ĉu akcepti sciigajn petojn?",
"notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Malakcepti peton} other {Malakcepti petojn}}",
"notification_requests.confirm_dismiss_multiple.message": "Vi estas malakceptonta {count, plural, one {unu sciigan peton} other {# sciigajn petojn}}. Vi ne povos facile aliri {count, plural, one {ĝin} other {ilin}} denove. Ĉu vi certas, ke vi volas daŭrigi?",
"notification_requests.confirm_dismiss_multiple.title": "Ĉu malakcepti sciigajn petojn?",
"notification_requests.dismiss": "Forĵeti",
"notification_requests.dismiss_multiple": "{count, plural, one {Malakcepti # peton…} other {# Malakcepti # petojn…}}",
"notification_requests.edit_selection": "Redakti",
"notification_requests.exit_selection": "Farita",
"notification_requests.explainer_for_limited_account": "Sciigoj de ĉi tiu konto estis filtritaj ĉar la konto estis limigita de moderanto.",
"notification_requests.explainer_for_limited_remote_account": "Sciigoj de ĉi tiu konto estis filtritaj ĉar la konto aŭ ĝia servilo estis limigitaj de moderanto.",
"notification_requests.maximize": "Maksimumigi",
"notification_requests.minimize_banner": "Minimumigi filtritajn sciigojn-rubandon",
"notification_requests.notifications_from": "Sciigoj de {name}",
"notification_requests.title": "Filtritaj sciigoj",
"notification_requests.view": "Vidi sciigojn",
"notifications.clear": "Forviŝi sciigojn",
"notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviŝi ĉiujn viajn sciigojn?",
"notifications.clear_title": "Ĉu forigi sciigojn?",
"notifications.column_settings.admin.report": "Novaj raportoj:",
"notifications.column_settings.admin.sign_up": "Novaj registriĝoj:",
"notifications.column_settings.alert": "Sciigoj de la retumilo",
"notifications.column_settings.favourite": "Stelumoj:",
"notifications.column_settings.filter_bar.advanced": "Montri ĉiujn kategoriojn",
"notifications.column_settings.filter_bar.category": "Rapida filtrila breto",
"notifications.column_settings.follow": "Novaj sekvantoj:",
"notifications.column_settings.follow_request": "Novaj petoj de sekvado:",
"notifications.column_settings.mention": "Mencioj:",
@ -447,7 +577,7 @@
"notifications.filter.all": "Ĉiuj",
"notifications.filter.boosts": "Diskonigoj",
"notifications.filter.favourites": "Stelumoj",
"notifications.filter.follows": "Sekvoj",
"notifications.filter.follows": "Sekvatoj",
"notifications.filter.mentions": "Mencioj",
"notifications.filter.polls": "Balotenketaj rezultoj",
"notifications.filter.statuses": "Ĝisdatigoj de homoj, kiujn vi sekvas",
@ -457,6 +587,23 @@
"notifications.permission_denied": "Labortablaj sciigoj ne disponeblas pro peto antaŭe rifuzita de retumiloj",
"notifications.permission_denied_alert": "Labortablaj sciigoj ne povas esti ebligitaj, ĉar retumilpermeso antaŭe estis rifuzita",
"notifications.permission_required": "Labortablaj sciigoj ne disponeblas ĉar la bezonata permeso ne estis donita.",
"notifications.policy.accept": "Akcepti",
"notifications.policy.accept_hint": "Montri en sciigoj",
"notifications.policy.drop": "Ignori",
"notifications.policy.drop_hint": "Sendi al la malpleno, por neniam esti vidita denove",
"notifications.policy.filter": "Filtri",
"notifications.policy.filter_hint": "Sendi al filtritaj sciigoj-enirkesto",
"notifications.policy.filter_limited_accounts_hint": "Limigita de servilaj moderigantoj",
"notifications.policy.filter_limited_accounts_title": "Moderigitaj kontoj",
"notifications.policy.filter_new_accounts.hint": "Kreite en la {days, plural, one {lasta tago} other {# lastaj tagoj}}",
"notifications.policy.filter_new_accounts_title": "Novaj kontoj",
"notifications.policy.filter_not_followers_hint": "Inkluzive de homoj, kiuj sekvis vin malpli ol {days, plural, one {unu tago} other {# tagoj}}",
"notifications.policy.filter_not_followers_title": "Homoj, kiuj ne sekvas vin",
"notifications.policy.filter_not_following_hint": "Ĝis vi permane aprobas ilin",
"notifications.policy.filter_not_following_title": "Homoj, kiujn vi ne sekvas",
"notifications.policy.filter_private_mentions_hint": "Filtrite krom se ĝi respondas al via propra mencio aŭ se vi sekvas la sendinton",
"notifications.policy.filter_private_mentions_title": "Nepetitaj privataj mencioj",
"notifications.policy.title": "Administri sciigojn de…",
"notifications_permission_banner.enable": "Ŝalti retumilajn sciigojn",
"notifications_permission_banner.how_to_control": "Por ricevi sciigojn kiam Mastodon ne estas malfermita, ebligu labortablajn sciigojn. Vi povas regi precize kiuj specoj de interagoj generas labortablajn sciigojn per la supra butono {icon} post kiam ili estas ebligitaj.",
"notifications_permission_banner.title": "Neniam preterlasas iun ajn",
@ -466,8 +613,8 @@
"onboarding.actions.go_to_home": "Go to your home feed",
"onboarding.compose.template": "Saluton #Mastodon!",
"onboarding.follows.empty": "Bedaŭrinde, neniu rezulto estas montrebla nuntempe. Vi povas provi serĉi aŭ foliumi la esploran paĝon por trovi kontojn por sekvi, aŭ retrovi baldaŭ.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon",
"onboarding.follows.lead": "Via hejma fluo estas la ĉefa maniero sperti Mastodon. Ju pli da homoj vi sekvas, des pli aktiva kaj interesa ĝi estos. Por komenci, jen kelkaj sugestoj:",
"onboarding.follows.title": "Agordi vian hejman fluon",
"onboarding.profile.discoverable": "Trovebligi mian profilon",
"onboarding.profile.discoverable_hint": "Kiam vi aliĝi al trovebleco ĉe Mastodon, viaj afiŝoj eble aperos en serĉaj rezultoj kaj populariĝoj, kaj via profilo eble estas sugestota al personoj kun similaj intereseoj al vi.",
"onboarding.profile.display_name": "Publika nomo",
@ -488,7 +635,7 @@
"onboarding.start.title": "Vi atingas ĝin!",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}",
"onboarding.steps.publish_status.body": "Say hello to the world.",
"onboarding.steps.publish_status.body": "Salutu la mondon per teksto, fotoj, filmetoj aŭ balotenketoj {emoji}",
"onboarding.steps.publish_status.title": "Fari vian unuan afiŝon",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile",
@ -518,6 +665,7 @@
"privacy.private.short": "Sekvantoj",
"privacy.public.long": "Ĉiujn ajn ĉe kaj ekster Mastodon",
"privacy.public.short": "Publika",
"privacy.unlisted.additional": "Ĉi tio kondutas ekzakte kiel publika, krom ke la afiŝo ne aperos en vivaj fluoj aŭ kradvortoj, esploro aŭ Mastodon-serĉo, eĉ se vi estas enskribita en la tuta konto.",
"privacy.unlisted.long": "Malpli algoritmaj fanfaroj",
"privacy.unlisted.short": "Diskrete publika",
"privacy_policy.last_updated": "Laste ĝisdatigita en {date}",
@ -537,7 +685,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "hodiaŭ",
"reply_indicator.attachments": "{count, plural, one {# aldonaĵo} other {# aldonaĵoj}}",
"reply_indicator.cancel": "Nuligi",
"reply_indicator.poll": "Balotenketo",
"report.block": "Bloki",
"report.block_explanation": "Vi ne vidos iliajn afiŝojn. Ili ne povos vidi viajn afiŝojn, nek sekvi vin. Ili ne scios, ke vi blokas ilin.",
"report.categories.legal": "Laŭleĝa",
@ -580,9 +730,13 @@
"report.unfollow_explanation": "Vi sekvas ĉi tiun konton. Por ne plu vidi ĝiajn afiŝojn en via hejma templinio, ĉesu sekvi ĝin.",
"report_notification.attached_statuses": "{count, plural, one {{count} afiŝo almetita} other {{count} afiŝoj almetitaj}}",
"report_notification.categories.legal": "Laŭleĝa",
"report_notification.categories.legal_sentence": "kontraŭleĝa enhavo",
"report_notification.categories.other": "Alia",
"report_notification.categories.other_sentence": "alia",
"report_notification.categories.spam": "Trudmesaĝo",
"report_notification.categories.spam_sentence": "trudmesaĝo",
"report_notification.categories.violation": "Malobservo de la regulo",
"report_notification.categories.violation_sentence": "malobservo de la regulo",
"report_notification.open": "Malfermi la raporton",
"search.no_recent_searches": "Neniuj lastaj serĉoj",
"search.placeholder": "Serĉi",
@ -610,8 +764,11 @@
"server_banner.about_active_users": "Personoj uzantaj ĉi tiun servilon dum la lastaj 30 tagoj (Aktivaj Uzantoj Monate)",
"server_banner.active_users": "aktivaj uzantoj",
"server_banner.administered_by": "Administrata de:",
"server_banner.is_one_of_many": "{domain} estas unu el la multaj sendependaj Mastodon-serviloj, kiujn vi povas uzi por partopreni en la fediverso.",
"server_banner.server_stats": "Statistikoj de la servilo:",
"sign_in_banner.create_account": "Krei konton",
"sign_in_banner.follow_anyone": "Sekvi iun ajn tra la fediverso kaj vidi ĉion en kronologia ordo. Neniuj algoritmoj, reklamoj aŭ klakbetoj videblas.",
"sign_in_banner.mastodon_is": "Mastodonto estas la plej bona maniero por resti flank-al-flanke kun kio okazas.",
"sign_in_banner.sign_in": "Saluti",
"sign_in_banner.sso_redirect": "Ensalutu aŭ Registriĝi",
"status.admin_account": "Malfermi fasadon de moderigado por @{name}",
@ -621,14 +778,18 @@
"status.bookmark": "Aldoni al la legosignoj",
"status.cancel_reblog_private": "Ne plu diskonigi",
"status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi",
"status.continued_thread": "Daŭrigis fadenon",
"status.copy": "Kopii la ligilon al la mesaĝo",
"status.delete": "Forigi",
"status.detailed_status": "Detala konversacia vido",
"status.direct": "Private mencii @{name}",
"status.direct_indicator": "Privata mencio",
"status.edit": "Redakti",
"status.edited": "Laste redaktita {date}",
"status.edited_x_times": "Redactita {count, plural, one {{count} fojon} other {{count} fojojn}}",
"status.embed": "Akiri enkorpigan kodon",
"status.favourite": "Ŝatata",
"status.favourites": "{count, plural, one {plej ŝatata} other {plej ŝatataj}}",
"status.filter": "Filtri ĉi tiun afiŝon",
"status.history.created": "{name} kreis {date}",
"status.history.edited": "{name} redaktis {date}",
@ -647,9 +808,11 @@
"status.reblog": "Diskonigi",
"status.reblog_private": "Diskonigi kun la sama videbleco",
"status.reblogged_by": "{name} diskonigis",
"status.reblogs": "{count, plural, one {diskonigo} other {diskonigoj}}",
"status.reblogs.empty": "Ankoraŭ neniu diskonigis tiun afiŝon. Kiam iu faras tion, ri aperos ĉi tie.",
"status.redraft": "Forigi kaj reskribi",
"status.remove_bookmark": "Forigi legosignon",
"status.replied_in_thread": "Respondis en fadeno",
"status.replied_to": "Respondis al {name}",
"status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Nadie de este servidor puede seguirte.",
"domain_block_modal.they_wont_know": "No sabrán que fueron bloqueados.",
"domain_block_modal.title": "¿Bloquear dominio?",
"domain_block_modal.you_will_lose_followers": "Se eliminarán todos tus seguidores de este servidor.",
"domain_block_modal.you_will_lose_num_followers": "Perderás {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} y {followingCount, plural, one {{followingCountDisplay} persona a la que sigues} other {{followingCountDisplay} personas a las que sigues}}.",
"domain_block_modal.you_wont_see_posts": "No verás mensajes ni notificaciones de usuarios en este servidor.",
"domain_pill.activitypub_lets_connect": "Te permite conectar e interactuar con cuentas no solo en Mastodon, sino también a través de diferentes aplicaciones sociales.",
"domain_pill.activitypub_like_language": "ActivityPub es como el idioma que Mastodon habla con otras redes sociales.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Quitar el foco del área de texto de redacción o de búsqueda",
"keyboard_shortcuts.up": "Subir en la lista",
"lightbox.close": "Cerrar",
"lightbox.compress": "Comprimir cuadro de vista de imagen",
"lightbox.expand": "Expandir cuadro de vista de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
"lightbox.zoom_in": "Ampliar al tamaño real",
"lightbox.zoom_out": "Ampliar hasta ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil fue ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Nuevas denuncias:",
"notifications.column_settings.admin.sign_up": "Nuevos registros:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
"notifications.column_settings.beta.category": "Funciones experimentales",
"notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@ -789,6 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición: {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
"status.embed": "Obtener código para insertar",
"status.favourite": "Marcar como favorito",
"status.favourites": "{count, plural, one {# voto} other {# votos}}",
"status.filter": "Filtrar este mensaje",

View file

@ -39,11 +39,11 @@
"account.following_counter": "{count, plural, one {{counter} siguiendo} other {{counter} siguiendo}}",
"account.follows.empty": "Este usuario todavía no sigue a nadie.",
"account.go_to_profile": "Ir al perfil",
"account.hide_reblogs": "Ocultar retoots de @{name}",
"account.hide_reblogs": "Ocultar impulsos de @{name}",
"account.in_memoriam": "En memoria.",
"account.joined_short": "Se unió",
"account.languages": "Cambiar idiomas suscritos",
"account.link_verified_on": "El proprietario de este link fue comprobado el {date}",
"account.link_verified_on": "El proprietario de este enlace 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.media": "Multimedia",
"account.mention": "Mencionar a @{name}",
@ -61,7 +61,7 @@
"account.requested": "Esperando aprobación. Haga clic para cancelar la solicitud de seguimiento",
"account.requested_follow": "{name} ha solicitado seguirte",
"account.share": "Compartir el perfil de @{name}",
"account.show_reblogs": "Mostrar retoots de @{name}",
"account.show_reblogs": "Mostrar impulsos de @{name}",
"account.statuses_counter": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
"account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Mostrar a {domain}",
@ -70,8 +70,8 @@
"account.unfollow": "Dejar de seguir",
"account.unmute": "Dejar de silenciar a @{name}",
"account.unmute_notifications_short": "Dejar de silenciar notificaciones",
"account.unmute_short": "Desmutear",
"account_note.placeholder": "Clic para añadir nota",
"account.unmute_short": "Dejar de silenciar",
"account_note.placeholder": "Haz clic para agregar una nota",
"admin.dashboard.daily_retention": "Tasa de retención de usuarios por día después de unirse",
"admin.dashboard.monthly_retention": "Tasa de retención de usuarios por mes después de unirse",
"admin.dashboard.retention.average": "Promedio",
@ -97,7 +97,7 @@
"block_modal.title": "¿Bloquear usuario?",
"block_modal.you_wont_see_mentions": "No verás publicaciones que los mencionen.",
"boost_modal.combo": "Puedes hacer clic en {combo} para saltar este aviso la próxima vez",
"boost_modal.reblog": "¿Impulsar la publicación?",
"boost_modal.reblog": "¿Deseas impulsar la publicación?",
"boost_modal.undo_reblog": "¿Dejar de impulsar la publicación?",
"bundle_column_error.copy_stacktrace": "Copiar informe de error",
"bundle_column_error.error.body": "La página solicitada no pudo ser renderizada. Podría deberse a un error en nuestro código o a un problema de compatibilidad con el navegador.",
@ -130,7 +130,7 @@
"column.lists": "Listas",
"column.mutes": "Usuarios silenciados",
"column.notifications": "Notificaciones",
"column.pins": "Toots fijados",
"column.pins": "Publicaciones fijadas",
"column.public": "Línea de tiempo federada",
"column_back_button.label": "Atrás",
"column_header.hide_settings": "Ocultar configuración",
@ -148,10 +148,10 @@
"compose.published.body": "Publicado.",
"compose.published.open": "Abrir",
"compose.saved.body": "Publicación guardada.",
"compose_form.direct_message_warning_learn_more": "Aprender mas",
"compose_form.direct_message_warning_learn_more": "Saber más",
"compose_form.encryption_warning": "Las publicaciones en Mastodon no están cifradas de extremo a extremo. No comparta ninguna información sensible en Mastodon.",
"compose_form.hashtag_warning": "Este toot no será listado bajo ningún hashtag dado que no es público. Solo toots públicos pueden ser buscados por hashtag.",
"compose_form.lock_disclaimer": "Tu cuenta no está bloqueada. Todos pueden seguirte para ver tus toots solo para seguidores.",
"compose_form.hashtag_warning": "Esta publicación no será listada bajo ninguna etiqueta dado que no es pública. Solo publicaciones públicas pueden ser buscadas por etiqueta.",
"compose_form.lock_disclaimer": "Tu cuenta no está {locked}. Todos pueden seguirte para ver tus publicaciones solo para seguidores.",
"compose_form.lock_disclaimer.lock": "bloqueado",
"compose_form.placeholder": "¿En qué estás pensando?",
"compose_form.poll.duration": "Duración de la encuesta",
@ -165,32 +165,32 @@
"compose_form.publish_form": "Publicar",
"compose_form.reply": "Respuesta",
"compose_form.save_changes": "Actualización",
"compose_form.spoiler.marked": "Texto oculto tras la advertencia",
"compose_form.spoiler.unmarked": "Texto no oculto",
"compose_form.spoiler.marked": "Quitar advertencia de contenido",
"compose_form.spoiler.unmarked": "Añadir advertencia de contenido",
"compose_form.spoiler_placeholder": "Advertencia de contenido (opcional)",
"confirmation_modal.cancel": "Cancelar",
"confirmations.block.confirm": "Bloquear",
"confirmations.delete.confirm": "Eliminar",
"confirmations.delete.message": "¿Estás seguro de que quieres borrar este toot?",
"confirmations.delete.message": "¿Estás seguro de que quieres borrar esta publicación?",
"confirmations.delete.title": "¿Eliminar publicación?",
"confirmations.delete_list.confirm": "Eliminar",
"confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
"confirmations.delete_list.title": "¿Eliminar lista?",
"confirmations.delete_list.title": "¿Deseas eliminar la lista?",
"confirmations.discard_edit_media.confirm": "Descartar",
"confirmations.discard_edit_media.message": "Tienes cambios sin guardar en la descripción o vista previa del archivo, ¿deseas descartarlos de cualquier manera?",
"confirmations.edit.confirm": "Editar",
"confirmations.edit.message": "Editar sobrescribirá el mensaje que estás escribiendo. ¿Estás seguro de que deseas continuar?",
"confirmations.edit.title": "¿Sobrescribir publicación?",
"confirmations.edit.title": "¿Sobreescribir publicación?",
"confirmations.logout.confirm": "Cerrar sesión",
"confirmations.logout.message": "¿Estás seguro de querer cerrar la sesión?",
"confirmations.logout.title": "¿Cerrar sesión?",
"confirmations.logout.message": "¿Estás seguro de que quieres cerrar la sesión?",
"confirmations.logout.title": "¿Deseas cerrar sesión?",
"confirmations.mute.confirm": "Silenciar",
"confirmations.redraft.confirm": "Borrar y volver a borrador",
"confirmations.redraft.message": "¿Estás seguro que quieres borrar esta publicación y editarla? Los favoritos e impulsos se perderán, y las respuestas a la publicación original quedarán separadas.",
"confirmations.redraft.title": "¿Borrar y volver a redactar la publicación?",
"confirmations.reply.confirm": "Responder",
"confirmations.reply.message": "Responder sobrescribirá el mensaje que estás escribiendo. ¿Estás seguro de que deseas continuar?",
"confirmations.reply.title": "¿Sobrescribir publicación?",
"confirmations.reply.title": "¿Sobreescribir publicación?",
"confirmations.unfollow.confirm": "Dejar de seguir",
"confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
"confirmations.unfollow.title": "¿Dejar de seguir al usuario?",
@ -213,15 +213,15 @@
"dismissable_banner.dismiss": "Descartar",
"dismissable_banner.explore_links": "Estas noticias están siendo discutidas por personas en este y otros servidores de la red descentralizada en este momento.",
"dismissable_banner.explore_statuses": "Estas son las publicaciones que están en tendencia en la red ahora. Las publicaciones recientes con más impulsos y favoritos se muestran más arriba.",
"dismissable_banner.explore_tags": "Se trata de hashtags que están ganando adeptos en las redes sociales hoy en día. Los hashtags que son utilizados por más personas diferentes se clasifican mejor.",
"dismissable_banner.public_timeline": "Estos son los toots públicos más recientes de personas en la web social a las que sigue la gente en {domain}.",
"dismissable_banner.explore_tags": "Se trata de etiquetas que están ganando adeptos en las redes sociales hoy en día. Las etiquetas que son utilizadas por más personas diferentes se clasifican mejor.",
"dismissable_banner.public_timeline": "Estas son las publicaciones públicas más recientes de personas en la web social a las que sigue la gente en {domain}.",
"domain_block_modal.block": "Bloquear servidor",
"domain_block_modal.block_account_instead": "Bloquear @{name} en su lugar",
"domain_block_modal.they_can_interact_with_old_posts": "Las personas de este servidor pueden interactuar con tus publicaciones antiguas.",
"domain_block_modal.they_cant_follow": "Nadie de este servidor puede seguirte.",
"domain_block_modal.they_wont_know": "No sabrán que han sido bloqueados.",
"domain_block_modal.title": "¿Bloquear dominio?",
"domain_block_modal.you_will_lose_followers": "Todos tus seguidores de este servidor serán eliminados.",
"domain_block_modal.you_will_lose_num_followers": "Perderás {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} y {followingCount, plural, one {{followingCountDisplay} persona a la que sigues} other {{followingCountDisplay} personas a las que sigues}}.",
"domain_block_modal.you_wont_see_posts": "No verás publicaciones ni notificaciones de usuarios en este servidor.",
"domain_pill.activitypub_lets_connect": "Te permite conectar e interactuar con personas no sólo en Mastodon, sino también a través de diferentes aplicaciones sociales.",
"domain_pill.activitypub_like_language": "ActivityPub es como el idioma que Mastodon habla con otras redes sociales.",
@ -236,7 +236,7 @@
"domain_pill.your_handle": "Tu alias:",
"domain_pill.your_server": "Tu hogar digital, donde residen todas tus publicaciones. ¿No te gusta este sitio? Muévete a otro servidor en cualquier momento y llévate a tus seguidores.",
"domain_pill.your_username": "Tu identificador único en este servidor. Es posible encontrar usuarios con el mismo nombre de usuario en diferentes servidores.",
"embed.instructions": "Añade este toot a tu sitio web con el siguiente código.",
"embed.instructions": "Añade esta publicación a tu sitio web con el siguiente código.",
"embed.preview": "Así es como se verá:",
"emoji_button.activity": "Actividad",
"emoji_button.clear": "Borrar",
@ -249,16 +249,16 @@
"emoji_button.objects": "Objetos",
"emoji_button.people": "Gente",
"emoji_button.recent": "Usados frecuentemente",
"emoji_button.search": "Buscar",
"emoji_button.search": "Buscar...",
"emoji_button.search_results": "Resultados de búsqueda",
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viajes y lugares",
"empty_column.account_hides_collections": "Este usuario ha elegido no hacer disponible esta información",
"empty_column.account_suspended": "Cuenta suspendida",
"empty_column.account_timeline": "¡No hay toots aquí!",
"empty_column.account_timeline": "¡No hay publicaciones aquí!",
"empty_column.account_unavailable": "Perfil no disponible",
"empty_column.blocks": "Aún no has bloqueado a ningún usuario.",
"empty_column.bookmarked_statuses": "Aún no tienes ningún toot guardado como marcador. Cuando guardes uno, se mostrará aquí.",
"empty_column.bookmarked_statuses": "Aún no tienes ninguna publicación guardada como marcador. Cuando guardes una, se mostrará aquí.",
"empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
"empty_column.direct": "Aún no tienes menciones privadas. Cuando envíes o recibas una, aparecerán aquí.",
"empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
@ -266,8 +266,8 @@
"empty_column.favourited_statuses": "Todavía no tienes publicaciones favoritas. Cuando le des favorito a una publicación se mostrarán acá.",
"empty_column.favourites": "Todavía nadie marcó como favorito esta publicación. Cuando alguien lo haga, se mostrará aquí.",
"empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
"empty_column.followed_tags": "No estás siguiendo ningún hashtag todavía. Cuando lo hagas, aparecerá aquí.",
"empty_column.hashtag": "No hay nada en este hashtag aún.",
"empty_column.followed_tags": "No estás siguiendo ninguna etiqueta todavía. Cuando lo hagas, aparecerá aquí.",
"empty_column.hashtag": "No hay nada en esta etiqueta aún.",
"empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
"empty_column.list": "No hay nada en esta lista aún. Cuando miembros de esta lista publiquen nuevos estatus, estos aparecerán qui.",
"empty_column.lists": "No tienes ninguna lista. cuando crees una, se mostrará aquí.",
@ -304,7 +304,7 @@
"filter_modal.select_filter.title": "Filtrar esta publicación",
"filter_modal.title.status": "Filtrar una publicación",
"filter_warning.matches_filter": "Coincide con el filtro “{title}”",
"filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que puede que conozcas",
"filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# people}} que puede que tú conozcas",
"filtered_notifications_banner.title": "Notificaciones filtradas",
"firehose.all": "Todas",
"firehose.local": "Este servidor",
@ -315,7 +315,7 @@
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
"follow_suggestions.dismiss": "No mostrar de nuevo",
"follow_suggestions.featured_longer": "Escogidos por el equipo de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populares entre las personas a las que sigues",
"follow_suggestions.friends_of_friends_longer": "Popular entre las personas a las que sigues",
"follow_suggestions.hints.featured": "Este perfil ha sido seleccionado a mano por el equipo de {domain}.",
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
@ -323,11 +323,11 @@
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
"follow_suggestions.popular_suggestion": "Sugerencia popular",
"follow_suggestions.popular_suggestion_longer": "Populares en {domain}",
"follow_suggestions.popular_suggestion_longer": "Popular en {domain}",
"follow_suggestions.similar_to_recently_followed_longer": "Similares a los perfiles que has seguido recientemente",
"follow_suggestions.view_all": "Ver todo",
"follow_suggestions.who_to_follow": "Recomendamos seguir",
"followed_tags": "Hashtags seguidos",
"followed_tags": "Etiquetas seguidas",
"footer.about": "Acerca de",
"footer.directory": "Directorio de perfiles",
"footer.get_app": "Obtener la aplicación",
@ -344,8 +344,8 @@
"hashtag.column_settings.select.no_options_message": "No se encontraron sugerencias",
"hashtag.column_settings.select.placeholder": "Introducir etiquetas…",
"hashtag.column_settings.tag_mode.all": "Todos estos",
"hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
"hashtag.column_settings.tag_mode.none": "Ninguno de estos",
"hashtag.column_settings.tag_mode.any": "Cualquiera de estas",
"hashtag.column_settings.tag_mode.none": "Ninguna de estas",
"hashtag.column_settings.tag_toggle": "Incluye etiquetas adicionales para esta columna",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participante} other {{counter} participantes}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} publicación} other {{counter} publicaciones}}",
@ -361,7 +361,7 @@
"hints.profiles.see_more_posts": "Ver más publicaciones en {domain}",
"hints.threads.replies_may_be_missing": "Puede que no se muestren algunas respuestas de otros servidores.",
"hints.threads.see_more": "Ver más respuestas en {domain}",
"home.column_settings.show_reblogs": "Mostrar retoots",
"home.column_settings.show_reblogs": "Mostrar impulsos",
"home.column_settings.show_replies": "Mostrar respuestas",
"home.hide_announcements": "Ocultar anuncios",
"home.pending_critical_update.body": "¡Por favor actualiza tu servidor Mastodon lo antes posible!",
@ -369,14 +369,14 @@
"home.pending_critical_update.title": "¡Actualización de seguridad crítica disponible!",
"home.show_announcements": "Mostrar anuncios",
"ignore_notifications_modal.disclaimer": "Mastodon no puede informar a los usuarios que has ignorado sus notificaciones. Ignorar notificaciones no impedirá que se sigan enviando los mensajes.",
"ignore_notifications_modal.filter_instead": "Filtrar en vez de ignorar",
"ignore_notifications_modal.filter_instead": "Filtrar en su lugar",
"ignore_notifications_modal.filter_to_act_users": "Aún podrás aceptar, rechazar o reportar usuarios",
"ignore_notifications_modal.filter_to_avoid_confusion": "Filtrar ayuda a evitar confusiones potenciales",
"ignore_notifications_modal.filter_to_review_separately": "Puedes revisar las notificaciones filtradas por separado",
"ignore_notifications_modal.ignore": "Ignorar notificaciones",
"ignore_notifications_modal.limited_accounts_title": "¿Ignorar notificaciones de cuentas moderadas?",
"ignore_notifications_modal.new_accounts_title": "¿Ignorar notificaciones de cuentas nuevas?",
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te sigue?",
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
"interaction_modal.description.favourite": "Con una cuenta en Mastodon, puedes marcar como favorita esta publicación para que el autor sepa que te gusta, y guardala para más adelante.",
@ -399,13 +399,13 @@
"intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}",
"keyboard_shortcuts.back": "volver atrás",
"keyboard_shortcuts.blocked": "abrir una lista de usuarios bloqueados",
"keyboard_shortcuts.boost": "retootear",
"keyboard_shortcuts.boost": "Impulsar publicación",
"keyboard_shortcuts.column": "enfocar un estado en una de las columnas",
"keyboard_shortcuts.compose": "enfocar el área de texto de redacción",
"keyboard_shortcuts.description": "Descripción",
"keyboard_shortcuts.direct": "para abrir la columna de menciones privadas",
"keyboard_shortcuts.down": "mover hacia abajo en la lista",
"keyboard_shortcuts.enter": "abrir estado",
"keyboard_shortcuts.enter": "Abrir publicación",
"keyboard_shortcuts.favourite": "Marcar como favorita la publicación",
"keyboard_shortcuts.favourites": "Abrir lista de favoritos",
"keyboard_shortcuts.federated": "abrir el timeline federado",
@ -419,23 +419,23 @@
"keyboard_shortcuts.my_profile": "abrir tu perfil",
"keyboard_shortcuts.notifications": "abrir la columna de notificaciones",
"keyboard_shortcuts.open_media": "para abrir archivos multimedia",
"keyboard_shortcuts.pinned": "abrir la lista de toots destacados",
"keyboard_shortcuts.pinned": "Abrir la lista de publicaciones fijadas",
"keyboard_shortcuts.profile": "abrir el perfil del autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.reply": "Responder a la publicación",
"keyboard_shortcuts.requests": "abrir la lista de peticiones de seguidores",
"keyboard_shortcuts.search": "para poner el foco en la búsqueda",
"keyboard_shortcuts.spoilers": "para mostrar/ocultar el campo CW",
"keyboard_shortcuts.start": "abrir la columna \"comenzar\"",
"keyboard_shortcuts.toggle_hidden": "mostrar/ocultar texto tras aviso de contenido (CW)",
"keyboard_shortcuts.toggle_sensitivity": "mostrar/ocultar medios",
"keyboard_shortcuts.toot": "para comenzar un nuevo toot",
"keyboard_shortcuts.toot": "Comenzar una nueva publicación",
"keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
"keyboard_shortcuts.up": "para ir hacia arriba en la lista",
"lightbox.close": "Cerrar",
"lightbox.compress": "Comprimir cuadro de visualización de imagen",
"lightbox.expand": "Expandir cuadro de visualización de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
"lightbox.zoom_in": "Ampliar al tamaño real",
"lightbox.zoom_out": "Ampliar para ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@ -474,7 +474,7 @@
"navigation_bar.blocks": "Usuarios bloqueados",
"navigation_bar.bookmarks": "Marcadores",
"navigation_bar.community_timeline": "Historia local",
"navigation_bar.compose": "Escribir un nuevo toot",
"navigation_bar.compose": "Redactar una nueva publicación",
"navigation_bar.direct": "Menciones privadas",
"navigation_bar.discover": "Descubrir",
"navigation_bar.domain_blocks": "Dominios ocultos",
@ -482,7 +482,7 @@
"navigation_bar.favourites": "Favoritos",
"navigation_bar.filters": "Palabras silenciadas",
"navigation_bar.follow_requests": "Solicitudes para seguirte",
"navigation_bar.followed_tags": "Hashtags seguidos",
"navigation_bar.followed_tags": "Etiquetas seguidas",
"navigation_bar.follows_and_followers": "Siguiendo y seguidores",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Cerrar sesión",
@ -490,25 +490,25 @@
"navigation_bar.mutes": "Usuarios silenciados",
"navigation_bar.opened_in_classic_interface": "Publicaciones, cuentas y otras páginas específicas se abren por defecto en la interfaz web clásica.",
"navigation_bar.personal": "Personal",
"navigation_bar.pins": "Toots fijados",
"navigation_bar.pins": "Publicaciones fijadas",
"navigation_bar.preferences": "Preferencias",
"navigation_bar.public_timeline": "Historia federada",
"navigation_bar.search": "Buscar",
"navigation_bar.security": "Seguridad",
"not_signed_in_indicator.not_signed_in": "Necesitas iniciar sesión para acceder a este recurso.",
"notification.admin.report": "{name} denunció a {target}",
"notification.admin.report_account": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}",
"notification.admin.report_account_other": "{name} informó de {count, plural, one {una publicación} other {# publicaciones}} de {target}",
"notification.admin.report_statuses": "{name} informó de {target} por {category}",
"notification.admin.report_statuses_other": "{name} informó de {target}",
"notification.admin.report_account": "{name} reportó {count, plural, one {una publicación} other {# publicaciones}} de {target} por {category}",
"notification.admin.report_account_other": "{name} reportó {count, plural, one {una publicación} other {# publicaciones}} de {target}",
"notification.admin.report_statuses": "{name} reportó {target} por {category}",
"notification.admin.report_statuses_other": "{name} reportó {target}",
"notification.admin.sign_up": "{name} se unio",
"notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# más} other {# más}} se registraron",
"notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} se registraron",
"notification.favourite": "{name} marcó como favorita tu publicación",
"notification.favourite.name_and_others_with_link": "{name} y <a>{count, plural, one {# más} other {# más}}</a> marcaron tu publicación como favorita",
"notification.favourite.name_and_others_with_link": "{name} y <a>{count, plural, one {# otro} other {# otros}}</a> marcaron tu publicación como favorita",
"notification.follow": "{name} te empezó a seguir",
"notification.follow.name_and_others": "{name} y {count, plural, one {# más} other {# más}} te siguieron",
"notification.follow.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} te siguieron",
"notification.follow_request": "{name} ha solicitado seguirte",
"notification.follow_request.name_and_others": "{name} y {count, plural, one {# más} other {# más}} han solicitado seguirte",
"notification.follow_request.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} han solicitado seguirte",
"notification.label.mention": "Mención",
"notification.label.private_mention": "Mención privada",
"notification.label.private_reply": "Respuesta privada",
@ -519,14 +519,14 @@
"notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.",
"notification.moderation_warning.action_disable": "Tu cuenta ha sido desactivada.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Se han marcado como sensibles algunas de tus publicaciones.",
"notification.moderation_warning.action_none": "Tu cuenta ha recibido un aviso de moderación.",
"notification.moderation_warning.action_none": "Tu cuenta ha recibido una advertencia de moderación.",
"notification.moderation_warning.action_sensitive": "De ahora en adelante, todas tus publicaciones se marcarán como sensibles.",
"notification.moderation_warning.action_silence": "Tu cuenta ha sido limitada.",
"notification.moderation_warning.action_suspend": "Tu cuenta ha sido suspendida.",
"notification.own_poll": "Tu encuesta ha terminado",
"notification.poll": "Una encuesta ha terminado",
"notification.reblog": "{name} ha retooteado tu estado",
"notification.reblog.name_and_others_with_link": "{name} y <a>{count, plural, one {# más} other {# más}}</a> impulsaron tu publicación",
"notification.poll": "Una encuesta en la que has votado ha terminado",
"notification.reblog": "{name} ha impulsado tu publicación",
"notification.reblog.name_and_others_with_link": "{name} y <a>{count, plural, one {# otro} other {# otros}}</a> impulsaron tu publicación",
"notification.relationships_severance_event": "Conexiones perdidas con {name}",
"notification.relationships_severance_event.account_suspension": "Un administrador de {from} ha suspendido {target}, lo que significa que ya no puedes recibir actualizaciones de sus cuentas o interactuar con ellas.",
"notification.relationships_severance_event.domain_block": "Un administrador de {from} ha bloqueado {target}, incluyendo {followersCount} de tus seguidores y {followingCount, plural, one {# cuenta} other {# cuentas}} que sigues.",
@ -536,18 +536,18 @@
"notification.update": "{name} editó una publicación",
"notification_requests.accept": "Aceptar",
"notification_requests.accept_multiple": "{count, plural, one {Aceptar # solicitud…} other {Aceptar # solicitudes…}}",
"notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceptar solicitud} other {Aceptar solicitudes}}",
"notification_requests.confirm_accept_multiple.message": "Vas a aceptar {count, plural, one {una solicitud} other {# solicitudes}}. ¿Quieres continuar?",
"notification_requests.confirm_accept_multiple.title": "¿Aceptar las solicitudes?",
"notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Descartar solicitud} other {Descartar solicitudes}}",
"notification_requests.confirm_dismiss_multiple.message": "Vas a descartar {count, plural, one {una solicitud} other {# solicitudes}}. No podrás volver a acceder fácilmente a {count, plural, one {ella} other {ellas}} de nuevo. ¿Seguro que quieres continuar?",
"notification_requests.confirm_dismiss_multiple.title": "¿Descartar las solicitudes?",
"notification_requests.confirm_accept_multiple.button": "{count, plural, one {Solicitud aceptada} other {Solicitudes aceptadas}}",
"notification_requests.confirm_accept_multiple.message": "Estás por aceptar {count, plural, one {una solicitud de notificación} other {# solicitudes de notificación}}. ¿Estás seguro de que quieres continuar?",
"notification_requests.confirm_accept_multiple.title": "¿Deseas aceptar las solicitudes de notificación?",
"notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Solicitud descartada} other {Solicitudes descartadas}}",
"notification_requests.confirm_dismiss_multiple.message": "Estás por descartar {count, plural, one {una solicitud de notificación} other {# solicitudes de notificación}}. No serás capaz de acceder fácilmente a {count, plural, one {ella} other {ellas}} de nuevo. ¿Estás seguro de que quieres continuar?",
"notification_requests.confirm_dismiss_multiple.title": "¿Deseas descartar las solicitudes de notificación?",
"notification_requests.dismiss": "Descartar",
"notification_requests.dismiss_multiple": "{count, plural, one {Descartar # solicitud…} other {Descartar # solicitudes…}}",
"notification_requests.edit_selection": "Editar",
"notification_requests.exit_selection": "Hecho",
"notification_requests.explainer_for_limited_account": "Las notificaciones de esta cuenta han sido filtradas porque la cuenta ha sido limitada por un moderador.",
"notification_requests.explainer_for_limited_remote_account": "Las notificaciones de esta cuenta han sido filtradas porque la cuenta o su servidor ha sido limitada por un moderador.",
"notification_requests.explainer_for_limited_account": "Las notificaciones de esta cuenta han sido filtradas, ya que la cuenta ha sido limitada por un moderador.",
"notification_requests.explainer_for_limited_remote_account": "Las notificaciones de esta cuenta han sido filtradas, ya que la cuenta o su servidor ha sido limitada por un moderador.",
"notification_requests.maximize": "Maximizar",
"notification_requests.minimize_banner": "Minimizar banner de notificaciones filtradas",
"notification_requests.notifications_from": "Notificaciones de {name}",
@ -555,12 +555,10 @@
"notification_requests.view": "Ver notificaciones",
"notifications.clear": "Limpiar notificaciones",
"notifications.clear_confirmation": "¿Seguro de querer borrar permanentemente todas tus notificaciones?",
"notifications.clear_title": "¿Borrar notificaciones?",
"notifications.clear_title": "¿Limpiar notificaciones?",
"notifications.column_settings.admin.report": "Nuevas denuncias:",
"notifications.column_settings.admin.sign_up": "Registros nuevos:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
"notifications.column_settings.beta.category": "Características experimentales",
"notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@ -569,7 +567,7 @@
"notifications.column_settings.mention": "Menciones:",
"notifications.column_settings.poll": "Resultados de la votación:",
"notifications.column_settings.push": "Notificaciones push",
"notifications.column_settings.reblog": "Retoots:",
"notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Mostrar en columna",
"notifications.column_settings.sound": "Reproducir sonido",
"notifications.column_settings.status": "Nuevas publicaciones:",
@ -577,7 +575,7 @@
"notifications.column_settings.unread_notifications.highlight": "Destacar notificaciones no leídas",
"notifications.column_settings.update": "Ediciones:",
"notifications.filter.all": "Todos",
"notifications.filter.boosts": "Retoots",
"notifications.filter.boosts": "Impulsos",
"notifications.filter.favourites": "Favoritos",
"notifications.filter.follows": "Seguidores",
"notifications.filter.mentions": "Menciones",
@ -623,7 +621,7 @@
"onboarding.profile.display_name_hint": "Tu nombre completo o tu apodo…",
"onboarding.profile.lead": "Siempre puedes completar esto más tarde en los ajustes, donde hay aún más opciones de personalización disponibles.",
"onboarding.profile.note": "Biografía",
"onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #hashtags…",
"onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #etiquetas…",
"onboarding.profile.save_and_continue": "Guardar y continuar",
"onboarding.profile.title": "Configuración del perfil",
"onboarding.profile.upload_avatar": "Subir foto de perfil",
@ -641,7 +639,7 @@
"onboarding.steps.publish_status.title": "Escribe tu primera publicación",
"onboarding.steps.setup_profile.body": "Si rellenas tu perfil tendrás más posibilidades de que otros interactúen contigo.",
"onboarding.steps.setup_profile.title": "Personaliza tu perfil",
"onboarding.steps.share_profile.body": "¡Dile a tus amigos cómo encontrarte en Mastodon!",
"onboarding.steps.share_profile.body": "Dile a tus amigos cómo encontrarte en Mastodon",
"onboarding.steps.share_profile.title": "Comparte tu perfil",
"onboarding.tips.2fa": "<strong>¿Sabías que?</strong> Puedes proteger tu cuenta configurando la autenticación de dos factores en la configuración de su cuenta. Funciona con cualquier aplicación TOTP de su elección, ¡no necesitas número de teléfono!",
"onboarding.tips.accounts_from_other_servers": "<strong>¿Sabías que?</strong> Como Mastodon es descentralizado, algunos perfiles que encuentras están alojados en servidores distintos del tuyo. Y sin embargo, ¡puedes interactuar con ellos! ¡Su servidor corresponde a la segunda mitad de su nombre de usuario!",
@ -667,7 +665,7 @@
"privacy.private.short": "Seguidores",
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
"privacy.public.short": "Público",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que el post no aparecerá en las cronologías en directo o en los hashtags, la exploración o busquedas en Mastodon, incluso si está optado por activar la cuenta de usuario.",
"privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que el post no aparecerá en las cronologías en directo o en las etiquetas, la exploración o busquedas en Mastodon, incluso si está optado por activar la cuenta de usuario.",
"privacy.unlisted.long": "Menos fanfares algorítmicos",
"privacy.unlisted.short": "Público silencioso",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
@ -701,7 +699,7 @@
"report.category.title_account": "perfil",
"report.category.title_status": "publicación",
"report.close": "Realizado",
"report.comment.title": "¿Hay algo más que usted cree que debamos saber?",
"report.comment.title": "¿Hay algo más que creas que deberíamos saber?",
"report.forward": "Reenviar a {target}",
"report.forward_hint": "Esta cuenta es de otro servidor. ¿Enviar una copia anonimizada del informe allí también?",
"report.mute": "Silenciar",
@ -778,9 +776,9 @@
"status.admin_status": "Abrir este estado en la interfaz de moderación",
"status.block": "Bloquear a @{name}",
"status.bookmark": "Añadir marcador",
"status.cancel_reblog_private": "Eliminar retoot",
"status.cannot_reblog": "Este toot no puede retootearse",
"status.continued_thread": "Continuó el hilo",
"status.cancel_reblog_private": "Deshacer impulso",
"status.cannot_reblog": "Esta publicación no puede ser impulsada",
"status.continued_thread": "Hilo continuado",
"status.copy": "Copiar enlace al estado",
"status.delete": "Borrar",
"status.detailed_status": "Vista de conversación detallada",
@ -789,6 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} time} other {{count} veces}}",
"status.embed": "Obtener código para incrustar",
"status.favourite": "Favorito",
"status.favourites": "{count, plural, one {favorito} other {favoritos}}",
"status.filter": "Filtrar esta publicación",
@ -804,16 +803,16 @@
"status.mute_conversation": "Silenciar conversación",
"status.open": "Expandir estado",
"status.pin": "Fijar",
"status.pinned": "Toot fijado",
"status.pinned": "Publicación fijada",
"status.read_more": "Leer más",
"status.reblog": "Retootear",
"status.reblog": "Impulsar",
"status.reblog_private": "Implusar a la audiencia original",
"status.reblogged_by": "Retooteado por {name}",
"status.reblogged_by": "Impulsado por {name}",
"status.reblogs": "{count, plural, one {impulso} other {impulsos}}",
"status.reblogs.empty": "Nadie retooteó este toot todavía. Cuando alguien lo haga, aparecerá aquí.",
"status.reblogs.empty": "Nadie impulsó esta publicación todavía. Cuando alguien lo haga, aparecerá aquí.",
"status.redraft": "Borrar y volver a borrador",
"status.remove_bookmark": "Eliminar marcador",
"status.replied_in_thread": "Respondió en el hilo",
"status.replied_in_thread": "Respondido en el hilo",
"status.replied_to": "Respondió a {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Nadie de este servidor puede seguirte.",
"domain_block_modal.they_wont_know": "No sabrán que han sido bloqueados.",
"domain_block_modal.title": "¿Bloquear dominio?",
"domain_block_modal.you_will_lose_followers": "Se eliminarán todos tus seguidores de este servidor.",
"domain_block_modal.you_will_lose_num_followers": "Perderás {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} y {followingCount, plural, one {{followingCountDisplay} persona a la que sigues} other {{followingCountDisplay} personas a las que sigues}}.",
"domain_block_modal.you_wont_see_posts": "No verás mensajes ni notificaciones de usuarios en este servidor.",
"domain_pill.activitypub_lets_connect": "Te permite conectar e interactuar con personas no sólo en Mastodon, sino también a través de diferentes aplicaciones sociales.",
"domain_pill.activitypub_like_language": "ActivityPub es como el idioma que Mastodon habla con otras redes sociales.",
@ -267,7 +267,7 @@
"empty_column.favourites": "Todavía nadie marcó esta publicación como favorita. Cuando alguien lo haga, se mostrarán aquí.",
"empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
"empty_column.followed_tags": "No has seguido ninguna etiqueta todavía. Cuando lo hagas, se mostrarán aquí.",
"empty_column.hashtag": "No hay nada en este hashtag aún.",
"empty_column.hashtag": "No hay nada en esta etiqueta todavía.",
"empty_column.home": "¡Tu línea temporal está vacía! Sigue a más personas para rellenarla.",
"empty_column.list": "Aún no hay nada en esta lista. Cuando los miembros de esta lista publiquen nuevos estados, estos aparecerán aquí.",
"empty_column.lists": "No tienes ninguna lista. Cuando crees una, se mostrará aquí.",
@ -342,7 +342,7 @@
"hashtag.column_header.tag_mode.any": "o {additional}",
"hashtag.column_header.tag_mode.none": "sin {additional}",
"hashtag.column_settings.select.no_options_message": "No se encontraron sugerencias",
"hashtag.column_settings.select.placeholder": "Introduzca hashtags…",
"hashtag.column_settings.select.placeholder": "Introduce etiquetas…",
"hashtag.column_settings.tag_mode.all": "Todos estos",
"hashtag.column_settings.tag_mode.any": "Cualquiera de estos",
"hashtag.column_settings.tag_mode.none": "Ninguno de estos",
@ -376,7 +376,7 @@
"ignore_notifications_modal.ignore": "Ignorar notificaciones",
"ignore_notifications_modal.limited_accounts_title": "¿Ignorar notificaciones de cuentas moderadas?",
"ignore_notifications_modal.new_accounts_title": "¿Ignorar notificaciones de cuentas nuevas?",
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te sigue?",
"ignore_notifications_modal.not_followers_title": "¿Ignorar notificaciones de personas que no te siguen?",
"ignore_notifications_modal.not_following_title": "¿Ignorar notificaciones de personas a las que no sigues?",
"ignore_notifications_modal.private_mentions_title": "¿Ignorar notificaciones de menciones privadas no solicitadas?",
"interaction_modal.description.favourite": "Con una cuenta en Mastodon, puedes marcar como favorita esta publicación para que el autor sepa que te gusta, y guardala para más adelante.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
"keyboard_shortcuts.up": "para ir hacia arriba en la lista",
"lightbox.close": "Cerrar",
"lightbox.compress": "Comprimir cuadro de visualización de imagen",
"lightbox.expand": "Expandir cuadro de visualización de imagen",
"lightbox.next": "Siguiente",
"lightbox.previous": "Anterior",
"lightbox.zoom_in": "Ampliar al tamaño real",
"lightbox.zoom_out": "Ampliar para ajustar",
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Nuevos informes:",
"notifications.column_settings.admin.sign_up": "Nuevos registros:",
"notifications.column_settings.alert": "Notificaciones de escritorio",
"notifications.column_settings.beta.category": "Características experimentales",
"notifications.column_settings.beta.grouping": "Agrupar notificaciones",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas las categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",
@ -639,7 +637,7 @@
"onboarding.steps.follow_people.title": "Personaliza tu línea de inicio",
"onboarding.steps.publish_status.body": "Di hola al mundo con texto, fotos, vídeos o encuestas {emoji}",
"onboarding.steps.publish_status.title": "Escribe tu primera publicación",
"onboarding.steps.setup_profile.body": "Aumenta tus interacciones tcompletando tu perfil.",
"onboarding.steps.setup_profile.body": "Aumenta tus interacciones con un perfil completo.",
"onboarding.steps.setup_profile.title": "Personaliza tu perfil",
"onboarding.steps.share_profile.body": "¡Dile a tus amigos cómo encontrarte en Mastodon!",
"onboarding.steps.share_profile.title": "Comparte tu perfil de Mastodon",
@ -789,6 +787,7 @@
"status.edit": "Editar",
"status.edited": "Última edición {date}",
"status.edited_x_times": "Editado {count, plural, one {{count} vez} other {{count} veces}}",
"status.embed": "Obtener código para incrustar",
"status.favourite": "Favorito",
"status.favourites": "{count, plural, one {favorito} other {favoritos}}",
"status.filter": "Filtrar esta publicación",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Sellest serverist ei saa keegi sind jälgida.",
"domain_block_modal.they_wont_know": "Nad ei tea, et nad on blokeeritud.",
"domain_block_modal.title": "Blokeerida domeen?",
"domain_block_modal.you_will_lose_followers": "Kõik sinu sellest serverist pärit jälgijad eemaldatakse.",
"domain_block_modal.you_wont_see_posts": "Sa ei näe selle serveri kasutajate postitusi ega teavitusi.",
"domain_pill.activitypub_lets_connect": "See võimaldab sul ühenduda inimestega ja nendega suhelda mitte ainult Mastodonis, vaid ka teistes suhtlusrakendustes.",
"domain_pill.activitypub_like_language": "ActivityPub on nagu keel, mida Mastodon räägib teiste suhtlusvõrgustikega.",
@ -432,8 +431,6 @@
"keyboard_shortcuts.unfocus": "Fookus tekstialalt/otsingult ära",
"keyboard_shortcuts.up": "Liigu loetelus üles",
"lightbox.close": "Sulge",
"lightbox.compress": "Suru kokku pildi vaatamise kast",
"lightbox.expand": "Laienda pildi vaatamise kast",
"lightbox.next": "Järgmine",
"lightbox.previous": "Eelmine",
"limited_account_hint.action": "Näita profilli sellegipoolest",
@ -457,6 +454,7 @@
"lists.subheading": "Sinu nimekirjad",
"load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}",
"loading_indicator.label": "Laadimine…",
"media_gallery.hide": "Peida",
"moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.",
"mute_modal.hide_from_notifications": "Peida teavituste hulgast",
"mute_modal.hide_options": "Peida valikud",
@ -558,8 +556,6 @@
"notifications.column_settings.admin.report": "Uued teavitused:",
"notifications.column_settings.admin.sign_up": "Uued kasutajad:",
"notifications.column_settings.alert": "Töölauateated",
"notifications.column_settings.beta.category": "Eksperimentaalsed oskused",
"notifications.column_settings.beta.grouping": "Teavituste rühmitamine",
"notifications.column_settings.favourite": "Lemmikud:",
"notifications.column_settings.filter_bar.advanced": "Näita kõiki kategooriaid",
"notifications.column_settings.filter_bar.category": "Kiirfiltri riba",
@ -779,6 +775,7 @@
"status.bookmark": "Järjehoidja",
"status.cancel_reblog_private": "Lõpeta jagamine",
"status.cannot_reblog": "Seda postitust ei saa jagada",
"status.continued_thread": "Jätkatud lõim",
"status.copy": "Kopeeri postituse link",
"status.delete": "Kustuta",
"status.detailed_status": "Detailne vestluskuva",
@ -787,6 +784,7 @@
"status.edit": "Muuda",
"status.edited": "Viimati muudetud {date}",
"status.edited_x_times": "Muudetud {count, plural, one{{count} kord} other {{count} korda}}",
"status.embed": "Hangi manustamiskood",
"status.favourite": "Lemmik",
"status.favourites": "{count, plural, one {lemmik} other {lemmikud}}",
"status.filter": "Filtreeri seda postitust",
@ -811,6 +809,7 @@
"status.reblogs.empty": "Keegi pole seda postitust veel jaganud. Kui keegi seda teeb, näeb seda siin.",
"status.redraft": "Kustuta & alga uuesti",
"status.remove_bookmark": "Eemalda järjehoidja",
"status.replied_in_thread": "Vastatud lõimes",
"status.replied_to": "Vastas kasutajale {name}",
"status.reply": "Vasta",
"status.replyAll": "Vasta lõimele",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Zerbitzari honetako inork ezin zaitu jarraitu.",
"domain_block_modal.they_wont_know": "Ez dute jakingo blokeatuak izan direnik.",
"domain_block_modal.title": "Domeinua blokeatu nahi duzu?",
"domain_block_modal.you_will_lose_followers": "Zerbitzari honetako jarraitzaile guztiak kenduko dira.",
"domain_block_modal.you_wont_see_posts": "Ez dituzu zerbitzari honetako erabiltzaileen argitalpenik edota jakinarazpenik ikusiko.",
"domain_pill.activitypub_lets_connect": "Mastodon-en ez ezik, beste sare sozialen aplikazioetako jendearekin konektatzea eta harremanetan jartzea uzten dizu.",
"domain_pill.activitypub_like_language": "ActivityPub, Mastodon-ek beste sare sozialekin hitz egiteko erabiltzen duen hizkuntza bezalakoxea da.",
@ -432,8 +431,6 @@
"keyboard_shortcuts.unfocus": "testua konposatzeko area / bilaketatik fokua kentzea",
"keyboard_shortcuts.up": "zerrendan gora mugitzea",
"lightbox.close": "Itxi",
"lightbox.compress": "Konprimatu irudia ikusteko kaxa",
"lightbox.expand": "Zabaldu irudia ikusteko kaxa",
"lightbox.next": "Hurrengoa",
"lightbox.previous": "Aurrekoa",
"limited_account_hint.action": "Erakutsi profila hala ere",
@ -457,6 +454,7 @@
"lists.subheading": "Zure zerrendak",
"load_pending": "{count, plural, one {elementu berri #} other {# elementu berri}}",
"loading_indicator.label": "Kargatzen…",
"media_gallery.hide": "Ezkutatu",
"moved_to_account_banner.text": "Zure {disabledAccount} kontua desgaituta dago une honetan, {movedToAccount} kontura aldatu zinelako.",
"mute_modal.hide_from_notifications": "Ezkutatu jakinarazpenetatik",
"mute_modal.hide_options": "Ezkutatu aukerak",
@ -554,8 +552,6 @@
"notifications.column_settings.admin.report": "Txosten berriak:",
"notifications.column_settings.admin.sign_up": "Izen-emate berriak:",
"notifications.column_settings.alert": "Mahaigaineko jakinarazpenak",
"notifications.column_settings.beta.category": "Ezaugarri esperimentalak",
"notifications.column_settings.beta.grouping": "Multzokatu jakinarazpenak",
"notifications.column_settings.favourite": "Gogokoak:",
"notifications.column_settings.filter_bar.advanced": "Bistaratu kategoria guztiak",
"notifications.column_settings.filter_bar.category": "Iragazki-barra bizkorra",
@ -775,6 +771,7 @@
"status.bookmark": "Laster-marka",
"status.cancel_reblog_private": "Kendu bultzada",
"status.cannot_reblog": "Bidalketa honi ezin zaio bultzada eman",
"status.continued_thread": "Harian jarraitu zuen",
"status.copy": "Kopiatu bidalketaren esteka",
"status.delete": "Ezabatu",
"status.detailed_status": "Elkarrizketaren ikuspegi xehetsua",
@ -783,6 +780,7 @@
"status.edit": "Editatu",
"status.edited": "Azken edizioa: {date}",
"status.edited_x_times": "{count, plural, one {behin} other {{count} aldiz}} editatua",
"status.embed": "Lortu txertatzeko kodea",
"status.favourite": "Gogokoa",
"status.favourites": "{count, plural, one {gogoko} other {gogoko}}",
"status.filter": "Iragazi bidalketa hau",
@ -807,6 +805,7 @@
"status.reblogs.empty": "Inork ez dio bultzada eman bidalketa honi oraindik. Inork egiten badu, hemen agertuko da.",
"status.redraft": "Ezabatu eta berridatzi",
"status.remove_bookmark": "Kendu laster-marka",
"status.replied_in_thread": "Harian erantzun zuen",
"status.replied_to": "{name} erabiltzaileari erantzuna",
"status.reply": "Erantzun",
"status.replyAll": "Erantzun harian",

View file

@ -220,7 +220,6 @@
"domain_block_modal.they_cant_follow": "هیچ‌کسی از این کارساز نمی‌تواند پیتان بگیرد.",
"domain_block_modal.they_wont_know": "نخواهند دانست که مسدود شده‌اند.",
"domain_block_modal.title": "انسداد دامنه؟",
"domain_block_modal.you_will_lose_followers": "همهٔ پی‌گیرندگانتان از این کارساز برداشته خواهند شد.",
"domain_block_modal.you_wont_see_posts": "فرسته‌ها یا آگاهی‌ها از کاربران روی این کارساز را نخواهید دید.",
"domain_pill.server": "کارساز",
"domain_pill.their_handle": "شناسه‌اش:",
@ -422,8 +421,6 @@
"keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جست‌وجو",
"keyboard_shortcuts.up": "بالا بردن در سیاهه",
"lightbox.close": "بستن",
"lightbox.compress": "فشرده‌سازی جعبهٔ نمایش تصویر",
"lightbox.expand": "گسترش جعبهٔ نمایش تصویر",
"lightbox.next": "بعدی",
"lightbox.previous": "قبلی",
"limited_account_hint.action": "به هر روی نمایه نشان داده شود",
@ -534,8 +531,6 @@
"notifications.column_settings.admin.report": "گزارش‌های جدید:",
"notifications.column_settings.admin.sign_up": "ثبت نام‌های جدید:",
"notifications.column_settings.alert": "آگاهی‌های میزکار",
"notifications.column_settings.beta.category": "ویژگی‌های آزمایشی",
"notifications.column_settings.beta.grouping": "گروه‌بندی آگاهی‌ها",
"notifications.column_settings.favourite": "برگزیده‌ها:",
"notifications.column_settings.filter_bar.advanced": "نمایش همۀ دسته‌ها",
"notifications.column_settings.filter_bar.category": "نوار پالایش سریع",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Kukaan tältä palvelimelta ei voi seurata sinua.",
"domain_block_modal.they_wont_know": "Hän ei saa tietää tulleensa estetyksi.",
"domain_block_modal.title": "Estetäänkö verkkotunnus?",
"domain_block_modal.you_will_lose_followers": "Kaikki seuraajasi tältä palvelimelta poistetaan.",
"domain_block_modal.you_wont_see_posts": "Et enää näe julkaisuja etkä ilmoituksia tämän palvelimen käyttäjiltä.",
"domain_pill.activitypub_lets_connect": "Sen avulla voit muodostaa yhteyden ja olla vuorovaikutuksessa ihmisten kanssa, ei vain Mastodonissa vaan myös muissa sosiaalisissa sovelluksissa.",
"domain_pill.activitypub_like_language": "ActivityPub on kuin kieli, jota Mastodon puhuu muiden sosiaalisten verkostojen kanssa.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Poistu kirjoitus- tai hakukentästä",
"keyboard_shortcuts.up": "Siirry luettelossa taaksepäin",
"lightbox.close": "Sulje",
"lightbox.compress": "Tiivis kuvankatselunäkymä",
"lightbox.expand": "Laajennettu kuvankatselunäkymä",
"lightbox.next": "Seuraava",
"lightbox.previous": "Edellinen",
"lightbox.zoom_in": "Zoomaa todelliseen kokoon",
"lightbox.zoom_out": "Zoomaa mahtumaan",
"limited_account_hint.action": "Näytä profiili joka tapauksessa",
"limited_account_hint.title": "Palvelimen {domain} moderaattorit ovat piilottaneet tämän profiilin.",
"link_preview.author": "Tehnyt {name}",
@ -559,8 +558,6 @@
"notifications.column_settings.admin.report": "Uudet raportit:",
"notifications.column_settings.admin.sign_up": "Uudet rekisteröitymiset:",
"notifications.column_settings.alert": "Työpöytäilmoitukset",
"notifications.column_settings.beta.category": "Kokeelliset ominaisuudet",
"notifications.column_settings.beta.grouping": "Ryhmittele ilmoitukset",
"notifications.column_settings.favourite": "Suosikit:",
"notifications.column_settings.filter_bar.advanced": "Näytä kaikki luokat",
"notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki",

View file

@ -134,7 +134,6 @@
"dismissable_banner.public_timeline": "Ito ang mga pinakamakailang nakapublikong post mula sa mga taong nasa social web na sinusundan ng mga tao sa {domain}.",
"domain_block_modal.block": "Harangan ang serbiro",
"domain_block_modal.title": "Harangan ang domain?",
"domain_block_modal.you_will_lose_followers": "Mabubura ang iyong mga tagasunod mula sa serbirong ito.",
"domain_pill.server": "Serbiro",
"embed.instructions": "I-embed ang post na ito sa iyong pook-sapot sa pamamagitan ng pagsipi ng kodigo sa ilalim.",
"embed.preview": "Ito ang magiging itsura:",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Eingin frá hesum ambætara kann fylgja tær.",
"domain_block_modal.they_wont_know": "Tey vita ikki, at tey eru bannað.",
"domain_block_modal.title": "Banna økisnavni?",
"domain_block_modal.you_will_lose_followers": "Allir tínir fylgjarar á hesum ambætara hvørva.",
"domain_block_modal.you_will_lose_num_followers": "Tú missir {followersCount, plural, one {{followersCountDisplay} fylgjara} other {{followersCountDisplay} fylgjarar}} og {followingCount, plural, one {{followingCountDisplay} persón, sum tú fylgir} other {{followingCountDisplay} persónar, sum tú fylgir}}.",
"domain_block_modal.you_wont_see_posts": "Tú sært ongar postar ella boð frá brúkarum á hesum ambætara.",
"domain_pill.activitypub_lets_connect": "Tað letur teg fáa samband og samvirka við fólki ikki bara á Mastodon, men á øðrum sosialum appum eisini.",
"domain_pill.activitypub_like_language": "ActivityPub er málið, sum Mastodon tosar við onnur sosial netverk.",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Tak skrivi-/leiti-økið úr miðdeplinum",
"keyboard_shortcuts.up": "Flyt upp á listanum",
"lightbox.close": "Lat aftur",
"lightbox.compress": "Kroyst myndavísikassa saman",
"lightbox.expand": "Víðka myndavísikassa",
"lightbox.next": "Fram",
"lightbox.previous": "Aftur",
"lightbox.zoom_in": "Suma til veruliga stødd",
"lightbox.zoom_out": "Suma, so tað passar",
"limited_account_hint.action": "Vís vangamynd kortini",
"limited_account_hint.title": "Hesin vangin er fjaldur av kjakleiðarunum á {domain}.",
"link_preview.author": "Av {name}",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Nýggjar fráboðanir:",
"notifications.column_settings.admin.sign_up": "Nýggjar tilmeldingar:",
"notifications.column_settings.alert": "Skriviborðsfráboðanir",
"notifications.column_settings.beta.category": "Royndarhentleikar",
"notifications.column_settings.beta.grouping": "Bólkafráboðanir",
"notifications.column_settings.favourite": "Dámdir postar:",
"notifications.column_settings.filter_bar.advanced": "Vís allar bólkar",
"notifications.column_settings.filter_bar.category": "Skjótfilturbjálki",
@ -789,6 +787,7 @@
"status.edit": "Rætta",
"status.edited": "Seinast broytt {date}",
"status.edited_x_times": "Rættað {count, plural, one {{count} ferð} other {{count} ferð}}",
"status.embed": "Fá kodu at seta inn",
"status.favourite": "Dámdur postur",
"status.favourites": "{count, plural, one {yndispostur} other {yndispostar}}",
"status.filter": "Filtrera hendan postin",

View file

@ -36,6 +36,7 @@
"account.followers.empty": "Personne ne suit ce compte pour l'instant.",
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
"account.following": "Abonné·e",
"account.following_counter": "{count, plural, one {{counter} abonnement} other {{counter} abonnements}}",
"account.follows.empty": "Ce compte ne suit personne présentement.",
"account.go_to_profile": "Voir ce profil",
"account.hide_reblogs": "Masquer les boosts de @{name}",
@ -163,7 +164,7 @@
"compose_form.publish": "Publier",
"compose_form.publish_form": "Publier",
"compose_form.reply": "Répondre",
"compose_form.save_changes": "Mis à jour",
"compose_form.save_changes": "Mettre à jour",
"compose_form.spoiler.marked": "Enlever l'avertissement de contenu",
"compose_form.spoiler.unmarked": "Ajouter un avertissement de contenu",
"compose_form.spoiler_placeholder": "Avertissement de contenu (optionnel)",
@ -220,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Personne de ce serveur ne peut vous suivre.",
"domain_block_modal.they_wont_know": "Il ne saura pas qu'il a été bloqué.",
"domain_block_modal.title": "Bloquer le domaine ?",
"domain_block_modal.you_will_lose_followers": "Tous vos abonnés de ce serveur seront supprimés.",
"domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.",
"domain_pill.activitypub_lets_connect": "Cela vous permet de vous connecter et d'interagir avec les autres non seulement sur Mastodon, mais également sur d'autres applications de réseaux sociaux.",
"domain_pill.activitypub_like_language": "ActivityPub est comme une langue que Mastodon utilise pour communiquer avec les autres réseaux sociaux.",
@ -311,7 +311,7 @@
"follow_request.authorize": "Autoriser",
"follow_request.reject": "Rejeter",
"follow_requests.unlocked_explanation": "Même si votre compte nest pas privé, léquipe de {domain} a pensé que vous pourriez vouloir peut-être consulter manuellement les demandes d'abonnement de ces comptes.",
"follow_suggestions.curated_suggestion": "Choix du staff",
"follow_suggestions.curated_suggestion": "Sélectionné par l'équipe",
"follow_suggestions.dismiss": "Ne plus afficher",
"follow_suggestions.featured_longer": "Sélectionné par l'équipe de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populaire dans le cercle des personnes que vous suivez",
@ -431,8 +431,6 @@
"keyboard_shortcuts.unfocus": "Ne plus se concentrer sur la zone de rédaction/barre de recherche",
"keyboard_shortcuts.up": "Monter dans la liste",
"lightbox.close": "Fermer",
"lightbox.compress": "Compresser la fenêtre de visualisation d'images",
"lightbox.expand": "Agrandir la fenêtre de visualisation d'images",
"lightbox.next": "Suivant",
"lightbox.previous": "Précédent",
"limited_account_hint.action": "Afficher le profil quand même",
@ -558,8 +556,6 @@
"notifications.column_settings.admin.report": "Nouveaux signalements:",
"notifications.column_settings.admin.sign_up": "Nouvelles inscriptions:",
"notifications.column_settings.alert": "Notifications navigateur",
"notifications.column_settings.beta.category": "Fonctionnalités expérimentales",
"notifications.column_settings.beta.grouping": "Grouper les notifications",
"notifications.column_settings.favourite": "Favoris:",
"notifications.column_settings.filter_bar.advanced": "Afficher toutes les catégories",
"notifications.column_settings.filter_bar.category": "Barre de filtre rapide",
@ -788,6 +784,7 @@
"status.edit": "Modifier",
"status.edited": "Dernière modification le {date}",
"status.edited_x_times": "Modifiée {count, plural, one {{count} fois} other {{count} fois}}",
"status.embed": "Obtenir le code d'intégration",
"status.favourite": "Ajouter aux favoris",
"status.favourites": "{count, plural, one {favori} other {favoris}}",
"status.filter": "Filtrer cette publication",
@ -812,6 +809,7 @@
"status.reblogs.empty": "Personne na encore boosté cette publication. Lorsque quelquun le fera, elle apparaîtra ici.",
"status.redraft": "Supprimer et réécrire",
"status.remove_bookmark": "Retirer des signets",
"status.replied_in_thread": "A répondu dans un fil de discussion",
"status.replied_to": "A répondu à {name}",
"status.reply": "Répondre",
"status.replyAll": "Répondre à cette discussion",

View file

@ -36,6 +36,7 @@
"account.followers.empty": "Personne ne suit cet·te utilisateur·rice pour linstant.",
"account.followers_counter": "{count, plural, one {{counter} abonné·e} other {{counter} abonné·e·s}}",
"account.following": "Abonnements",
"account.following_counter": "{count, plural, one {{counter} abonnement} other {{counter} abonnements}}",
"account.follows.empty": "Cet·te utilisateur·rice ne suit personne pour linstant.",
"account.go_to_profile": "Aller au profil",
"account.hide_reblogs": "Masquer les partages de @{name}",
@ -163,7 +164,7 @@
"compose_form.publish": "Publier",
"compose_form.publish_form": "Nouvelle publication",
"compose_form.reply": "Répondre",
"compose_form.save_changes": "Mis à jour",
"compose_form.save_changes": "Mettre à jour",
"compose_form.spoiler.marked": "Enlever lavertissement de contenu",
"compose_form.spoiler.unmarked": "Ajouter un avertissement de contenu",
"compose_form.spoiler_placeholder": "Avertissement de contenu (optionnel)",
@ -220,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Personne de ce serveur ne peut vous suivre.",
"domain_block_modal.they_wont_know": "Il ne saura pas qu'il a été bloqué.",
"domain_block_modal.title": "Bloquer le domaine ?",
"domain_block_modal.you_will_lose_followers": "Tous vos abonnés de ce serveur seront supprimés.",
"domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.",
"domain_pill.activitypub_lets_connect": "Cela vous permet de vous connecter et d'interagir avec les autres non seulement sur Mastodon, mais également sur d'autres applications de réseaux sociaux.",
"domain_pill.activitypub_like_language": "ActivityPub est comme une langue que Mastodon utilise pour communiquer avec les autres réseaux sociaux.",
@ -311,7 +311,7 @@
"follow_request.authorize": "Accepter",
"follow_request.reject": "Rejeter",
"follow_requests.unlocked_explanation": "Même si votre compte nest pas privé, léquipe de {domain} a pensé que vous pourriez vouloir consulter manuellement les demandes de suivi de ces comptes.",
"follow_suggestions.curated_suggestion": "Choix du staff",
"follow_suggestions.curated_suggestion": "Sélectionné par l'équipe",
"follow_suggestions.dismiss": "Ne plus afficher",
"follow_suggestions.featured_longer": "Sélectionné par l'équipe de {domain}",
"follow_suggestions.friends_of_friends_longer": "Populaire dans le cercle des personnes que vous suivez",
@ -431,8 +431,6 @@
"keyboard_shortcuts.unfocus": "Quitter la zone de rédaction/barre de recherche",
"keyboard_shortcuts.up": "Monter dans la liste",
"lightbox.close": "Fermer",
"lightbox.compress": "Compresser la fenêtre de visualisation des images",
"lightbox.expand": "Agrandir la fenêtre de visualisation des images",
"lightbox.next": "Suivant",
"lightbox.previous": "Précédent",
"limited_account_hint.action": "Afficher le profil quand même",
@ -558,8 +556,6 @@
"notifications.column_settings.admin.report": "Nouveaux signalements :",
"notifications.column_settings.admin.sign_up": "Nouvelles inscriptions :",
"notifications.column_settings.alert": "Notifications du navigateur",
"notifications.column_settings.beta.category": "Fonctionnalités expérimentales",
"notifications.column_settings.beta.grouping": "Grouper les notifications",
"notifications.column_settings.favourite": "Favoris :",
"notifications.column_settings.filter_bar.advanced": "Afficher toutes les catégories",
"notifications.column_settings.filter_bar.category": "Barre de filtre rapide",
@ -788,6 +784,7 @@
"status.edit": "Modifier",
"status.edited": "Dernière modification le {date}",
"status.edited_x_times": "Modifié {count, plural, one {{count} fois} other {{count} fois}}",
"status.embed": "Obtenir le code d'intégration",
"status.favourite": "Ajouter aux favoris",
"status.favourites": "{count, plural, one {favori} other {favoris}}",
"status.filter": "Filtrer ce message",
@ -812,6 +809,7 @@
"status.reblogs.empty": "Personne na encore partagé ce message. Lorsque quelquun le fera, il apparaîtra ici.",
"status.redraft": "Supprimer et réécrire",
"status.remove_bookmark": "Retirer des marque-pages",
"status.replied_in_thread": "A répondu dans un fil de discussion",
"status.replied_to": "En réponse à {name}",
"status.reply": "Répondre",
"status.replyAll": "Répondre au fil",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Net ien op dizze server kin jo folgje.",
"domain_block_modal.they_wont_know": "Se krije net te witten dat se blokkearre wurde.",
"domain_block_modal.title": "Domein blokkearje?",
"domain_block_modal.you_will_lose_followers": "Al jo folgers fan dizze server wurde ûntfolge.",
"domain_block_modal.you_wont_see_posts": "Jo sjogge gjin berjochten of meldingen mear fan brûkers op dizze server.",
"domain_pill.activitypub_lets_connect": "It soarget derfoar dat jo net allinnich mar ferbine en kommunisearje kinne mei minsken op Mastodon, mar ek mei oare sosjale apps.",
"domain_pill.activitypub_like_language": "ActivityPub is de taal dyt Mastodon mei oare sosjale netwurken sprekt.",
@ -432,8 +431,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "Nei boppe yn list ferpleatse",
"lightbox.close": "Slute",
"lightbox.compress": "Ofbylding passend werjaan",
"lightbox.expand": "Ofbylding grut werjaan",
"lightbox.next": "Folgjende",
"lightbox.previous": "Foarige",
"limited_account_hint.action": "Profyl dochs besjen",
@ -558,8 +555,6 @@
"notifications.column_settings.admin.report": "Nije rapportaazjes:",
"notifications.column_settings.admin.sign_up": "Nije registraasjes:",
"notifications.column_settings.alert": "Desktopmeldingen",
"notifications.column_settings.beta.category": "Eksperimintele funksjes",
"notifications.column_settings.beta.grouping": "Notifikaasjes groepearje",
"notifications.column_settings.favourite": "Favoriten:",
"notifications.column_settings.filter_bar.advanced": "Alle kategoryen toane",
"notifications.column_settings.filter_bar.category": "Flugge filterbalke",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Ní féidir le duine ar bith ón bhfreastalaí seo tú a leanúint.",
"domain_block_modal.they_wont_know": "Ní bheidh a fhios acu go bhfuil bac orthu.",
"domain_block_modal.title": "Blocáil fearann?",
"domain_block_modal.you_will_lose_followers": "Bainfear do leantóirí go léir ón bhfreastalaí seo.",
"domain_block_modal.you_wont_see_posts": "Ní fheicfidh tú postálacha nó fógraí ó úsáideoirí ar an bhfreastalaí seo.",
"domain_pill.activitypub_lets_connect": "Ligeann sé duit ceangal agus idirghníomhú le daoine, ní hamháin ar Mastodon, ach thar aipeanna sóisialta éagsúla freisin.",
"domain_pill.activitypub_like_language": "Tá GníomhaíochtPub cosúil leis an teanga a labhraíonn Mastodon le líonraí sóisialta eile.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Unfocus cum textarea/search",
"keyboard_shortcuts.up": "Bog suas ar an liosta",
"lightbox.close": "Dún",
"lightbox.compress": "Comhbhrúigh an bosca amhairc íomhá",
"lightbox.expand": "Leathnaigh an bosca amhairc íomhá",
"lightbox.next": "An céad eile",
"lightbox.previous": "Roimhe seo",
"lightbox.zoom_in": "Súmáil chuig an méid iarbhír",
"lightbox.zoom_out": "Súmáil a d'oirfeadh",
"limited_account_hint.action": "Taispeáin an phróifíl ar aon nós",
"limited_account_hint.title": "Tá an phróifíl seo curtha i bhfolach ag na modhnóra {domain}.",
"link_preview.author": "Le {name}",
@ -457,6 +456,7 @@
"lists.subheading": "Do liostaí",
"load_pending": "{count, plural, one {# mír nua} two {# mír nua} few {# mír nua} many {# mír nua} other {# mír nua}}",
"loading_indicator.label": "Á lódáil…",
"media_gallery.hide": "Folaigh",
"moved_to_account_banner.text": "Tá do chuntas {disabledAccount} díchumasaithe faoi láthair toisc gur bhog tú go {movedToAccount}.",
"mute_modal.hide_from_notifications": "Folaigh ó fhógraí",
"mute_modal.hide_options": "Folaigh roghanna",
@ -558,8 +558,6 @@
"notifications.column_settings.admin.report": "Tuairiscí nua:",
"notifications.column_settings.admin.sign_up": "Clárúcháin nua:",
"notifications.column_settings.alert": "Fógraí deisce",
"notifications.column_settings.beta.category": "Gnéithe turgnamhacha",
"notifications.column_settings.beta.grouping": "Fógraí grúpa",
"notifications.column_settings.favourite": "Ceanáin:",
"notifications.column_settings.filter_bar.advanced": "Taispeáin gach catagóir",
"notifications.column_settings.filter_bar.category": "Barra scagairí tapa",
@ -779,6 +777,7 @@
"status.bookmark": "Leabharmharcanna",
"status.cancel_reblog_private": "Dímhol",
"status.cannot_reblog": "Ní féidir an phostáil seo a mholadh",
"status.continued_thread": "Snáithe ar lean",
"status.copy": "Cóipeáil an nasc chuig an bpostáil",
"status.delete": "Scrios",
"status.detailed_status": "Amharc comhrá mionsonraithe",
@ -787,6 +786,7 @@
"status.edit": "Cuir in eagar",
"status.edited": "Arna chuir in eagar anuas {date}",
"status.edited_x_times": "Curtha in eagar {count, plural, one {{count} uair amháin} two {{count} uair} few {{count} uair} many {{count} uair} other {{count} uair}}",
"status.embed": "Faigh cód leabú",
"status.favourite": "Is fearr leat",
"status.favourites": "{count, plural, one {a bhfuil grá agat do} two {gráite} few {gráite} many {gráite} other {gráite}}",
"status.filter": "Déan scagadh ar an bpostáil seo",
@ -811,6 +811,7 @@
"status.reblogs.empty": "Níor mhol éinne an phostáil seo fós. Nuair a mholfaidh duine éigin í, taispeánfar anseo é sin.",
"status.redraft": "Scrios ⁊ athdhréachtaigh",
"status.remove_bookmark": "Bain leabharmharc",
"status.replied_in_thread": "D'fhreagair sa snáithe",
"status.replied_to": "D'fhreagair {name}",
"status.reply": "Freagair",
"status.replyAll": "Freagair le snáithe",

View file

@ -36,7 +36,7 @@
"account.followers.empty": "Chan eil neach sam bith a leantainn air a chleachdaiche seo fhathast.",
"account.followers_counter": "{count, plural, one {{counter} neach-leantainn} other {{counter} luchd-leantainn}}",
"account.following": "A leantainn",
"account.following_counter": "{count, plural, one {Tha {counter} a leantainn} other {Tha {counter} a leantainn}}",
"account.following_counter": "{count, plural, one {A leantainn {counter}} other {A leantainn {counter}}}",
"account.follows.empty": "Chan eil an cleachdaiche seo a leantainn neach sam bith fhathast.",
"account.go_to_profile": "Tadhail air a phròifil",
"account.hide_reblogs": "Falaich na brosnachaidhean o @{name}",
@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Chan urrainn do neach sam bith a th air an fhrithealaiche seo do leantainn.",
"domain_block_modal.they_wont_know": "Cha bhi fios aca gun deach am bacadh.",
"domain_block_modal.title": "A bheil thu airson an àrainn a bhacadh?",
"domain_block_modal.you_will_lose_followers": "Thèid a h-uile neach-leantainn agad a th air an fhrithealaiche seo a thoirt air falbh.",
"domain_block_modal.you_wont_see_posts": "Chan fhaic thu postaichean no brathan o chleachdaichean a th air an fhrithealaiche seo.",
"domain_pill.activitypub_lets_connect": "Leigidh e leat ceangal a dhèanamh ri daoine chan ann air Mastodon a-mhàin ach air feadh aplacaidean sòisealta eile cuideachd agus conaltradh leotha.",
"domain_pill.activitypub_like_language": "Tha ActivityPub coltach ri cànan a bhruidhneas Mastodon ri lìonraidhean sòisealta eile.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Thoir am fòcas far raon teacsa an sgrìobhaidh/an luirg",
"keyboard_shortcuts.up": "Gluais suas air an liosta",
"lightbox.close": "Dùin",
"lightbox.compress": "Co-theannaich bogsa sealladh an deilbh",
"lightbox.expand": "Leudaich bogsa sealladh an deilbh",
"lightbox.next": "Air adhart",
"lightbox.previous": "Air ais",
"lightbox.zoom_in": "Sùm dhan fhìor-mheud",
"lightbox.zoom_out": "Sùm fèin-obrachail",
"limited_account_hint.action": "Seall a phròifil co-dhiù",
"limited_account_hint.title": "Chaidh a phròifil seo fhalach le maoir {domain}.",
"link_preview.author": "Le {name}",
@ -457,6 +456,7 @@
"lists.subheading": "Na liostaichean agad",
"load_pending": "{count, plural, one {# nì ùr} two {# nì ùr} few {# nithean ùra} other {# nì ùr}}",
"loading_indicator.label": "Ga luchdadh…",
"media_gallery.hide": "Falaich",
"moved_to_account_banner.text": "Tha an cunntas {disabledAccount} agad à comas on a rinn thu imrich gu {movedToAccount}.",
"mute_modal.hide_from_notifications": "Falaich o na brathan",
"mute_modal.hide_options": "Roghainnean falaich",
@ -558,8 +558,6 @@
"notifications.column_settings.admin.report": "Gearanan ùra:",
"notifications.column_settings.admin.sign_up": "Clàraidhean ùra:",
"notifications.column_settings.alert": "Brathan deasga",
"notifications.column_settings.beta.category": "Gleusan deuchainneil",
"notifications.column_settings.beta.grouping": "Buidhnich na brathan",
"notifications.column_settings.favourite": "Annsachdan:",
"notifications.column_settings.filter_bar.advanced": "Seall a h-uile roinn-seòrsa",
"notifications.column_settings.filter_bar.category": "Bàr-criathraidh luath",
@ -779,6 +777,7 @@
"status.bookmark": "Cuir ris na comharran-lìn",
"status.cancel_reblog_private": "Na brosnaich tuilleadh",
"status.cannot_reblog": "Cha ghabh am post seo brosnachadh",
"status.continued_thread": "Pàirt de shnàithlean",
"status.copy": "Dèan lethbhreac dhen cheangal dhan phost",
"status.delete": "Sguab às",
"status.detailed_status": "Mion-shealladh a chòmhraidh",
@ -787,6 +786,7 @@
"status.edit": "Deasaich",
"status.edited": "An deasachadh mu dheireadh {date}",
"status.edited_x_times": "Chaidh a dheasachadh {count, plural, one {{count} turas} two {{count} thuras} few {{count} tursan} other {{count} turas}}",
"status.embed": "Faigh còd leabachaidh",
"status.favourite": "Cuir ris na h-annsachdan",
"status.favourites": "{count, plural, one {annsachd} two {annsachd} few {annsachdan} other {annsachd}}",
"status.filter": "Criathraich am post seo",
@ -811,6 +811,7 @@
"status.reblogs.empty": "Chan deach am post seo a bhrosnachadh le duine sam bith fhathast. Nuair a bhrosnaicheas cuideigin e, nochdaidh iad an-seo.",
"status.redraft": "Sguab às ⁊ dèan dreachd ùr",
"status.remove_bookmark": "Thoir an comharra-lìn air falbh",
"status.replied_in_thread": "Freagairt do shnàithlean",
"status.replied_to": "Air {name} fhreagairt",
"status.reply": "Freagair",
"status.replyAll": "Freagair dhan t-snàithlean",

View file

@ -221,7 +221,7 @@
"domain_block_modal.they_cant_follow": "Ninguén deste servidor pode seguirte.",
"domain_block_modal.they_wont_know": "Non saberá que a bloqueaches.",
"domain_block_modal.title": "Bloquear dominio?",
"domain_block_modal.you_will_lose_followers": "Vanse eliminar todas as túas seguidoras deste servidor.",
"domain_block_modal.you_will_lose_num_followers": "Vas perder {followersCount, plural, one {{followersCountDisplay} seguidora} other {{followersCountDisplay} seguidoras}} e {followingCount, plural, one {{followingCountDisplay} persoa que segues} other {{followingCountDisplay} persoas que segues}}.",
"domain_block_modal.you_wont_see_posts": "Non verás publicacións ou notificacións das usuarias deste servidor.",
"domain_pill.activitypub_lets_connect": "Permíteche conectar e interactuar con persoas non só de Mastodon, se non tamén con outras sociais.",
"domain_pill.activitypub_like_language": "ActivityPub é algo así como o idioma que Mastodon fala con outras redes sociais.",
@ -368,13 +368,13 @@
"home.pending_critical_update.link": "Mira as actualizacións",
"home.pending_critical_update.title": "Hai una actualización crítica de seguridade!",
"home.show_announcements": "Amosar anuncios",
"ignore_notifications_modal.disclaimer": "Mastodon non pode informar ás usuarias se ignoraches as súas notificacións. Ao ignorar as notificacións non evitarás que as mensaxes sexan enviadas igualmente.",
"ignore_notifications_modal.disclaimer": "Mastodon non pode informar ás usuarias de que ignoraches as súas notificacións. Ao ignorar as notificacións non evitarás que as mensaxes sexan enviadas igualmente.",
"ignore_notifications_modal.filter_instead": "Filtrar igualmente",
"ignore_notifications_modal.filter_to_act_users": "Poderás seguir aceptando, rexeitando e denunciando usuarias",
"ignore_notifications_modal.filter_to_avoid_confusion": "Ao filtrar axudas a evitar posibles confusións",
"ignore_notifications_modal.filter_to_review_separately": "Podes revisar as notificacións filtradas por separado",
"ignore_notifications_modal.filter_to_review_separately": "Podes revisar por separado as notificacións filtradas",
"ignore_notifications_modal.ignore": "Ignorar notificacións",
"ignore_notifications_modal.limited_accounts_title": "Ignorar notificacións desde contas moderadas?",
"ignore_notifications_modal.limited_accounts_title": "Ignorar notificacións desde contas limitadas?",
"ignore_notifications_modal.new_accounts_title": "Ignorar notificacións desde novas contas?",
"ignore_notifications_modal.not_followers_title": "Ignorar notificacións de persoas que non te seguen?",
"ignore_notifications_modal.not_following_title": "Ignorar notificacións de persoas que non segues?",
@ -432,10 +432,10 @@
"keyboard_shortcuts.unfocus": "Para deixar de destacar a área de escritura/procura",
"keyboard_shortcuts.up": "Para mover cara arriba na listaxe",
"lightbox.close": "Fechar",
"lightbox.compress": "Comprimir a caixa de vista da imaxe",
"lightbox.expand": "Estender a caixa de vista da imaxe",
"lightbox.next": "Seguinte",
"lightbox.previous": "Anterior",
"lightbox.zoom_in": "Ver tamaño real",
"lightbox.zoom_out": "Ver tamaño axustado",
"limited_account_hint.action": "Mostrar perfil igualmente",
"limited_account_hint.title": "Este perfil foi agochado pola moderación de {domain}.",
"link_preview.author": "Por {name}",
@ -463,7 +463,7 @@
"mute_modal.hide_options": "Opcións ao ocultar",
"mute_modal.indefinite": "Ata que as reactive",
"mute_modal.show_options": "Mostrar opcións",
"mute_modal.they_can_mention_and_follow": "Pódete mencionar e seguirte, pero non o verás.",
"mute_modal.they_can_mention_and_follow": "Pódete mencionar e seguirte, pero non a verás.",
"mute_modal.they_wont_know": "Non saberá que a acalaches.",
"mute_modal.title": "Acalar usuaria?",
"mute_modal.you_wont_see_mentions": "Non verás as publicacións que a mencionen.",
@ -527,7 +527,7 @@
"notification.poll": "Rematou a enquisa na que votaches",
"notification.reblog": "{name} compartiu a túa publicación",
"notification.reblog.name_and_others_with_link": "{name} e <a>{count, plural, one {# máis} other {# máis}}</a> promoveron a túa publicación",
"notification.relationships_severance_event": "Perdeuse a conexión con {name}",
"notification.relationships_severance_event": "Relacións perdidas con {name}",
"notification.relationships_severance_event.account_suspension": "A administración de {from} suspendeu a {target}, o que significa que xa non vas recibir actualizacións de esa conta ou interactuar con ela.",
"notification.relationships_severance_event.domain_block": "A administración de {from} bloqueou a {target}, que inclúe a {followersCount} das túas seguidoras e a {followingCount, plural, one {# conta} other {# contas}} que sigues.",
"notification.relationships_severance_event.learn_more": "Saber máis",
@ -559,8 +559,6 @@
"notifications.column_settings.admin.report": "Novas denuncias:",
"notifications.column_settings.admin.sign_up": "Novas usuarias:",
"notifications.column_settings.alert": "Notificacións de escritorio",
"notifications.column_settings.beta.category": "Características experimentais",
"notifications.column_settings.beta.grouping": "Notificacións de grupo",
"notifications.column_settings.favourite": "Favoritas:",
"notifications.column_settings.filter_bar.advanced": "Mostrar todas as categorías",
"notifications.column_settings.filter_bar.category": "Barra de filtrado rápido",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "משתמש משרת זה לא יכול לעקוב אחריך.",
"domain_block_modal.they_wont_know": "הם לא ידעו כי נחסמו.",
"domain_block_modal.title": "לחסום שרת?",
"domain_block_modal.you_will_lose_followers": "כל עוקביך משרת זה יוסרו.",
"domain_block_modal.you_wont_see_posts": "לא תוכלו לראות הודעות ממשתמשים על שרת זה.",
"domain_pill.activitypub_lets_connect": "מאפשר לך להתחבר ולהתרועע עם אחרים לא רק במסטודון, אלא גם ביישומים חברתיים שונים אחרים.",
"domain_pill.activitypub_like_language": "אקטיביטיפאב היא למעשה השפה בה מסטודון מדבר עם רשתות חברתיות אחרות.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש",
"keyboard_shortcuts.up": "לנוע במעלה הרשימה",
"lightbox.close": "סגירה",
"lightbox.compress": "דחיסת קופסת צפייה בתמונה",
"lightbox.expand": "הרחבת קופסת צפייה בתמונה",
"lightbox.next": "הבא",
"lightbox.previous": "הקודם",
"lightbox.zoom_in": "הגדלה לגודל מלא",
"lightbox.zoom_out": "התאמה לגודל המסך",
"limited_account_hint.action": "הצג חשבון בכל זאת",
"limited_account_hint.title": "פרופיל המשתמש הזה הוסתר על ידי המנחים של {domain}.",
"link_preview.author": "מאת {name}",
@ -559,8 +558,6 @@
"notifications.column_settings.admin.report": "דו\"חות חדשים",
"notifications.column_settings.admin.sign_up": "הרשמות חדשות:",
"notifications.column_settings.alert": "התראות לשולחן העבודה",
"notifications.column_settings.beta.category": "יכולות ניסיוניות",
"notifications.column_settings.beta.grouping": "התראות קבוצה",
"notifications.column_settings.favourite": "חיבובים:",
"notifications.column_settings.filter_bar.advanced": "להציג את כל הקטגוריות",
"notifications.column_settings.filter_bar.category": "שורת סינון מהיר",
@ -789,6 +786,7 @@
"status.edit": "עריכה",
"status.edited": "נערך לאחרונה {date}",
"status.edited_x_times": "נערך {count, plural, one {פעם {count}} other {{count} פעמים}}",
"status.embed": "העתקת קוד להטמעה",
"status.favourite": "חיבוב",
"status.favourites": "{count, plural, one {חיבוב אחד} two {זוג חיבובים} other {# חיבובים}}",
"status.filter": "סנן הודעה זו",

View file

@ -349,8 +349,6 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "बंद करें",
"lightbox.compress": "कंप्रेस इमेज व्यू बॉक्स",
"lightbox.expand": "एक्सपैंड इमेज व्यू बॉक्स",
"lightbox.next": "अगला",
"lightbox.previous": "पिछला",
"limited_account_hint.action": "फिर भी प्रोफाइल दिखाओ",

View file

@ -221,7 +221,6 @@
"domain_block_modal.they_cant_follow": "Erről a kiszolgálóról senki sem követhet.",
"domain_block_modal.they_wont_know": "Nem fogja tudni, hogy letiltották.",
"domain_block_modal.title": "Letiltsuk a domaint?",
"domain_block_modal.you_will_lose_followers": "Az ezen a kiszolgálón lévő összes követődet törölni fogjuk.",
"domain_block_modal.you_wont_see_posts": "Nem látsz majd bejegyzéseket vagy értesítéseket ennek a kiszolgálónak a felhasználóitól.",
"domain_pill.activitypub_lets_connect": "Lehetővé teszi, hogy kapcsolatba lépj nem csak a Mastodonon, hanem a más közösségi alkalmazásokon lévő emberekkel is.",
"domain_pill.activitypub_like_language": "Az ActivityPub olyan mint egy nyelv, amelyet a Mastodon a más közösségi hálózatokkal való kommunikációra használ.",
@ -432,10 +431,10 @@
"keyboard_shortcuts.unfocus": "Szerkesztés/keresés fókuszból való kivétele",
"keyboard_shortcuts.up": "Mozgás felfelé a listában",
"lightbox.close": "Bezárás",
"lightbox.compress": "Képnéző doboz összezárása",
"lightbox.expand": "Képnéző doboz kinyitása",
"lightbox.next": "Következő",
"lightbox.previous": "Előző",
"lightbox.zoom_in": "Nagyítás a tényleges méretre",
"lightbox.zoom_out": "Méretre igazítás",
"limited_account_hint.action": "Profil megjelenítése mindenképpen",
"limited_account_hint.title": "Ezt a profilt {domain} moderátorai elrejtették.",
"link_preview.author": "{name} szerint",
@ -559,8 +558,6 @@
"notifications.column_settings.admin.report": "Új jelentések:",
"notifications.column_settings.admin.sign_up": "Új regisztrálók:",
"notifications.column_settings.alert": "Asztali értesítések",
"notifications.column_settings.beta.category": "Kísérleti funkciók",
"notifications.column_settings.beta.grouping": "Csoportértesítések",
"notifications.column_settings.favourite": "Kedvencek:",
"notifications.column_settings.filter_bar.advanced": "Minden kategória megjelenítése",
"notifications.column_settings.filter_bar.category": "Gyorsszűrő sáv",

View file

@ -271,8 +271,6 @@
"keyboard_shortcuts.unfocus": "տեքստի/որոնման տիրոյթից ապասեւեռուելու համար",
"keyboard_shortcuts.up": "ցանկով վերեւ շարժուելու համար",
"lightbox.close": "Փակել",
"lightbox.compress": "Փակել պատկերի դիտման պատուհանը",
"lightbox.expand": "Բացել պատկերի դիտման պատուհանը",
"lightbox.next": "Յաջորդ",
"lightbox.previous": "Նախորդ",
"lists.account.add": "Աւելացնել ցանկին",

Some files were not shown because too many files have changed in this diff Show more