diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index f87082013c6572..5c7263c87467d9 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1e0bfcf78061..5eef082cccd83d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,13 @@ 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. +- Fix ReDoS vulnerability on some Ruby versions ([GHSA-jpxp-r43f-rhvx](https://github.com/mastodon/mastodon/security/advisories/GHSA-jpxp-r43f-rhvx)) - Change `form-action` Content-Security-Policy directive to be more restrictive (#26897 by @ClearlyClaire) - Update dependencies ### Added -- **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)\ +- **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, #31929, #32089 and #32085 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.\ @@ -27,7 +28,7 @@ The following changelog entries focus on changes visible to users, administrator - `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)\ +- **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, #31723 and #32062 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.\ @@ -76,7 +77,11 @@ The following changelog entries focus on changes visible to users, administrator 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 ability to reorder uploaded media before posting in web UI** (#28456 and #32093 by @Gargron) +- Add “A Mastodon update is available.” message on admin dashboard for non-bugfix updates (#32106 by @ClearlyClaire) +- Add ability to view alt text by clicking the ALT badge in web UI (#32058 by @Gargron) +- Add preview of followers removed in domain block modal in web UI (#32032 and #32105 by @ClearlyClaire and @Gargron) +- Add reblogs and favourites counts to statuses in ActivityPub (#32007 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)\ This is also exposed through the REST API: https://docs.joinmastodon.org/entities/Instance/#icon @@ -122,14 +127,14 @@ The following changelog entries focus on changes visible to users, administrator - 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 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)\ +- Add support for libvips in addition to ImageMagick (#30090, #30590, #30597, #30632, #30857, #30869, #30858 and #32104 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)\ +- Add OpenTelemetry instrumentation (#30130, #30322, #30353, #30350 and #31998 by @julianocosta89, @renchap, @robbkidd and @timetinytim)\ 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 @@ -138,7 +143,6 @@ The following changelog entries focus on changes visible to users, administrator - 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) @@ -167,15 +171,15 @@ 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, #29659, and #31889 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, #31889 and #32033 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 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 colors throughout the web UI** (#29522, #29584, #29653, #29779, #29803, #29809, #29808, #29828, #31034, #31168, #31266, #31348, #31349, #31361, #31510 and #32128 by @ClearlyClaire, @Gargron, @mjankowski, @renchap, and @vmstan) - **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)\ +- **Change email templates** (#28416, #28755, #28814, #29064, #28883, #29470, #29607, #29761, #29760, #29879, #32073 and #32132 by @c960657, @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)\ This replaces the “past interactions” recommendation algorithm with a “friends of friends” algorithm that suggests accounts followed by people you follow, and a “similar profiles” algorithm that suggests accounts with a profile similar to your most recent follows.\ @@ -188,10 +192,17 @@ The following changelog entries focus on changes visible to users, administrator Administrators may need to update their setup accordingly. - 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 embedded posts to use web UI (#31766 and #32135 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 design of media attachments and profile media tab in web UI (#31807, #32048, and #31967 by @Gargron) - Change labels on thread indicators in web UI (#31806 by @Gargron) +- Change label of "Data export" menu item in settings interface (#32099 by @c960657) +- Change responsive break points on navigation panel in web UI (#32034 by @Gargron) +- Change cursor to `not-allowed` on disabled buttons (#32076 by @mjankowski) +- Change OAuth authorization prompt to not refer to apps as “third-party” (#32005 by @Gargron) +- Change Mastodon to issue correct HTTP signatures by default (#31994 by @ClearlyClaire) +- Change zoom icon in web UI (#29683 by @Gargron) +- Change directory page to use URL query strings for options (#31980, #31977 and #31984 by @ClearlyClaire and @renchap) - 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) @@ -254,6 +265,7 @@ The following changelog entries focus on changes visible to users, administrator ### Removed +- Remove unused E2EE messaging code and related `crypto` OAuth scope (#31193, #31945, #31963, and #31964 by @ClearlyClaire and @mjankowski) - Remove StatsD integration (replaced by OpenTelemetry) (#30240 by @mjankowski) - Remove `CacheBuster` default options (#30718 by @mjankowski) - Remove home marker updates from the Web UI (#22721 by @davbeck)\ @@ -269,9 +281,21 @@ The following changelog entries focus on changes visible to users, administrator - Fix log out from user menu not working on Safari (#31402 by @renchap) - 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 error when accepting an appeal for sensitive posts deleted in the meantime (#32037 by @ClearlyClaire) +- Fix error when encountering reblog of deleted post in feed rebuild (#32001 by @ClearlyClaire) +- Fix Safari browser glitch related to horizontal scrolling (#31960 by @Gargron) +- Fix too many requests caused by relationship look-ups in web UI (#32042 by @Gargron) +- Fix links for reblogs in moderation interface (#31979 by @ClearlyClaire) +- Fix the appearance of avatars when they do not load (#31966 by @renchap) +- Fix spurious error notifications for aborted requests in web UI (#31952 by @c960657) - 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 wrapping in dashboard quick access buttons (#32043 by @renchap) +- Fix recently used tags hint being displayed in profile edition page when there is none (#32120 by @mjankowski) +- Fix checkbox lists on narrow screens in the settings interface (#32112 by @mjankowski) +- Fix the position of status action buttons being affected by interaction counters (#32084 by @renchap) +- Fix the summary of converted ActivityPub object types to be treated as HTML (#28629 by @Menrath) - 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) @@ -285,7 +309,7 @@ The following changelog entries focus on changes visible to users, administrator - 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) - Fix rack attack `match_type` value typo in logging config (#30514 by @mjankowski) -- Fix various cases of duplicate, missing, or inconsistent borders or scrollbar styles (#31068, #31286, #31268, #31275, #31284, #31305, #31346, #31372, #31373, #31389, #31432, #31391, and #31445 by @valtlai and @vmstan) +- Fix various cases of duplicate, missing, or inconsistent borders or scrollbar styles (#31068, #31286, #31268, #31275, #31284, #31305, #31346, #31372, #31373, #31389, #31432, #31391, #31445 and #32091 by @ClearlyClaire, @valtlai and @vmstan) - Fix race condition in `POST /api/v1/push/subscription` (#30166 by @ClearlyClaire) - Fix post deletion not being delayed when those are part of an account warning (#30163 by @ClearlyClaire) - Fix rendering error on `/start` when not logged in (#30023 by @timothyjrogers) diff --git a/Gemfile.lock b/Gemfile.lock index 79e542014c1ef2..b85d97761d2dd3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,17 +100,17 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.977.0) - aws-sdk-core (3.206.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.163.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.10.0) @@ -134,7 +134,7 @@ GEM bindata (2.5.0) binding_of_caller (1.0.1) debug_inspector (>= 1.2.0) - blurhash (0.1.7) + blurhash (0.1.8) bootsnap (1.18.4) msgpack (~> 1.2) brakeman (6.2.1) @@ -289,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) @@ -347,7 +347,7 @@ GEM activesupport (>= 3.0) nokogiri (>= 1.6) io-console (0.7.2) - irb (1.14.0) + irb (1.14.1) rdoc (>= 4.0.0) reline (>= 0.4.2) jmespath (1.6.2) @@ -406,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) @@ -601,7 +601,7 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) - propshaft (1.0.0) + propshaft (1.0.1) actionpack (>= 7.0.0) activesupport (>= 7.0.0) rack @@ -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) diff --git a/app/controllers/activitypub/likes_controller.rb b/app/controllers/activitypub/likes_controller.rb new file mode 100644 index 00000000000000..4aa6a4a771f156 --- /dev/null +++ b/app/controllers/activitypub/likes_controller.rb @@ -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 diff --git a/app/controllers/activitypub/replies_controller.rb b/app/controllers/activitypub/replies_controller.rb index 11aac48c9c34b1..0a19275d38e942 100644 --- a/app/controllers/activitypub/replies_controller.rb +++ b/app/controllers/activitypub/replies_controller.rb @@ -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 diff --git a/app/controllers/activitypub/shares_controller.rb b/app/controllers/activitypub/shares_controller.rb new file mode 100644 index 00000000000000..65b4a5b3831326 --- /dev/null +++ b/app/controllers/activitypub/shares_controller.rb @@ -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 diff --git a/app/controllers/api/v1/domain_blocks/previews_controller.rb b/app/controllers/api/v1/domain_blocks/previews_controller.rb new file mode 100644 index 00000000000000..a917bddd98ed4c --- /dev/null +++ b/app/controllers/api/v1/domain_blocks/previews_controller.rb @@ -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 diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index d43a658421f6b3..f930a4510e9ae1 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -31,7 +31,7 @@ def set_app_body_class def redirect_unauthenticated_to_permalinks! return if user_signed_in? # NOTE: Different from upstream because we allow moved users to log in - 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? diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 64f2ad70a66e16..fd631ce92ecd30 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -10,16 +10,17 @@ def ui_languages end def featured_tags_hint(recently_used_tags) - safe_join( - [ - t('simple_form.hints.featured_tag.name'), - safe_join( - links_for_featured_tags(recently_used_tags), - ', ' - ), - ], - ' ' - ) + recently_used_tags.present? && + safe_join( + [ + t('simple_form.hints.featured_tag.name'), + safe_join( + links_for_featured_tags(recently_used_tags), + ', ' + ), + ], + ' ' + ) end def session_device_icon(session) diff --git a/app/javascript/flavours/glitch/actions/accounts.js b/app/javascript/flavours/glitch/actions/accounts.js index 699b92dd09f4bb..e8f81048a6d476 100644 --- a/app/javascript/flavours/glitch/actions/accounts.js +++ b/app/javascript/flavours/glitch/actions/accounts.js @@ -1,4 +1,5 @@ import { browserHistory } from 'flavours/glitch/components/router'; +import { debounceWithDispatchAndArguments } from 'flavours/glitch/utils/debounce'; import api, { getLinks } from '../api'; @@ -462,6 +463,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(); @@ -473,13 +488,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); }; } diff --git a/app/javascript/flavours/glitch/actions/notification_groups.ts b/app/javascript/flavours/glitch/actions/notification_groups.ts index 9b5a1ffeef0a1f..eebf6ce7a2b6b3 100644 --- a/app/javascript/flavours/glitch/actions/notification_groups.ts +++ b/app/javascript/flavours/glitch/actions/notification_groups.ts @@ -68,10 +68,15 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } +const supportedGroupedNotificationTypes = ['favourite', 'reblog']; + export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => - apiFetchNotificationGroups({ exclude_types: getExcludedTypes(getState()) }), + apiFetchNotificationGroups({ + grouped_types: supportedGroupedNotificationTypes, + exclude_types: getExcludedTypes(getState()), + }), ({ notifications, accounts, statuses }, { dispatch }) => { dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedStatuses(statuses)); @@ -93,6 +98,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ + grouped_types: supportedGroupedNotificationTypes, max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -109,6 +115,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { 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 diff --git a/app/javascript/flavours/glitch/actions/notification_policies.ts b/app/javascript/flavours/glitch/actions/notification_policies.ts index 65b9882d3baf14..a64175831f3b1f 100644 --- a/app/javascript/flavours/glitch/actions/notification_policies.ts +++ b/app/javascript/flavours/glitch/actions/notification_policies.ts @@ -17,6 +17,6 @@ export const updateNotificationsPolicy = createDataLoadingThunk( (policy: Partial) => apiUpdateNotificationsPolicy(policy), ); -export const decreasePendingNotificationsCount = createAction( - 'notificationPolicy/decreasePendingNotificationCount', +export const decreasePendingRequestsCount = createAction( + 'notificationPolicy/decreasePendingRequestsCount', ); diff --git a/app/javascript/flavours/glitch/actions/notification_requests.ts b/app/javascript/flavours/glitch/actions/notification_requests.ts index 5e3bfd88e7d303..f53668abd529f8 100644 --- a/app/javascript/flavours/glitch/actions/notification_requests.ts +++ b/app/javascript/flavours/glitch/actions/notification_requests.ts @@ -13,11 +13,11 @@ import type { ApiNotificationJSON, } from 'flavours/glitch/api_types/notifications'; import type { ApiStatusJSON } from 'flavours/glitch/api_types/statuses'; -import type { AppDispatch, RootState } from 'flavours/glitch/store'; +import type { AppDispatch } from 'flavours/glitch/store'; import { createDataLoadingThunk } from 'flavours/glitch/store/typed_functions'; import { importFetchedAccounts, importFetchedStatuses } from './importer'; -import { decreasePendingNotificationsCount } from './notification_policies'; +import { decreasePendingRequestsCount } from './notification_policies'; // TODO: refactor with notification_groups function dispatchAssociatedRecords( @@ -169,19 +169,11 @@ export const expandNotificationsForRequest = createDataLoadingThunk( }, ); -const selectNotificationCountForRequest = (state: RootState, id: string) => { - const requests = state.notificationRequests.items; - const thisRequest = requests.find((request) => request.id === id); - return thisRequest ? thisRequest.notifications_count : 0; -}; - export const acceptNotificationRequest = createDataLoadingThunk( 'notificationRequest/accept', ({ id }: { id: string }) => apiAcceptNotificationRequest(id), - (_data, { dispatch, getState, discardLoadData, actionArg: { id } }) => { - const count = selectNotificationCountForRequest(getState(), id); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData }) => { + dispatch(decreasePendingRequestsCount(1)); // The payload is not used in any functions return discardLoadData; @@ -191,10 +183,8 @@ export const acceptNotificationRequest = createDataLoadingThunk( export const dismissNotificationRequest = createDataLoadingThunk( 'notificationRequest/dismiss', ({ id }: { id: string }) => apiDismissNotificationRequest(id), - (_data, { dispatch, getState, discardLoadData, actionArg: { id } }) => { - const count = selectNotificationCountForRequest(getState(), id); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData }) => { + dispatch(decreasePendingRequestsCount(1)); // The payload is not used in any functions return discardLoadData; @@ -204,13 +194,8 @@ export const dismissNotificationRequest = createDataLoadingThunk( export const acceptNotificationRequests = createDataLoadingThunk( 'notificationRequests/acceptBulk', ({ ids }: { ids: string[] }) => apiAcceptNotificationRequests(ids), - (_data, { dispatch, getState, discardLoadData, actionArg: { ids } }) => { - const count = ids.reduce( - (count, id) => count + selectNotificationCountForRequest(getState(), id), - 0, - ); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData, actionArg: { ids } }) => { + dispatch(decreasePendingRequestsCount(ids.length)); // The payload is not used in any functions return discardLoadData; @@ -220,13 +205,8 @@ export const acceptNotificationRequests = createDataLoadingThunk( export const dismissNotificationRequests = createDataLoadingThunk( 'notificationRequests/dismissBulk', ({ ids }: { ids: string[] }) => apiDismissNotificationRequests(ids), - (_data, { dispatch, getState, discardLoadData, actionArg: { ids } }) => { - const count = ids.reduce( - (count, id) => count + selectNotificationCountForRequest(getState(), id), - 0, - ); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData, actionArg: { ids } }) => { + dispatch(decreasePendingRequestsCount(ids.length)); // The payload is not used in any functions return discardLoadData; diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index 70a1f23df5adb3..7b80663f3ddb52 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -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, @@ -68,14 +68,6 @@ defineMessages({ mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, }); -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)); - } -}; - export const loadPending = () => ({ type: NOTIFICATIONS_LOAD_PENDING, }); @@ -118,8 +110,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, @@ -211,7 +201,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)); diff --git a/app/javascript/flavours/glitch/api.ts b/app/javascript/flavours/glitch/api.ts index 25bb25547cf94d..51cbe0b6954e09 100644 --- a/app/javascript/flavours/glitch/api.ts +++ b/app/javascript/flavours/glitch/api.ts @@ -70,6 +70,7 @@ export async function apiRequest( args: { params?: RequestParamsOrData; data?: RequestParamsOrData; + timeout?: number; } = {}, ) { const { data } = await api().request({ diff --git a/app/javascript/flavours/glitch/api/notifications.ts b/app/javascript/flavours/glitch/api/notifications.ts index a3055e3f3e55d6..9453f545e61c5d 100644 --- a/app/javascript/flavours/glitch/api/notifications.ts +++ b/app/javascript/flavours/glitch/api/notifications.ts @@ -31,6 +31,7 @@ export const apiFetchNotifications = async ( export const apiFetchNotificationGroups = async (params?: { url?: string; + grouped_types?: string[]; exclude_types?: string[]; max_id?: string; since_id?: string; @@ -91,5 +92,5 @@ export const apiAcceptNotificationRequests = async (id: string[]) => { }; export const apiDismissNotificationRequests = async (id: string[]) => { - return apiRequestPost('v1/notifications/dismiss/dismiss', { id }); + return apiRequestPost('v1/notifications/requests/dismiss', { id }); }; diff --git a/app/javascript/flavours/glitch/components/alt_text_badge.tsx b/app/javascript/flavours/glitch/components/alt_text_badge.tsx new file mode 100644 index 00000000000000..99bec1ee51cf71 --- /dev/null +++ b/app/javascript/flavours/glitch/components/alt_text_badge.tsx @@ -0,0 +1,67 @@ +import { useState, useCallback, useRef } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import Overlay from 'react-overlays/Overlay'; +import type { + OffsetValue, + UsePopperOptions, +} from 'react-overlays/esm/usePopper'; + +const offset = [0, 4] as OffsetValue; +const popperConfig = { strategy: 'fixed' } as UsePopperOptions; + +export const AltTextBadge: React.FC<{ + description: string; +}> = ({ description }) => { + const anchorRef = useRef(null); + const [open, setOpen] = useState(false); + + const handleClick = useCallback(() => { + setOpen((v) => !v); + }, [setOpen]); + + const handleClose = useCallback(() => { + setOpen(false); + }, [setOpen]); + + return ( + <> + + + + {({ props }) => ( +
+
+

+ +

+

{description}

+
+
+ )} +
+ + ); +}; diff --git a/app/javascript/flavours/glitch/components/button.tsx b/app/javascript/flavours/glitch/components/button.tsx index c76aaea42f26fc..3e720f7ceead2a 100644 --- a/app/javascript/flavours/glitch/components/button.tsx +++ b/app/javascript/flavours/glitch/components/button.tsx @@ -7,6 +7,7 @@ interface BaseProps extends Omit, 'children'> { block?: boolean; secondary?: boolean; + dangerous?: boolean; } interface PropsChildren extends PropsWithChildren { @@ -26,6 +27,7 @@ export const Button: React.FC = ({ disabled, block, secondary, + dangerous, className, title, text, @@ -46,6 +48,7 @@ export const Button: React.FC = ({ className={classNames('button', className, { 'button-secondary': secondary, 'button--block': block, + 'button--dangerous': dangerous, })} disabled={disabled} onClick={handleClick} diff --git a/app/javascript/flavours/glitch/components/media_gallery.jsx b/app/javascript/flavours/glitch/components/media_gallery.jsx index 5be5fb4c58bb55..4d51bdcdc2b1ff 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.jsx +++ b/app/javascript/flavours/glitch/components/media_gallery.jsx @@ -10,7 +10,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; +import { AltTextBadge } from 'flavours/glitch/components/alt_text_badge'; import { Blurhash } from 'flavours/glitch/components/blurhash'; +import { formatTime } from 'flavours/glitch/features/video'; import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state'; @@ -58,7 +60,7 @@ class Item extends PureComponent { hoverToPlay () { const { attachment } = this.props; - return !this.getAutoPlay() && attachment.get('type') === 'gifv'; + return !this.getAutoPlay() && ['gifv', 'video'].includes(attachment.get('type')); } handleClick = (e) => { @@ -97,7 +99,7 @@ class Item extends PureComponent { } if (attachment.get('description')?.length > 0) { - badges.push(ALT); + badges.push(); } const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); @@ -152,10 +154,15 @@ class Item extends PureComponent { /> ); - } else if (attachment.get('type') === 'gifv') { + } else if (['gifv', 'video'].includes(attachment.get('type'))) { const autoPlay = this.getAutoPlay(); + const duration = attachment.getIn(['meta', 'original', 'duration']); - badges.push(GIF); + if (attachment.get('type') === 'gifv') { + badges.push(GIF); + } else { + badges.push({formatTime(Math.floor(duration))}); + } thumbnail = (
@@ -169,6 +176,7 @@ class Item extends PureComponent { onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + onLoadedData={this.handleImageLoad} autoPlay={autoPlay} playsInline loop diff --git a/app/javascript/flavours/glitch/components/navigation_portal.tsx b/app/javascript/flavours/glitch/components/navigation_portal.tsx index 223cc242321995..b10b1f28a96b96 100644 --- a/app/javascript/flavours/glitch/components/navigation_portal.tsx +++ b/app/javascript/flavours/glitch/components/navigation_portal.tsx @@ -4,22 +4,22 @@ import AccountNavigation from 'flavours/glitch/features/account/navigation'; import Trends from 'flavours/glitch/features/getting_started/containers/trends_container'; import { showTrends } from 'flavours/glitch/initial_state'; -const DefaultNavigation: React.FC = () => - showTrends ? ( - <> -
- - - ) : null; +const DefaultNavigation: React.FC = () => (showTrends ? : null); export const NavigationPortal: React.FC = () => ( - - - - - - - - - +
+ + + + + + + + + +
); diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index a037895b4e1924..493ef4f68a8983 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -648,6 +648,27 @@ class Status extends ImmutablePureComponent { media={status.get('media_attachments')} />, ); + } else if (['image', 'gifv'].includes(status.getIn(['media_attachments', 0, 'type'])) || status.get('media_attachments').size > 1) { + media.push( + + {Component => ( + , + ); + mediaIcons.push('picture-o'); } else if (attachments.getIn([0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); @@ -703,27 +724,6 @@ class Status extends ImmutablePureComponent { , ); mediaIcons.push('video-camera'); - } else { // Media type is 'image' or 'gifv' - media.push( - - {Component => ( - , - ); - mediaIcons.push('picture-o'); } if (!status.get('sensitive') && !(status.get('spoiler_text').length > 0) && settings.getIn(['collapsed', 'backgrounds', 'preview_images'])) { diff --git a/app/javascript/flavours/glitch/components/status_action_bar.jsx b/app/javascript/flavours/glitch/components/status_action_bar.jsx index 01b44111920218..a8349255162583 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.jsx +++ b/app/javascript/flavours/glitch/components/status_action_bar.jsx @@ -315,36 +315,48 @@ class StatusActionBar extends ImmutablePureComponent { } const filterButton = this.props.onFilter && ( - +
+ +
); return (
- - - - +
+ +
+
+ +
+
+ +
+
+ +
{filterButton} - +
+ +
diff --git a/app/javascript/flavours/glitch/features/account/navigation.jsx b/app/javascript/flavours/glitch/features/account/navigation.jsx index 4be00c49f21cf8..9505c48d5f386f 100644 --- a/app/javascript/flavours/glitch/features/account/navigation.jsx +++ b/app/javascript/flavours/glitch/features/account/navigation.jsx @@ -43,10 +43,7 @@ class AccountNavigation extends PureComponent { } return ( - <> -
- - + ); } diff --git a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.jsx b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.jsx deleted file mode 100644 index c709e58db1a05b..00000000000000 --- a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.jsx +++ /dev/null @@ -1,158 +0,0 @@ -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; - -import AudiotrackIcon from '@/material-icons/400-24px/music_note.svg?react'; -import PlayArrowIcon from '@/material-icons/400-24px/play_arrow.svg?react'; -import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react'; -import { Blurhash } from 'flavours/glitch/components/blurhash'; -import { Icon } from 'flavours/glitch/components/icon'; -import { autoPlayGif, displayMedia, useBlurhash } from 'flavours/glitch/initial_state'; - -export default class MediaItem extends ImmutablePureComponent { - - static propTypes = { - attachment: ImmutablePropTypes.map.isRequired, - displayWidth: PropTypes.number.isRequired, - onOpenMedia: PropTypes.func.isRequired, - }; - - state = { - visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all', - loaded: false, - }; - - handleImageLoad = () => { - this.setState({ loaded: true }); - }; - - handleMouseEnter = e => { - if (this.hoverToPlay()) { - e.target.play(); - } - }; - - handleMouseLeave = e => { - if (this.hoverToPlay()) { - e.target.pause(); - e.target.currentTime = 0; - } - }; - - hoverToPlay () { - return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1; - } - - handleClick = e => { - if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - - if (this.state.visible) { - this.props.onOpenMedia(this.props.attachment); - } else { - this.setState({ visible: true }); - } - } - }; - - render () { - const { attachment, displayWidth } = this.props; - const { visible, loaded } = this.state; - - const width = `${Math.floor((displayWidth - 4) / 3) - 4}px`; - const height = width; - const status = attachment.get('status'); - const title = status.get('spoiler_text') || attachment.get('description'); - - let thumbnail, label, icon, content; - - if (!visible) { - icon = ( - - - - ); - } else { - if (['audio', 'video'].includes(attachment.get('type'))) { - content = ( - {attachment.get('description')} - ); - - if (attachment.get('type') === 'audio') { - label = ; - } else { - label = ; - } - } else if (attachment.get('type') === 'image') { - const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0; - const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0; - const x = ((focusX / 2) + .5) * 100; - const y = ((focusY / -2) + .5) * 100; - - content = ( - {attachment.get('description')} - ); - } else if (attachment.get('type') === 'gifv') { - content = ( - - ); - } - -} diff --git a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.tsx b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.tsx new file mode 100644 index 00000000000000..e7983c503c452b --- /dev/null +++ b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.tsx @@ -0,0 +1,203 @@ +import { useState, useCallback } from 'react'; + +import classNames from 'classnames'; + +import HeadphonesIcon from '@/material-icons/400-24px/headphones-fill.svg?react'; +import MovieIcon from '@/material-icons/400-24px/movie-fill.svg?react'; +import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react'; +import { AltTextBadge } from 'flavours/glitch/components/alt_text_badge'; +import { Blurhash } from 'flavours/glitch/components/blurhash'; +import { Icon } from 'flavours/glitch/components/icon'; +import { formatTime } from 'flavours/glitch/features/video'; +import { + autoPlayGif, + displayMedia, + useBlurhash, +} from 'flavours/glitch/initial_state'; +import type { Status, MediaAttachment } from 'flavours/glitch/models/status'; + +export const MediaItem: React.FC<{ + attachment: MediaAttachment; + onOpenMedia: (arg0: MediaAttachment) => void; +}> = ({ attachment, onOpenMedia }) => { + const [visible, setVisible] = useState( + (displayMedia !== 'hide_all' && + !attachment.getIn(['status', 'sensitive'])) || + displayMedia === 'show_all', + ); + const [loaded, setLoaded] = useState(false); + + const handleImageLoad = useCallback(() => { + setLoaded(true); + }, [setLoaded]); + + const handleMouseEnter = useCallback( + (e: React.MouseEvent) => { + if (e.target instanceof HTMLVideoElement) { + void e.target.play(); + } + }, + [], + ); + + const handleMouseLeave = useCallback( + (e: React.MouseEvent) => { + if (e.target instanceof HTMLVideoElement) { + e.target.pause(); + e.target.currentTime = 0; + } + }, + [], + ); + + const handleClick = useCallback( + (e: React.MouseEvent) => { + if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { + e.preventDefault(); + + if (visible) { + onOpenMedia(attachment); + } else { + setVisible(true); + } + } + }, + [attachment, visible, onOpenMedia, setVisible], + ); + + const status = attachment.get('status') as Status; + const description = (attachment.getIn(['translation', 'description']) || + attachment.get('description')) as string | undefined; + const previewUrl = attachment.get('preview_url') as string; + const fullUrl = attachment.get('url') as string; + const avatarUrl = status.getIn(['account', 'avatar_static']) as string; + const lang = status.get('language') as string; + const blurhash = attachment.get('blurhash') as string; + const statusUrl = status.get('url') as string; + const type = attachment.get('type') as string; + + let thumbnail; + + const badges = []; + + if (description && description.length > 0) { + badges.push(); + } + + if (!visible) { + thumbnail = ( +
+ +
+ ); + } else if (type === 'audio') { + thumbnail = ( + <> + {description} + +
+ +
+ + ); + } else if (type === 'image') { + const focusX = (attachment.getIn(['meta', 'focus', 'x']) || 0) as number; + const focusY = (attachment.getIn(['meta', 'focus', 'y']) || 0) as number; + const x = (focusX / 2 + 0.5) * 100; + const y = (focusY / -2 + 0.5) * 100; + + thumbnail = ( + {description} + ); + } else if (['video', 'gifv'].includes(type)) { + const duration = attachment.getIn([ + 'meta', + 'original', + 'duration', + ]) as number; + + thumbnail = ( +
+
+ ); + + if (type === 'gifv') { + badges.push( + + GIF + , + ); + } else { + badges.push( + + {formatTime(Math.floor(duration))} + , + ); + } + } + + return ( +
+ + + + {thumbnail} + + + {badges.length > 0 && ( +
{badges}
+ )} +
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/account_gallery/index.jsx b/app/javascript/flavours/glitch/features/account_gallery/index.jsx index d3f845ddc4668a..284713f93dbb0b 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/index.jsx +++ b/app/javascript/flavours/glitch/features/account_gallery/index.jsx @@ -20,7 +20,7 @@ import { expandAccountMediaTimeline } from '../../actions/timelines'; import HeaderContainer from '../account_timeline/containers/header_container'; import Column from '../ui/components/column'; -import MediaItem from './components/media_item'; +import { MediaItem } from './components/media_item'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', normalizeForLookup(acct)]); diff --git a/app/javascript/flavours/glitch/features/compose/components/sensitive_button.jsx b/app/javascript/flavours/glitch/features/compose/components/sensitive_button.jsx index deb401bfb744e4..de7d033ed076e4 100644 --- a/app/javascript/flavours/glitch/features/compose/components/sensitive_button.jsx +++ b/app/javascript/flavours/glitch/features/compose/components/sensitive_button.jsx @@ -21,11 +21,11 @@ const messages = defineMessages({ export const SensitiveButton = () => { const intl = useIntl(); - const spoilersAlwaysOn = useAppSelector((state) => state.getIn(['local_settings', 'always_show_spoilers_field'])); - const spoilerText = useAppSelector((state) => state.getIn(['compose', 'spoiler_text'])); - const sensitive = useAppSelector((state) => state.getIn(['compose', 'sensitive'])); - const spoiler = useAppSelector((state) => state.getIn(['compose', 'spoiler'])); - const mediaCount = useAppSelector((state) => state.getIn(['compose', 'media_attachments']).size); + const spoilersAlwaysOn = useAppSelector((state) => state.local_settings.getIn(['always_show_spoilers_field'])); + const spoilerText = useAppSelector((state) => state.compose.get('spoiler_text')); + const sensitive = useAppSelector((state) => state.compose.get('sensitive')); + const spoiler = useAppSelector((state) => state.compose.get('spoiler')); + const mediaCount = useAppSelector((state) => state.compose.get('media_attachments').size); const disabled = spoilersAlwaysOn ? (spoilerText && spoilerText.length > 0) : spoiler; const active = sensitive || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0); diff --git a/app/javascript/flavours/glitch/features/compose/components/upload.jsx b/app/javascript/flavours/glitch/features/compose/components/upload.jsx deleted file mode 100644 index 790d76264d2bdd..00000000000000 --- a/app/javascript/flavours/glitch/features/compose/components/upload.jsx +++ /dev/null @@ -1,81 +0,0 @@ -import PropTypes from 'prop-types'; -import { useCallback } from 'react'; - -import { FormattedMessage } from 'react-intl'; - -import classNames from 'classnames'; - -import { useDispatch, useSelector } from 'react-redux'; - -import spring from 'react-motion/lib/spring'; - -import CloseIcon from '@/material-icons/400-20px/close.svg?react'; -import EditIcon from '@/material-icons/400-24px/edit.svg?react'; -import WarningIcon from '@/material-icons/400-24px/warning.svg?react'; -import { undoUploadCompose, initMediaEditModal } from 'flavours/glitch/actions/compose'; -import { Blurhash } from 'flavours/glitch/components/blurhash'; -import { Icon } from 'flavours/glitch/components/icon'; -import Motion from 'flavours/glitch/features/ui/util/optional_motion'; - -export const Upload = ({ id, onDragStart, onDragEnter, onDragEnd }) => { - const dispatch = useDispatch(); - const media = useSelector(state => state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id)); - const sensitive = useSelector(state => state.getIn(['compose', 'sensitive'])); - - const handleUndoClick = useCallback(() => { - dispatch(undoUploadCompose(id)); - }, [dispatch, id]); - - const handleFocalPointClick = useCallback(() => { - dispatch(initMediaEditModal(id)); - }, [dispatch, id]); - - const handleDragStart = useCallback(() => { - onDragStart(id); - }, [onDragStart, id]); - - const handleDragEnter = useCallback(() => { - onDragEnter(id); - }, [onDragEnter, id]); - - if (!media) { - return null; - } - - const focusX = media.getIn(['meta', 'focus', 'x']); - const focusY = media.getIn(['meta', 'focus', 'y']); - const x = ((focusX / 2) + .5) * 100; - const y = ((focusY / -2) + .5) * 100; - const missingDescription = (media.get('description') || '').length === 0; - - return ( -
- - {({ scale }) => ( -
- {sensitive && } - -
- - -
- -
- -
-
- )} -
-
- ); -}; - -Upload.propTypes = { - id: PropTypes.string, - onDragEnter: PropTypes.func, - onDragStart: PropTypes.func, - onDragEnd: PropTypes.func, -}; diff --git a/app/javascript/flavours/glitch/features/compose/components/upload.tsx b/app/javascript/flavours/glitch/features/compose/components/upload.tsx new file mode 100644 index 00000000000000..a583a8d81d5b33 --- /dev/null +++ b/app/javascript/flavours/glitch/features/compose/components/upload.tsx @@ -0,0 +1,130 @@ +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import classNames from 'classnames'; + +import { useSortable } from '@dnd-kit/sortable'; +import { CSS } from '@dnd-kit/utilities'; + +import CloseIcon from '@/material-icons/400-20px/close.svg?react'; +import EditIcon from '@/material-icons/400-24px/edit.svg?react'; +import WarningIcon from '@/material-icons/400-24px/warning.svg?react'; +import { + undoUploadCompose, + initMediaEditModal, +} from 'flavours/glitch/actions/compose'; +import { Blurhash } from 'flavours/glitch/components/blurhash'; +import { Icon } from 'flavours/glitch/components/icon'; +import type { MediaAttachment } from 'flavours/glitch/models/media_attachment'; +import { useAppDispatch, useAppSelector } from 'flavours/glitch/store'; + +export const Upload: React.FC<{ + id: string; + dragging?: boolean; + overlay?: boolean; + tall?: boolean; + wide?: boolean; +}> = ({ id, dragging, overlay, tall, wide }) => { + const dispatch = useAppDispatch(); + const media = useAppSelector( + (state) => + state.compose // eslint-disable-line @typescript-eslint/no-unsafe-call + .get('media_attachments') // eslint-disable-line @typescript-eslint/no-unsafe-member-access + .find((item: MediaAttachment) => item.get('id') === id) as // eslint-disable-line @typescript-eslint/no-unsafe-member-access + | MediaAttachment + | undefined, + ); + const sensitive = useAppSelector( + (state) => state.compose.get('sensitive') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + ); + + const handleUndoClick = useCallback(() => { + dispatch(undoUploadCompose(id)); + }, [dispatch, id]); + + const handleFocalPointClick = useCallback(() => { + dispatch(initMediaEditModal(id)); + }, [dispatch, id]); + + const { attributes, listeners, setNodeRef, transform, transition } = + useSortable({ id }); + + if (!media) { + return null; + } + + const focusX = media.getIn(['meta', 'focus', 'x']) as number; + const focusY = media.getIn(['meta', 'focus', 'y']) as number; + const x = (focusX / 2 + 0.5) * 100; + const y = (focusY / -2 + 0.5) * 100; + const missingDescription = + ((media.get('description') as string | undefined) ?? '').length === 0; + + const style = { + transform: CSS.Transform.toString(transform), + transition, + }; + + return ( +
+
+ {sensitive && ( + + )} + +
+ + +
+ +
+ +
+
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/compose/components/upload_form.jsx b/app/javascript/flavours/glitch/features/compose/components/upload_form.jsx deleted file mode 100644 index 2b26735f5e1cc5..00000000000000 --- a/app/javascript/flavours/glitch/features/compose/components/upload_form.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useRef, useCallback } from 'react'; - -import { useSelector, useDispatch } from 'react-redux'; - -import { changeMediaOrder } from 'flavours/glitch/actions/compose'; - -import { SensitiveButton } from './sensitive_button'; -import { Upload } from './upload'; -import { UploadProgress } from './upload_progress'; - -export const UploadForm = () => { - const dispatch = useDispatch(); - const mediaIds = useSelector(state => state.getIn(['compose', 'media_attachments']).map(item => item.get('id'))); - const active = useSelector(state => state.getIn(['compose', 'is_uploading'])); - const progress = useSelector(state => state.getIn(['compose', 'progress'])); - const isProcessing = useSelector(state => state.getIn(['compose', 'is_processing'])); - - const dragItem = useRef(); - const dragOverItem = useRef(); - - const handleDragStart = useCallback(id => { - dragItem.current = id; - }, [dragItem]); - - const handleDragEnter = useCallback(id => { - dragOverItem.current = id; - }, [dragOverItem]); - - const handleDragEnd = useCallback(() => { - dispatch(changeMediaOrder(dragItem.current, dragOverItem.current)); - dragItem.current = null; - dragOverItem.current = null; - }, [dispatch, dragItem, dragOverItem]); - - return ( - <> - - - {mediaIds.size > 0 && ( -
- {mediaIds.map(id => ( - - ))} -
- )} - - {!mediaIds.isEmpty() && } - - ); -}; diff --git a/app/javascript/flavours/glitch/features/compose/components/upload_form.tsx b/app/javascript/flavours/glitch/features/compose/components/upload_form.tsx new file mode 100644 index 00000000000000..44bfaa8f384fc0 --- /dev/null +++ b/app/javascript/flavours/glitch/features/compose/components/upload_form.tsx @@ -0,0 +1,188 @@ +import { useState, useCallback, useMemo } from 'react'; + +import { useIntl, defineMessages } from 'react-intl'; + +import type { List } from 'immutable'; + +import type { + DragStartEvent, + DragEndEvent, + UniqueIdentifier, + Announcements, + ScreenReaderInstructions, +} from '@dnd-kit/core'; +import { + DndContext, + closestCenter, + KeyboardSensor, + PointerSensor, + useSensor, + useSensors, + DragOverlay, +} from '@dnd-kit/core'; +import { + SortableContext, + sortableKeyboardCoordinates, + rectSortingStrategy, +} from '@dnd-kit/sortable'; + +import { changeMediaOrder } from 'flavours/glitch/actions/compose'; +import type { MediaAttachment } from 'flavours/glitch/models/media_attachment'; +import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; + +import { SensitiveButton } from './sensitive_button'; +import { Upload } from './upload'; +import { UploadProgress } from './upload_progress'; + +const messages = defineMessages({ + screenReaderInstructions: { + id: 'upload_form.drag_and_drop.instructions', + defaultMessage: + 'To pick up a media attachment, press space or enter. While dragging, use the arrow keys to move the media attachment in any given direction. Press space or enter again to drop the media attachment in its new position, or press escape to cancel.', + }, + onDragStart: { + id: 'upload_form.drag_and_drop.on_drag_start', + defaultMessage: 'Picked up media attachment {item}.', + }, + onDragOver: { + id: 'upload_form.drag_and_drop.on_drag_over', + defaultMessage: 'Media attachment {item} was moved.', + }, + onDragEnd: { + id: 'upload_form.drag_and_drop.on_drag_end', + defaultMessage: 'Media attachment {item} was dropped.', + }, + onDragCancel: { + id: 'upload_form.drag_and_drop.on_drag_cancel', + defaultMessage: + 'Dragging was cancelled. Media attachment {item} was dropped.', + }, +}); + +export const UploadForm: React.FC = () => { + const dispatch = useAppDispatch(); + const intl = useIntl(); + const mediaIds = useAppSelector( + (state) => + state.compose // eslint-disable-line @typescript-eslint/no-unsafe-call + .get('media_attachments') // eslint-disable-line @typescript-eslint/no-unsafe-member-access + .map((item: MediaAttachment) => item.get('id')) as List, // eslint-disable-line @typescript-eslint/no-unsafe-member-access + ); + const active = useAppSelector( + (state) => state.compose.get('is_uploading') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + ); + const progress = useAppSelector( + (state) => state.compose.get('progress') as number, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + ); + const isProcessing = useAppSelector( + (state) => state.compose.get('is_processing') as boolean, // eslint-disable-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + ); + const [activeId, setActiveId] = useState(null); + const sensors = useSensors( + useSensor(PointerSensor, { + activationConstraint: { + distance: 5, + }, + }), + useSensor(KeyboardSensor, { + coordinateGetter: sortableKeyboardCoordinates, + }), + ); + + const handleDragStart = useCallback( + (e: DragStartEvent) => { + const { active } = e; + + setActiveId(active.id); + }, + [setActiveId], + ); + + const handleDragEnd = useCallback( + (e: DragEndEvent) => { + const { active, over } = e; + + if (over && active.id !== over.id) { + dispatch(changeMediaOrder(active.id, over.id)); + } + + setActiveId(null); + }, + [dispatch, setActiveId], + ); + + const accessibility: { + screenReaderInstructions: ScreenReaderInstructions; + announcements: Announcements; + } = useMemo( + () => ({ + screenReaderInstructions: { + draggable: intl.formatMessage(messages.screenReaderInstructions), + }, + + announcements: { + onDragStart({ active }) { + return intl.formatMessage(messages.onDragStart, { item: active.id }); + }, + + onDragOver({ active }) { + return intl.formatMessage(messages.onDragOver, { item: active.id }); + }, + + onDragEnd({ active }) { + return intl.formatMessage(messages.onDragEnd, { item: active.id }); + }, + + onDragCancel({ active }) { + return intl.formatMessage(messages.onDragCancel, { item: active.id }); + }, + }, + }), + [intl], + ); + + return ( + <> + + + {mediaIds.size > 0 && ( +
+ + + {mediaIds.map((id, idx) => ( + + ))} + + + + {activeId ? : null} + + +
+ )} + + {!mediaIds.isEmpty() && } + + ); +}; diff --git a/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx b/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx index f4413a8c170d82..23801d7869b5af 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx +++ b/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx @@ -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; } diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx b/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx index 11306afb6130aa..dcce9a47de7e84 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx @@ -21,6 +21,7 @@ import { Permalink } from 'flavours/glitch/components/permalink'; import PictureInPicturePlaceholder from 'flavours/glitch/components/picture_in_picture_placeholder'; import { useAppHistory } from 'flavours/glitch/components/router'; import { VisibilityIcon } from 'flavours/glitch/components/visibility_icon'; +import PollContainer from 'flavours/glitch/containers/poll_container'; import { useAppSelector } from 'flavours/glitch/store'; import { Avatar } from '../../../components/avatar'; @@ -194,6 +195,28 @@ export const DetailedStatus: React.FC<{ ) ) { media.push(); + } else if ( + ['image', 'gifv'].includes( + status.getIn(['media_attachments', 0, 'type']) as string, + ) || + status.get('media_attachments').size > 1 + ) { + media.push( +
diff --git a/app/javascript/flavours/glitch/features/ui/components/column_link.jsx b/app/javascript/flavours/glitch/features/ui/components/column_link.jsx index 4445435309d8ee..452e810a6d8b77 100644 --- a/app/javascript/flavours/glitch/features/ui/components/column_link.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/column_link.jsx @@ -3,11 +3,11 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { useRouteMatch, NavLink } from 'react-router-dom'; -import { Icon } from 'flavours/glitch/components/icon'; +import { Icon } from 'flavours/glitch/components/icon'; -const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text, to, onClick, href, method, badge, transparent, ...other }) => { +const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text, to, onClick, 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' ? {badge} : null; const iconElement = (typeof icon === 'string' || iconComponent) ? : icon; const activeIconElement = activeIcon ?? (activeIconComponent ? : iconElement); @@ -58,6 +58,7 @@ ColumnLink.propTypes = { method: PropTypes.string, badge: PropTypes.node, transparent: PropTypes.bool, + optional: PropTypes.bool, }; export default ColumnLink; diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx b/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx index 9471104b97f48d..c70c8183b9d17a 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.jsx @@ -63,7 +63,7 @@ export default class ColumnsArea extends ImmutablePureComponent { }; // Corresponds to (max-width: $no-gap-breakpoint - 1px) in SCSS - mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1206px)'); + mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1174px)'); state = { renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches), diff --git a/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.jsx deleted file mode 100644 index 8b06389179aaa3..00000000000000 --- a/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.jsx +++ /dev/null @@ -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 'flavours/glitch/actions/accounts'; -import { blockDomain } from 'flavours/glitch/actions/domain_blocks'; -import { closeModal } from 'flavours/glitch/actions/modal'; -import { Button } from 'flavours/glitch/components/button'; -import { Icon } from 'flavours/glitch/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 ( -
-
-
-
- -
- -
-

-
{domain}
-
-
- -
-
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
-
-
- -
-
- - -
- - - - -
-
-
- ); -}; - -DomainBlockModal.propTypes = { - domain: PropTypes.string.isRequired, - accountId: PropTypes.string.isRequired, - acct: PropTypes.string.isRequired, -}; - -export default DomainBlockModal; diff --git a/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.tsx b/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.tsx new file mode 100644 index 00000000000000..b056db7f6fe6b4 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/components/domain_block_modal.tsx @@ -0,0 +1,223 @@ +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 'flavours/glitch/actions/accounts'; +import { blockDomain } from 'flavours/glitch/actions/domain_blocks'; +import { closeModal } from 'flavours/glitch/actions/modal'; +import { apiRequest } from 'flavours/glitch/api'; +import { Button } from 'flavours/glitch/components/button'; +import { Icon } from 'flavours/glitch/components/icon'; +import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator'; +import { ShortNumber } from 'flavours/glitch/components/short_number'; +import { useAppDispatch } from 'flavours/glitch/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 | 'error' | 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('GET', 'v1/domain_blocks/preview', { + params: { domain }, + timeout: 5000, + }) + .then((data) => { + setPreview(data); + setLoading(false); + return ''; + }) + .catch(() => { + setPreview('error'); + setLoading(false); + }); + }, [setPreview, setLoading, domain]); + + return ( +
+
+
+
+ +
+ +
+

+ +

+
{domain}
+
+
+ +
+ {preview && + preview !== 'error' && + preview.followers_count + preview.following_count > 0 && ( +
+
+ +
+
+ + + ), + followingCount: preview.following_count, + followingCountDisplay: ( + + ), + }} + /> + +
+
+ )} + + {preview === 'error' && ( +
+
+ +
+
+ + + +
+
+ )} + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ + +
+ + + + +
+
+
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default DomainBlockModal; diff --git a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx index 3e3fa5d9f120a7..0d73cd421f68ef 100644 --- a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.jsx @@ -122,14 +122,17 @@ class NavigationPanel extends Component { let banner = undefined; - if(transientSingleColumn) - banner = (
- {intl.formatMessage(messages.openedInClassicInterface)} - {" "} - - {intl.formatMessage(messages.advancedInterface)} - -
); + if (transientSingleColumn) { + banner = ( +
+ {intl.formatMessage(messages.openedInClassicInterface)} + {" "} + + {intl.formatMessage(messages.advancedInterface)} + +
+ ); + } return (
@@ -139,55 +142,59 @@ class NavigationPanel extends Component {
} - {signedIn && ( - <> - - - - - )} - - {trendsEnabled ? ( - - ) : ( - - )} - - {(signedIn || timelinePreview) && ( - - )} - - {!signedIn && ( -
+
+ {signedIn && ( + <> + + + + + )} + + {trendsEnabled ? ( + + ) : ( + + )} + + {(signedIn || timelinePreview) && ( + + )} + + {!signedIn && ( +
+
+ { disabledAccountId ? : } +
+ )} + + {signedIn && ( + <> + + + + + + + +
+ + {!!preferencesLink && } + + + {canManageReports(permissions) && } + {canViewAdminDashboard(permissions) && } + + )} + +

- { disabledAccountId ? : } +
- )} - - {signedIn && ( - <> - - - - - - - -
- - {!!preferencesLink && } - - - {canManageReports(permissions) && } - {canViewAdminDashboard(permissions) && } - - )} - -
-
-
+
+
); diff --git a/app/javascript/flavours/glitch/features/ui/index.jsx b/app/javascript/flavours/glitch/features/ui/index.jsx index 0ee191cfb4535d..d1165194ba32bd 100644 --- a/app/javascript/flavours/glitch/features/ui/index.jsx +++ b/app/javascript/flavours/glitch/features/ui/index.jsx @@ -196,7 +196,7 @@ class SwitchingColumnsArea extends PureComponent { {redirect} {singleColumn ? : null} - {singleColumn && pathName.startsWith('/deck/') ? : null} + {singleColumn && pathName.startsWith('/deck/') ? : null} {/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */} {!singleColumn && pathName === '/getting-started' ? : null} {!singleColumn && pathName === '/home' ? : null} diff --git a/app/javascript/flavours/glitch/models/media_attachment.ts b/app/javascript/flavours/glitch/models/media_attachment.ts new file mode 100644 index 00000000000000..0e5b9ab555e354 --- /dev/null +++ b/app/javascript/flavours/glitch/models/media_attachment.ts @@ -0,0 +1,2 @@ +// Temporary until we type it correctly +export type MediaAttachment = Immutable.Map; diff --git a/app/javascript/flavours/glitch/models/status.ts b/app/javascript/flavours/glitch/models/status.ts index bf1784bc615404..9246f3621325b6 100644 --- a/app/javascript/flavours/glitch/models/status.ts +++ b/app/javascript/flavours/glitch/models/status.ts @@ -10,3 +10,5 @@ export type Status = Immutable.Map; type CardShape = Required; export type Card = RecordOf; + +export type MediaAttachment = Immutable.Map; diff --git a/app/javascript/flavours/glitch/reducers/notification_policy.ts b/app/javascript/flavours/glitch/reducers/notification_policy.ts index 0ec68f89506601..0b548ef367f5e9 100644 --- a/app/javascript/flavours/glitch/reducers/notification_policy.ts +++ b/app/javascript/flavours/glitch/reducers/notification_policy.ts @@ -2,7 +2,7 @@ import { createReducer, isAnyOf } from '@reduxjs/toolkit'; import { fetchNotificationPolicy, - decreasePendingNotificationsCount, + decreasePendingRequestsCount, updateNotificationsPolicy, } from 'flavours/glitch/actions/notification_policies'; import type { NotificationPolicy } from 'flavours/glitch/models/notification_policy'; @@ -10,10 +10,9 @@ import type { NotificationPolicy } from 'flavours/glitch/models/notification_pol export const notificationPolicyReducer = createReducer(null, (builder) => { builder - .addCase(decreasePendingNotificationsCount, (state, action) => { + .addCase(decreasePendingRequestsCount, (state, action) => { if (state) { - state.summary.pending_notifications_count -= action.payload; - state.summary.pending_requests_count -= 1; + state.summary.pending_requests_count -= action.payload; } }) .addMatcher( diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 6ee86f5ee0fb28..72613cbbc4874b 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -81,6 +81,18 @@ outline: $ui-button-icon-focus-outline; } + &--dangerous { + background-color: var(--error-background-color); + color: var(--on-error-color); + + &:active, + &:focus, + &:hover { + background-color: var(--error-active-background-color); + transition: none; + } + } + &--destructive { &:active, &:focus, @@ -93,7 +105,7 @@ &:disabled, &.disabled { background-color: $ui-primary-color; - cursor: default; + cursor: not-allowed; } &.copyable { @@ -230,6 +242,7 @@ flex: 0 0 auto; a { + display: flex; color: inherit; text-decoration: none; } @@ -299,6 +312,10 @@ } } + &--with-counter { + padding-inline-end: 4px; + } + &__counter { display: block; width: auto; @@ -636,19 +653,39 @@ body > [data-popper-placement] { } &__uploads { - display: flex; - gap: 8px; padding: 0 12px; - flex-wrap: wrap; - align-self: stretch; - align-items: flex-start; - align-content: flex-start; - justify-content: center; + aspect-ratio: 3/2; + } + + .media-gallery { + gap: 8px; } &__upload { - flex: 1 1 0; - min-width: calc(50% - 8px); + position: relative; + cursor: grab; + + &.dragging { + opacity: 0; + } + + &.overlay { + height: 100%; + border-radius: 8px; + pointer-events: none; + } + + &__drag-handle { + position: absolute; + top: 50%; + inset-inline-start: 0; + transform: translateY(-50%); + color: $white; + background: transparent; + border: 0; + padding: 8px 3px; + cursor: grab; + } &__actions { display: flex; @@ -669,8 +706,7 @@ body > [data-popper-placement] { &__thumbnail { width: 100%; - height: 144px; - border-radius: 6px; + height: 100%; background-position: center; background-size: cover; background-repeat: no-repeat; @@ -1516,6 +1552,16 @@ body > [data-popper-placement] { } } + &__action-bar__button-wrapper { + flex-basis: 0; + + // glitch-soc: disable this for now; flex-grow: 1; + + &:last-child { + flex-grow: 0; + } + } + &--first-in-thread { border-top: 1px solid var(--background-border-color); } @@ -2889,7 +2935,7 @@ a.account__display-name { &__main { box-sizing: border-box; width: 100%; - flex: 0 0 auto; + flex: 0 1 auto; display: flex; flex-direction: column; @@ -3658,12 +3704,14 @@ $ui-header-logo-wordmark-width: 99px; margin-top: 10px; margin-bottom: 10px; height: calc(100% - 20px); - overflow-y: auto; + overflow: hidden; display: flex; flex-direction: column; - & > a { - flex: 0 0 auto; + &__menu { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; } .logo { @@ -3674,6 +3722,36 @@ $ui-header-logo-wordmark-width: 99px; &__logo { margin-bottom: 12px; } + + @media screen and (height <= 710px) { + &__portal { + display: none; + } + } + + @media screen and (height <= 765px) { + &__portal .trends__item:nth-child(n + 3) { + display: none; + } + } + + @media screen and (height <= 820px) { + &__portal .trends__item:nth-child(n + 4) { + display: none; + } + } + + @media screen and (height <= 920px) { + .column-link.column-link--optional { + display: none; + } + } + + @media screen and (height <= 1040px) { + .list-panel { + display: none; + } + } } .navigation-panel, @@ -4037,22 +4115,6 @@ $ui-header-logo-wordmark-width: 99px; } } - @media screen and (height <= 810px) { - .trends__item:nth-of-type(3) { - display: none; - } - } - - @media screen and (height <= 720px) { - .trends__item:nth-of-type(2) { - display: none; - } - } - - @media screen and (height <= 670px) { - display: none; - } - .trends__item { border-bottom: 0; padding: 10px; @@ -6245,6 +6307,7 @@ a.status-card { .icon { width: 24px; height: 24px; + filter: var(--overlay-icon-shadow); } &:hover, @@ -6339,6 +6402,10 @@ a.status-card { .icon-button { color: $white; + .icon { + filter: var(--overlay-icon-shadow); + } + &:hover, &:focus, &:active { @@ -6397,6 +6464,7 @@ a.status-card { .media-modal__page-dot { flex: 0 0 auto; background-color: $white; + filter: var(--overlay-icon-shadow); opacity: 0.4; height: 6px; width: 6px; @@ -6673,6 +6741,14 @@ a.status-card { display: flex; gap: 16px; align-items: center; + + strong { + font-weight: 700; + } + } + + &--deemphasized { + color: $secondary-text-color; } &__icon { @@ -7392,7 +7468,7 @@ img.modal-warning { .media-gallery__actions { position: absolute; - bottom: 6px; + top: 6px; inset-inline-end: 6px; display: flex; gap: 2px; @@ -7415,75 +7491,16 @@ img.modal-warning { .media-gallery__item__badges { position: absolute; bottom: 8px; - inset-inline-start: 8px; + inset-inline-end: 8px; display: flex; gap: 2px; - - &--layout-2 { - .media-gallery__item:nth-child(1) { - border-end-end-radius: 0; - border-start-end-radius: 0; - } - - .media-gallery__item:nth-child(2) { - border-start-start-radius: 0; - border-end-start-radius: 0; - } - } - - &--layout-3 { - .media-gallery__item:nth-child(1) { - border-end-end-radius: 0; - border-start-end-radius: 0; - } - - .media-gallery__item:nth-child(2) { - border-start-start-radius: 0; - border-end-start-radius: 0; - border-end-end-radius: 0; - } - - .media-gallery__item:nth-child(3) { - border-start-start-radius: 0; - border-end-start-radius: 0; - border-start-end-radius: 0; - } - } - - &--layout-4 { - .media-gallery__item:nth-child(1) { - border-end-end-radius: 0; - border-start-end-radius: 0; - border-end-start-radius: 0; - } - - .media-gallery__item:nth-child(2) { - border-start-start-radius: 0; - border-end-start-radius: 0; - border-end-end-radius: 0; - } - - .media-gallery__item:nth-child(3) { - border-start-start-radius: 0; - border-start-end-radius: 0; - border-end-start-radius: 0; - border-end-end-radius: 0; - } - - .media-gallery__item:nth-child(4) { - border-start-start-radius: 0; - border-end-start-radius: 0; - border-start-end-radius: 0; - } - } } -.media-gallery__alt__label, -.media-gallery__gifv__label { - display: flex; - align-items: center; - justify-content: center; +.media-gallery__alt__label { + display: block; + text-align: center; color: $white; + border: 0; background: rgba($black, 0.65); backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%); padding: 3px 8px; @@ -7491,8 +7508,41 @@ img.modal-warning { font-size: 12px; font-weight: 700; z-index: 1; - pointer-events: none; line-height: 20px; + cursor: pointer; + pointer-events: auto; + + &--non-interactive { + pointer-events: none; + } +} + +.media-gallery__alt__popover { + background: rgba($black, 0.65); + backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%); + border-radius: 4px; + box-shadow: var(--dropdown-shadow); + padding: 16px; + min-width: 16em; + min-height: 2em; + max-width: 22em; + max-height: 30em; + overflow-y: auto; + + h4 { + font-size: 15px; + line-height: 20px; + font-weight: 500; + color: $white; + margin-bottom: 8px; + } + + p { + font-size: 15px; + line-height: 20px; + color: rgba($white, 0.85); + white-space: pre-line; + } } .attachment-list { @@ -7566,10 +7616,68 @@ img.modal-warning { width: 100%; min-height: 64px; display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: 50% 50%; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; gap: 2px; + &--layout-2 { + & > .media-gallery__item:nth-child(1) { + border-end-end-radius: 0; + border-start-end-radius: 0; + } + + & > .media-gallery__item:nth-child(2) { + border-start-start-radius: 0; + border-end-start-radius: 0; + } + } + + &--layout-3 { + & > .media-gallery__item:nth-child(1) { + border-end-end-radius: 0; + border-start-end-radius: 0; + } + + & > .media-gallery__item:nth-child(2) { + border-start-start-radius: 0; + border-end-start-radius: 0; + border-end-end-radius: 0; + } + + & > .media-gallery__item:nth-child(3) { + border-start-start-radius: 0; + border-end-start-radius: 0; + border-start-end-radius: 0; + } + } + + &--layout-4 { + & > .media-gallery__item:nth-child(1) { + border-end-end-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: 0; + } + + & > .media-gallery__item:nth-child(2) { + border-start-start-radius: 0; + border-end-start-radius: 0; + border-end-end-radius: 0; + } + + & > .media-gallery__item:nth-child(3) { + border-start-start-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: 0; + border-end-end-radius: 0; + } + + & > .media-gallery__item:nth-child(4) { + border-start-start-radius: 0; + border-end-start-radius: 0; + border-start-end-radius: 0; + } + } + @include fullwidth-gallery; } @@ -7580,6 +7688,9 @@ img.modal-warning { position: relative; border-radius: 8px; overflow: hidden; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; + z-index: 1; &--tall { grid-row: span 2; @@ -7596,15 +7707,44 @@ img.modal-warning { &.letterbox { background: $base-shadow-color; } + + &--square { + aspect-ratio: 1; + } + + &__overlay { + position: absolute; + top: 0; + inset-inline-start: 0; + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + width: 100%; + height: 100%; + pointer-events: none; + padding: 8px; + z-index: 1; + + &--corner { + align-items: flex-start; + justify-content: flex-end; + } + + .icon { + color: $white; + filter: var(--overlay-icon-shadow); + } + } } .media-gallery__item-thumbnail { - cursor: zoom-in; + cursor: pointer; display: block; text-decoration: none; color: $secondary-text-color; position: relative; - z-index: 1; + z-index: -1; &, img { @@ -7626,7 +7766,7 @@ img.modal-warning { position: absolute; top: 0; inset-inline-start: 0; - z-index: 0; + z-index: -2; background: $base-overlay-background; &--hidden { @@ -7639,10 +7779,11 @@ img.modal-warning { overflow: hidden; position: relative; width: 100%; + z-index: -1; } .media-gallery__item-gifv-thumbnail { - cursor: zoom-in; + cursor: pointer; height: 100%; width: 100%; object-fit: contain; @@ -7654,13 +7795,6 @@ img.modal-warning { } } -.media-gallery__item-thumbnail-label { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - overflow: hidden; - position: absolute; -} - /* End Media Gallery */ .detailed, @@ -7683,6 +7817,8 @@ img.modal-warning { border-radius: 8px; padding-bottom: 44px; width: 100%; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; &.editable { border-radius: 0; @@ -7739,6 +7875,7 @@ img.modal-warning { .video-player__controls { padding-top: 10px; background: transparent; + z-index: 1; } } @@ -7752,16 +7889,15 @@ img.modal-warning { color: $white; display: flex; align-items: center; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; + z-index: 2; &.editable { border-radius: 0; height: 100% !important; } - &:focus { - outline: 0; - } - .detailed-status & { width: 100%; height: 100%; @@ -7773,7 +7909,7 @@ img.modal-warning { display: block; max-width: 100vw; max-height: 80vh; - z-index: 1; + z-index: -2; position: relative; } @@ -7800,7 +7936,7 @@ img.modal-warning { &__controls { position: absolute; direction: ltr; - z-index: 2; + z-index: -1; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; @@ -8115,26 +8251,16 @@ img.modal-warning { } .account-gallery__container { - display: flex; - flex-wrap: wrap; - padding: 4px 2px; -} + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 2px; -.account-gallery__item { - border: 0; - box-sizing: border-box; - display: block; - position: relative; - border-radius: 4px; - overflow: hidden; - margin: 2px; + .media-gallery__item { + border-radius: 0; + } - &__icons { - position: absolute; - top: 50%; - inset-inline-start: 50%; - transform: translate(-50%, -50%); - font-size: 24px; + .load-more { + grid-column: span 3; } } diff --git a/app/javascript/flavours/glitch/styles/dashboard.scss b/app/javascript/flavours/glitch/styles/dashboard.scss index 1621220ccb522e..d049b2456c1795 100644 --- a/app/javascript/flavours/glitch/styles/dashboard.scss +++ b/app/javascript/flavours/glitch/styles/dashboard.scss @@ -86,9 +86,7 @@ color: $primary-text-color; transition: all 100ms ease-in; font-size: 14px; - padding: 0 16px; - line-height: 36px; - height: 36px; + padding: 8px 16px; text-decoration: none; margin-bottom: 4px; diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 29f4fe04f70a29..63346bb5ca9188 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -313,6 +313,10 @@ code { ul { columns: 2; + + @media screen and (max-width: $mobile-breakpoint) { + columns: 1; + } } } diff --git a/app/javascript/flavours/glitch/styles/reset.scss b/app/javascript/flavours/glitch/styles/reset.scss index 5a4152826d9e4b..fc0305baf3cdb4 100644 --- a/app/javascript/flavours/glitch/styles/reset.scss +++ b/app/javascript/flavours/glitch/styles/reset.scss @@ -56,7 +56,6 @@ table { @supports not selector(::-webkit-scrollbar) { html { scrollbar-color: $action-button-color var(--background-border-color); - scrollbar-width: thin; } } diff --git a/app/javascript/flavours/glitch/styles/tables.scss b/app/javascript/flavours/glitch/styles/tables.scss index 6c7723b60d774e..c84f672a6f345e 100644 --- a/app/javascript/flavours/glitch/styles/tables.scss +++ b/app/javascript/flavours/glitch/styles/tables.scss @@ -355,6 +355,10 @@ a.table-action-link { @media screen and (max-width: $no-gap-breakpoint) { border-top: 1px solid var(--background-border-color); } + + &--no-toolbar { + border-top: 1px solid var(--background-border-color); + } } @media screen and (width <= 870px) { diff --git a/app/javascript/flavours/glitch/styles/variables.scss b/app/javascript/flavours/glitch/styles/variables.scss index 111034fc6203a0..d19db06855957b 100644 --- a/app/javascript/flavours/glitch/styles/variables.scss +++ b/app/javascript/flavours/glitch/styles/variables.scss @@ -87,7 +87,7 @@ $media-modal-media-max-width: 100%; // put margins on top and bottom of image to avoid the screen covered by image. $media-modal-media-max-height: 80%; -$no-gap-breakpoint: 1207px; +$no-gap-breakpoint: 1175px; $mobile-breakpoint: 630px; $font-sans-serif: 'mastodon-font-sans-serif' !default; @@ -117,4 +117,9 @@ $dismiss-overlay-width: 4rem; --surface-variant-active-background-color: #{lighten($ui-base-color, 4%)}; --on-surface-color: #{transparentize($ui-base-color, 0.5)}; --avatar-border-radius: 8px; + --media-outline-color: #{rgba(#fcf8ff, 0.15)}; + --overlay-icon-shadow: drop-shadow(0 0 8px #{rgba($base-shadow-color, 0.25)}); + --error-background-color: #{darken($error-red, 16%)}; + --error-active-background-color: #{darken($error-red, 12%)}; + --on-error-color: #fff; } diff --git a/app/javascript/flavours/glitch/utils/debounce.ts b/app/javascript/flavours/glitch/utils/debounce.ts new file mode 100644 index 00000000000000..1ca979153faa34 --- /dev/null +++ b/app/javascript/flavours/glitch/utils/debounce.ts @@ -0,0 +1,23 @@ +import { debounce } from 'lodash'; + +import type { AppDispatch } from 'flavours/glitch/store'; + +export const debounceWithDispatchAndArguments = ( + fn: (dispatch: AppDispatch, ...args: T[]) => void, + { delay = 100 }, +) => { + let argumentBuffer: T[] = []; + let dispatchBuffer: AppDispatch; + + const wrapped = debounce(() => { + const tmpBuffer = argumentBuffer; + argumentBuffer = []; + fn(dispatchBuffer, ...tmpBuffer); + }, delay); + + return (dispatch: AppDispatch, ...args: T[]) => { + dispatchBuffer = dispatch; + argumentBuffer.push(...args); + wrapped(); + }; +}; diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index 9144235195e3f5..3d0e8b8c9054b1 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -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); }; } diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts index 9d3fc0d4254dcf..b40b04f8ccfd69 100644 --- a/app/javascript/mastodon/actions/notification_groups.ts +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -68,10 +68,15 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } +const supportedGroupedNotificationTypes = ['favourite', 'reblog']; + export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => - apiFetchNotificationGroups({ exclude_types: getExcludedTypes(getState()) }), + apiFetchNotificationGroups({ + grouped_types: supportedGroupedNotificationTypes, + exclude_types: getExcludedTypes(getState()), + }), ({ notifications, accounts, statuses }, { dispatch }) => { dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedStatuses(statuses)); @@ -93,6 +98,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ + grouped_types: supportedGroupedNotificationTypes, max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -109,6 +115,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { 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 diff --git a/app/javascript/mastodon/actions/notification_policies.ts b/app/javascript/mastodon/actions/notification_policies.ts index b182bcf6996326..fd798eaad7e834 100644 --- a/app/javascript/mastodon/actions/notification_policies.ts +++ b/app/javascript/mastodon/actions/notification_policies.ts @@ -17,6 +17,6 @@ export const updateNotificationsPolicy = createDataLoadingThunk( (policy: Partial) => apiUpdateNotificationsPolicy(policy), ); -export const decreasePendingNotificationsCount = createAction( - 'notificationPolicy/decreasePendingNotificationCount', +export const decreasePendingRequestsCount = createAction( + 'notificationPolicy/decreasePendingRequestsCount', ); diff --git a/app/javascript/mastodon/actions/notification_requests.ts b/app/javascript/mastodon/actions/notification_requests.ts index ef9cbef03ee4bb..8352ff2aadbf3e 100644 --- a/app/javascript/mastodon/actions/notification_requests.ts +++ b/app/javascript/mastodon/actions/notification_requests.ts @@ -13,11 +13,11 @@ import type { ApiNotificationJSON, } from 'mastodon/api_types/notifications'; import type { ApiStatusJSON } from 'mastodon/api_types/statuses'; -import type { AppDispatch, RootState } from 'mastodon/store'; +import type { AppDispatch } from 'mastodon/store'; import { createDataLoadingThunk } from 'mastodon/store/typed_functions'; import { importFetchedAccounts, importFetchedStatuses } from './importer'; -import { decreasePendingNotificationsCount } from './notification_policies'; +import { decreasePendingRequestsCount } from './notification_policies'; // TODO: refactor with notification_groups function dispatchAssociatedRecords( @@ -169,19 +169,11 @@ export const expandNotificationsForRequest = createDataLoadingThunk( }, ); -const selectNotificationCountForRequest = (state: RootState, id: string) => { - const requests = state.notificationRequests.items; - const thisRequest = requests.find((request) => request.id === id); - return thisRequest ? thisRequest.notifications_count : 0; -}; - export const acceptNotificationRequest = createDataLoadingThunk( 'notificationRequest/accept', ({ id }: { id: string }) => apiAcceptNotificationRequest(id), - (_data, { dispatch, getState, discardLoadData, actionArg: { id } }) => { - const count = selectNotificationCountForRequest(getState(), id); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData }) => { + dispatch(decreasePendingRequestsCount(1)); // The payload is not used in any functions return discardLoadData; @@ -191,10 +183,8 @@ export const acceptNotificationRequest = createDataLoadingThunk( export const dismissNotificationRequest = createDataLoadingThunk( 'notificationRequest/dismiss', ({ id }: { id: string }) => apiDismissNotificationRequest(id), - (_data, { dispatch, getState, discardLoadData, actionArg: { id } }) => { - const count = selectNotificationCountForRequest(getState(), id); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData }) => { + dispatch(decreasePendingRequestsCount(1)); // The payload is not used in any functions return discardLoadData; @@ -204,13 +194,8 @@ export const dismissNotificationRequest = createDataLoadingThunk( export const acceptNotificationRequests = createDataLoadingThunk( 'notificationRequests/acceptBulk', ({ ids }: { ids: string[] }) => apiAcceptNotificationRequests(ids), - (_data, { dispatch, getState, discardLoadData, actionArg: { ids } }) => { - const count = ids.reduce( - (count, id) => count + selectNotificationCountForRequest(getState(), id), - 0, - ); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData, actionArg: { ids } }) => { + dispatch(decreasePendingRequestsCount(ids.length)); // The payload is not used in any functions return discardLoadData; @@ -220,13 +205,8 @@ export const acceptNotificationRequests = createDataLoadingThunk( export const dismissNotificationRequests = createDataLoadingThunk( 'notificationRequests/dismissBulk', ({ ids }: { ids: string[] }) => apiDismissNotificationRequests(ids), - (_data, { dispatch, getState, discardLoadData, actionArg: { ids } }) => { - const count = ids.reduce( - (count, id) => count + selectNotificationCountForRequest(getState(), id), - 0, - ); - - dispatch(decreasePendingNotificationsCount(count)); + (_data, { dispatch, discardLoadData, actionArg: { ids } }) => { + dispatch(decreasePendingRequestsCount(ids.length)); // The payload is not used in any functions return discardLoadData; diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 14072562d4c0e9..4c6e27cd5f8d2e 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -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, @@ -56,14 +56,6 @@ defineMessages({ 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)); - } -}; - export const loadPending = () => ({ type: NOTIFICATIONS_LOAD_PENDING, }); @@ -106,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, @@ -199,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)); diff --git a/app/javascript/mastodon/api.ts b/app/javascript/mastodon/api.ts index 25bb25547cf94d..51cbe0b6954e09 100644 --- a/app/javascript/mastodon/api.ts +++ b/app/javascript/mastodon/api.ts @@ -70,6 +70,7 @@ export async function apiRequest( args: { params?: RequestParamsOrData; data?: RequestParamsOrData; + timeout?: number; } = {}, ) { const { data } = await api().request({ diff --git a/app/javascript/mastodon/api/notifications.ts b/app/javascript/mastodon/api/notifications.ts index 24d526655cefc4..813e2f3a1701dc 100644 --- a/app/javascript/mastodon/api/notifications.ts +++ b/app/javascript/mastodon/api/notifications.ts @@ -31,6 +31,7 @@ export const apiFetchNotifications = async ( export const apiFetchNotificationGroups = async (params?: { url?: string; + grouped_types?: string[]; exclude_types?: string[]; max_id?: string; since_id?: string; @@ -91,5 +92,5 @@ export const apiAcceptNotificationRequests = async (id: string[]) => { }; export const apiDismissNotificationRequests = async (id: string[]) => { - return apiRequestPost('v1/notifications/dismiss/dismiss', { id }); + return apiRequestPost('v1/notifications/requests/dismiss', { id }); }; diff --git a/app/javascript/mastodon/components/alt_text_badge.tsx b/app/javascript/mastodon/components/alt_text_badge.tsx new file mode 100644 index 00000000000000..99bec1ee51cf71 --- /dev/null +++ b/app/javascript/mastodon/components/alt_text_badge.tsx @@ -0,0 +1,67 @@ +import { useState, useCallback, useRef } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import Overlay from 'react-overlays/Overlay'; +import type { + OffsetValue, + UsePopperOptions, +} from 'react-overlays/esm/usePopper'; + +const offset = [0, 4] as OffsetValue; +const popperConfig = { strategy: 'fixed' } as UsePopperOptions; + +export const AltTextBadge: React.FC<{ + description: string; +}> = ({ description }) => { + const anchorRef = useRef(null); + const [open, setOpen] = useState(false); + + const handleClick = useCallback(() => { + setOpen((v) => !v); + }, [setOpen]); + + const handleClose = useCallback(() => { + setOpen(false); + }, [setOpen]); + + return ( + <> + + + + {({ props }) => ( +
+
+

+ +

+

{description}

+
+
+ )} +
+ + ); +}; diff --git a/app/javascript/mastodon/components/button.tsx b/app/javascript/mastodon/components/button.tsx index c76aaea42f26fc..3e720f7ceead2a 100644 --- a/app/javascript/mastodon/components/button.tsx +++ b/app/javascript/mastodon/components/button.tsx @@ -7,6 +7,7 @@ interface BaseProps extends Omit, 'children'> { block?: boolean; secondary?: boolean; + dangerous?: boolean; } interface PropsChildren extends PropsWithChildren { @@ -26,6 +27,7 @@ export const Button: React.FC = ({ disabled, block, secondary, + dangerous, className, title, text, @@ -46,6 +48,7 @@ export const Button: React.FC = ({ className={classNames('button', className, { 'button-secondary': secondary, 'button--block': block, + 'button--dangerous': dangerous, })} disabled={disabled} onClick={handleClick} diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index ba54b7f903645a..84cb4e04dcb5db 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -10,7 +10,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { debounce } from 'lodash'; +import { AltTextBadge } from 'mastodon/components/alt_text_badge'; import { Blurhash } from 'mastodon/components/blurhash'; +import { formatTime } from 'mastodon/features/video'; import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state'; @@ -57,7 +59,7 @@ class Item extends PureComponent { hoverToPlay () { const { attachment } = this.props; - return !this.getAutoPlay() && attachment.get('type') === 'gifv'; + return !this.getAutoPlay() && ['gifv', 'video'].includes(attachment.get('type')); } handleClick = (e) => { @@ -96,7 +98,7 @@ class Item extends PureComponent { } if (attachment.get('description')?.length > 0) { - badges.push(ALT); + badges.push(); } const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); @@ -150,10 +152,15 @@ class Item extends PureComponent { /> ); - } else if (attachment.get('type') === 'gifv') { + } else if (['gifv', 'video'].includes(attachment.get('type'))) { const autoPlay = this.getAutoPlay(); + const duration = attachment.getIn(['meta', 'original', 'duration']); - badges.push(GIF); + if (attachment.get('type') === 'gifv') { + badges.push(GIF); + } else { + badges.push({formatTime(Math.floor(duration))}); + } thumbnail = (
@@ -167,6 +174,7 @@ class Item extends PureComponent { onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} + onLoadedData={this.handleImageLoad} autoPlay={autoPlay} playsInline loop diff --git a/app/javascript/mastodon/components/navigation_portal.tsx b/app/javascript/mastodon/components/navigation_portal.tsx index 46f2c0bfacdc89..08f91ce18aaf58 100644 --- a/app/javascript/mastodon/components/navigation_portal.tsx +++ b/app/javascript/mastodon/components/navigation_portal.tsx @@ -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 ? ( - <> -
- - - ) : null; +const DefaultNavigation: React.FC = () => (showTrends ? : null); export const NavigationPortal: React.FC = () => ( - - - - - - - - - +
+ + + + + + + + + +
); diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 6c32fd245d7a1b..46926b4aaead34 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -449,7 +449,25 @@ class Status extends ImmutablePureComponent { } else if (status.get('media_attachments').size > 0) { const language = status.getIn(['translation', 'language']) || status.get('language'); - if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { + if (['image', 'gifv'].includes(status.getIn(['media_attachments', 0, 'type'])) || status.get('media_attachments').size > 1) { + media = ( + + {Component => ( + + )} + + ); + } else if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); @@ -501,24 +519,6 @@ class Status extends ImmutablePureComponent { )} ); - } else { - media = ( - - {Component => ( - - )} - - ); } } else if (status.get('spoiler_text').length === 0 && status.get('card')) { media = ( diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx index 165e81c7d88a0f..75531abf568cf7 100644 --- a/app/javascript/mastodon/components/status_action_bar.jsx +++ b/app/javascript/mastodon/components/status_action_bar.jsx @@ -375,20 +375,29 @@ class StatusActionBar extends ImmutablePureComponent { return (
- - - - - - +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
); } diff --git a/app/javascript/mastodon/features/account/navigation.jsx b/app/javascript/mastodon/features/account/navigation.jsx index ccebe9043a1302..aa78135de247a9 100644 --- a/app/javascript/mastodon/features/account/navigation.jsx +++ b/app/javascript/mastodon/features/account/navigation.jsx @@ -43,10 +43,7 @@ class AccountNavigation extends PureComponent { } return ( - <> -
- - + ); } diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx deleted file mode 100644 index 087e7757533327..00000000000000 --- a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx +++ /dev/null @@ -1,158 +0,0 @@ -import PropTypes from 'prop-types'; - -import classNames from 'classnames'; - -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; - -import AudiotrackIcon from '@/material-icons/400-24px/music_note.svg?react'; -import PlayArrowIcon from '@/material-icons/400-24px/play_arrow.svg?react'; -import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react'; -import { Blurhash } from 'mastodon/components/blurhash'; -import { Icon } from 'mastodon/components/icon'; -import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state'; - -export default class MediaItem extends ImmutablePureComponent { - - static propTypes = { - attachment: ImmutablePropTypes.map.isRequired, - displayWidth: PropTypes.number.isRequired, - onOpenMedia: PropTypes.func.isRequired, - }; - - state = { - visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all', - loaded: false, - }; - - handleImageLoad = () => { - this.setState({ loaded: true }); - }; - - handleMouseEnter = e => { - if (this.hoverToPlay()) { - e.target.play(); - } - }; - - handleMouseLeave = e => { - if (this.hoverToPlay()) { - e.target.pause(); - e.target.currentTime = 0; - } - }; - - hoverToPlay () { - return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1; - } - - handleClick = e => { - if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - - if (this.state.visible) { - this.props.onOpenMedia(this.props.attachment); - } else { - this.setState({ visible: true }); - } - } - }; - - render () { - const { attachment, displayWidth } = this.props; - const { visible, loaded } = this.state; - - const width = `${Math.floor((displayWidth - 4) / 3) - 4}px`; - const height = width; - const status = attachment.get('status'); - const title = status.get('spoiler_text') || attachment.get('description'); - - let thumbnail, label, icon, content; - - if (!visible) { - icon = ( - - - - ); - } else { - if (['audio', 'video'].includes(attachment.get('type'))) { - content = ( - {attachment.get('description')} - ); - - if (attachment.get('type') === 'audio') { - label = ; - } else { - label = ; - } - } else if (attachment.get('type') === 'image') { - const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0; - const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0; - const x = ((focusX / 2) + .5) * 100; - const y = ((focusY / -2) + .5) * 100; - - content = ( - {attachment.get('description')} - ); - } else if (attachment.get('type') === 'gifv') { - content = ( -
diff --git a/app/javascript/mastodon/features/ui/components/column_link.jsx b/app/javascript/mastodon/features/ui/components/column_link.jsx index 6ef122c07be844..3386c17f071f5e 100644 --- a/app/javascript/mastodon/features/ui/components/column_link.jsx +++ b/app/javascript/mastodon/features/ui/components/column_link.jsx @@ -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' ? {badge} : null; const iconElement = (typeof icon === 'string' || iconComponent) ? : icon; const activeIconElement = activeIcon ?? (activeIconComponent ? : iconElement); @@ -43,6 +43,7 @@ ColumnLink.propTypes = { method: PropTypes.string, badge: PropTypes.node, transparent: PropTypes.bool, + optional: PropTypes.bool, }; export default ColumnLink; diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx index ff76d5bcb296d3..de957a79b67c57 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.jsx +++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx @@ -62,7 +62,7 @@ export default class ColumnsArea extends ImmutablePureComponent { }; // Corresponds to (max-width: $no-gap-breakpoint - 1px) in SCSS - mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1206px)'); + mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 1174px)'); state = { renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches), diff --git a/app/javascript/mastodon/features/ui/components/domain_block_modal.jsx b/app/javascript/mastodon/features/ui/components/domain_block_modal.jsx deleted file mode 100644 index 78d5cbb1301b2b..00000000000000 --- a/app/javascript/mastodon/features/ui/components/domain_block_modal.jsx +++ /dev/null @@ -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 ( -
-
-
-
- -
- -
-

-
{domain}
-
-
- -
-
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
-
-
- -
-
- - -
- - - - -
-
-
- ); -}; - -DomainBlockModal.propTypes = { - domain: PropTypes.string.isRequired, - accountId: PropTypes.string.isRequired, - acct: PropTypes.string.isRequired, -}; - -export default DomainBlockModal; diff --git a/app/javascript/mastodon/features/ui/components/domain_block_modal.tsx b/app/javascript/mastodon/features/ui/components/domain_block_modal.tsx new file mode 100644 index 00000000000000..ec0899114415a3 --- /dev/null +++ b/app/javascript/mastodon/features/ui/components/domain_block_modal.tsx @@ -0,0 +1,223 @@ +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 | 'error' | 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('GET', 'v1/domain_blocks/preview', { + params: { domain }, + timeout: 5000, + }) + .then((data) => { + setPreview(data); + setLoading(false); + return ''; + }) + .catch(() => { + setPreview('error'); + setLoading(false); + }); + }, [setPreview, setLoading, domain]); + + return ( +
+
+
+
+ +
+ +
+

+ +

+
{domain}
+
+
+ +
+ {preview && + preview !== 'error' && + preview.followers_count + preview.following_count > 0 && ( +
+
+ +
+
+ + + ), + followingCount: preview.following_count, + followingCountDisplay: ( + + ), + }} + /> + +
+
+ )} + + {preview === 'error' && ( +
+
+ +
+
+ + + +
+
+ )} + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ + +
+ + + + +
+
+
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default DomainBlockModal; diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx index 0ca21e89765449..8fa20a554d3869 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -120,14 +120,17 @@ class NavigationPanel extends Component { let banner = undefined; - if(transientSingleColumn) - banner = (
- {intl.formatMessage(messages.openedInClassicInterface)} - {" "} - - {intl.formatMessage(messages.advancedInterface)} - -
); + if (transientSingleColumn) { + banner = ( +
+ {intl.formatMessage(messages.openedInClassicInterface)} + {" "} + + {intl.formatMessage(messages.advancedInterface)} + +
+ ); + } return (
@@ -141,54 +144,58 @@ class NavigationPanel extends Component {
} - {signedIn && ( - <> - - - - - )} - - {trendsEnabled ? ( - - ) : ( - - )} - - {(signedIn || timelinePreview) && ( - - )} - - {!signedIn && ( -
+
+ {signedIn && ( + <> + + + + + )} + + {trendsEnabled ? ( + + ) : ( + + )} + + {(signedIn || timelinePreview) && ( + + )} + + {!signedIn && ( +
+
+ { disabledAccountId ? : } +
+ )} + + {signedIn && ( + <> + + + + + + + +
+ + + + {canManageReports(permissions) && } + {canViewAdminDashboard(permissions) && } + + )} + +

- { disabledAccountId ? : } +
- )} - - {signedIn && ( - <> - - - - - - - -
- - - - {canManageReports(permissions) && } - {canViewAdminDashboard(permissions) && } - - )} - -
-
-
+
+
); diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index a6e3640478464c..2f9f962b810c4c 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -186,7 +186,7 @@ class SwitchingColumnsArea extends PureComponent { {redirect} {singleColumn ? : null} - {singleColumn && pathName.startsWith('/deck/') ? : null} + {singleColumn && pathName.startsWith('/deck/') ? : null} {/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */} {!singleColumn && pathName === '/getting-started' ? : null} {!singleColumn && pathName === '/home' ? : null} diff --git a/app/javascript/mastodon/locales/an.json b/app/javascript/mastodon/locales/an.json index fcd30804219961..be303985ee2fee 100644 --- a/app/javascript/mastodon/locales/an.json +++ b/app/javascript/mastodon/locales/an.json @@ -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", diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index d50ca8dbb59bc9..18830708db615f 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -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": "يتيح لك التواصل والتفاعل مع الناس ليس فقط على ماستدون، ولكن عبر تطبيقات اجتماعية مختلفة أيضا.", "domain_pill.activitypub_like_language": "إنّ ActivityPub مثل لغة ماستدون التي يتحدث بها مع شبكات اجتماعية أخرى.", @@ -420,8 +419,6 @@ "keyboard_shortcuts.unfocus": "لإلغاء التركيز على حقل النص أو نافذة البحث", "keyboard_shortcuts.up": "للانتقال إلى أعلى القائمة", "lightbox.close": "إغلاق", - "lightbox.compress": "ضغط مربع عرض الصورة", - "lightbox.expand": "توسيع مربع عرض الصور", "lightbox.next": "التالي", "lightbox.previous": "العودة", "limited_account_hint.action": "إظهار الملف التعريفي على أي حال", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 8c28e71d2cf2b5..797d8cc22e578d 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -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": "Усе роўна паказваць профіль", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 507b8d29372570..1e462ba752757c 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Скоростта е ограничена", "alert.unexpected.message": "Възникна неочаквана грешка.", "alert.unexpected.title": "Опаа!", + "alt_text_badge.title": "Алтернативен текст", "announcement.announcement": "Оповестяване", "attachments_list.unprocessed": "(необработено)", "audio.hide": "Скриване на звука", @@ -220,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, говорещ с други социални мрежи.", @@ -419,8 +419,6 @@ "keyboard_shortcuts.unfocus": "Разфокусиране на текстовото поле за съставяне/търсене", "keyboard_shortcuts.up": "Преместване нагоре в списъка", "lightbox.close": "Затваряне", - "lightbox.compress": "Свиване на полето за преглед на образи", - "lightbox.expand": "Разгъване на полето за преглед на образи", "lightbox.next": "Напред", "lightbox.previous": "Назад", "limited_account_hint.action": "Показване на профила въпреки това", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index 18616fcef2cc29..79949ed91f132e 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -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", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 3cdeab3ae42d46..b79ac156e229ac 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Límit de freqüència", "alert.unexpected.message": "S'ha produït un error inesperat.", "alert.unexpected.title": "Vaja!", + "alt_text_badge.title": "Text alternatiu", "announcement.announcement": "Anunci", "attachments_list.unprocessed": "(sense processar)", "audio.hide": "Amaga l'àudio", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "Perdreu seguidors i gent a qui seguiu d'aquest servidor.", "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 +434,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ó d’imatge", - "lightbox.expand": "Amplia el quadre de visualització d’imatge", "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}", @@ -850,6 +852,11 @@ "upload_error.poll": "No es permet carregar fitxers a les enquestes.", "upload_form.audio_description": "Descriu-ho per a persones amb problemes d'audició", "upload_form.description": "Descriu-ho per a persones amb problemes de visió", + "upload_form.drag_and_drop.instructions": "Per a agafar un fitxer multimèdia adjunt, premeu l'espai o la tecla Enter. Mentre l'arrossegueu, utilitzeu les fletxes per a moure l'adjunt en qualsevol direcció. Premeu espai o Enter un altre cop per a deixar-lo anar a la seva nova posició, o premeu la tecla d'escapament per cancel·lar.", + "upload_form.drag_and_drop.on_drag_cancel": "S'ha cancel·lat l'arrossegament. S'ha deixat anar l'adjunt multimèdia {item}.", + "upload_form.drag_and_drop.on_drag_end": "S'ha deixat anar l'adjunt multimèdia {item}.", + "upload_form.drag_and_drop.on_drag_over": "S'ha mogut l'adjunt multimèdia {item}.", + "upload_form.drag_and_drop.on_drag_start": "S'ha agafat l'adjunt multimèdia {item}.", "upload_form.edit": "Edita", "upload_form.thumbnail": "Canvia la miniatura", "upload_form.video_description": "Descriu-ho per a persones amb problemes de visió o audició", diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json index 2a3a391eab4885..bea6e5ceecc12f 100644 --- a/app/javascript/mastodon/locales/ckb.json +++ b/app/javascript/mastodon/locales/ckb.json @@ -335,8 +335,6 @@ "keyboard_shortcuts.unfocus": "بۆ دروستکردنی ناوچەی دەق/گەڕان", "keyboard_shortcuts.up": "بۆ ئەوەی لە لیستەکەدا بڕۆیت", "lightbox.close": "دابخە", - "lightbox.compress": "سندوقی نیشاندانی وێنە بپەستێنە", - "lightbox.expand": "فراوانکردنی سندوقی بینینی وێنە", "lightbox.next": "داهاتوو", "lightbox.previous": "پێشوو", "limited_account_hint.action": "بەهەر حاڵ پڕۆفایلی پیشان بدە", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 37eb945615a192..043061769befe3 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -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", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index af7a0128132bf0..1f2804daa5f657 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -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", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 51ea1bdf3a6ecc..f2d0708882fae5 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -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}", @@ -787,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", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 2c36869622ce80..659f807d050c59 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Hastighedsbegrænset", "alert.unexpected.message": "En uventet fejl opstod.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Alt text", "announcement.announcement": "Bekendtgørelse", "attachments_list.unprocessed": "(ubehandlet)", "audio.hide": "Skjul lyd", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "Alle følgere og personer som følges på denne server mistes.", "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 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "Filupload ikke tilladt for afstemninger.", "upload_form.audio_description": "Beskrivelse til hørehæmmede", "upload_form.description": "Beskrivelse til svagtseende", + "upload_form.drag_and_drop.instructions": "For at opsamle en medievedhæftning, tryk på Mellemrum eller Retur. Mens der trækkes, benyt piletasterne til at flytte medievedhæftningen i en given retning. Tryk på Mellemrum eller Retur igen for at slippe medievedhæftningen på den nye position, eller tryk på Escape for at afbryde.", + "upload_form.drag_and_drop.on_drag_cancel": "Træk blev afbrudt. Medievedhæftningen {item} blev sluppet.", + "upload_form.drag_and_drop.on_drag_end": "Medievedhæftningen {item} er sluppet.", + "upload_form.drag_and_drop.on_drag_over": "Medievedhæftningen {item} er flyttet.", + "upload_form.drag_and_drop.on_drag_start": "Opsamlede medievedhæftningen {item}.", "upload_form.edit": "Redigér", "upload_form.thumbnail": "Skift miniature", "upload_form.video_description": "Beskrivelse for hørehæmmede eller synshandicappede personer", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index e6c086bfa29b84..6f45d4fe5329a3 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Anfragelimit überschritten", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", "alert.unexpected.title": "Oha!", + "alt_text_badge.title": "Bildbeschreibung", "announcement.announcement": "Ankündigung", "attachments_list.unprocessed": "(ausstehend)", "audio.hide": "Audio ausblenden", @@ -155,7 +156,7 @@ "compose_form.lock_disclaimer.lock": "geschützt", "compose_form.placeholder": "Was gibt’s 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,20 +222,21 @@ "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_will_lose_relationships": "Du wirst von diesem Server alle Follower und Profile, denen du dort folgst, verlieren.", "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.", "domain_pill.server": "Server", "domain_pill.their_handle": "Deren Adresse:", - "domain_pill.their_server": "Deren digitales Zuhause. Hier „leben“ alle Beiträge von diesem Profil.", + "domain_pill.their_server": "Deren digitale Heimat. Hier „leben“ alle Beiträge von diesem Profil.", "domain_pill.their_username": "Deren eindeutigen Identität auf dem betreffenden Server. Es ist möglich, Profile mit dem gleichen Profilnamen auf verschiedenen Servern zu finden.", "domain_pill.username": "Profilname", "domain_pill.whats_in_a_handle": "Was ist Teil der Adresse?", "domain_pill.who_they_are": "Adressen teilen mit, wer jemand ist und wo sich jemand aufhält. Daher kannst du mit Leuten im gesamten Social Web interagieren, wenn es eine durch ist.", "domain_pill.who_you_are": "Deine Adresse teilt mit, wer du bist und wo du dich aufhältst. Daher können andere Leute im gesamten Social Web mit dir interagieren, wenn es eine durch ist.", "domain_pill.your_handle": "Deine Adresse:", - "domain_pill.your_server": "Dein digitales Zuhause. Hier „leben“ alle Beiträge von dir. Dir gefällt es hier nicht? Du kannst jederzeit den Server wechseln und ebenso deine Follower übertragen.", + "domain_pill.your_server": "Deine digitale Heimat. Hier „leben“ alle Beiträge von dir. Falls es dir hier nicht gefällt, kannst du jederzeit den Server wechseln und ebenso deine Follower übertragen.", "domain_pill.your_username": "Deine eindeutige Identität auf diesem Server. Es ist möglich, Profile mit dem gleichen Profilnamen auf verschiedenen Servern zu finden.", "embed.instructions": "Du kannst diesen Beitrag auf deiner Website einbetten, indem du den nachfolgenden Code kopierst.", "embed.preview": "Vorschau:", @@ -432,10 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "Medien-Anhänge sind zusammen mit Umfragen nicht erlaubt.", "upload_form.audio_description": "Beschreibe für Menschen mit Hörbehinderung", "upload_form.description": "Beschreibe für Menschen mit Sehbehinderung", + "upload_form.drag_and_drop.instructions": "Drücke zum Aufnehmen eines Medienanhangs die Eingabe- oder Leertaste. Verwende beim Ziehen die Pfeiltasten, um den Medienanhang zur gewünschten Position zu bewegen. Drücke erneut die Eingabe- oder Leertaste, um den Medienanhang an der gewünschten Position abzulegen. Mit der Escape-Taste kannst du den Vorgang abbrechen.", + "upload_form.drag_and_drop.on_drag_cancel": "Das Ziehen wurde abgebrochen und der Medienanhang {item} wurde abgelegt.", + "upload_form.drag_and_drop.on_drag_end": "Der Medienanhang {item} wurde abgelegt.", + "upload_form.drag_and_drop.on_drag_over": "Der Medienanhang {item} wurde bewegt.", + "upload_form.drag_and_drop.on_drag_start": "Der Medienanhang {item} wurde aufgenommen.", "upload_form.edit": "Bearbeiten", "upload_form.thumbnail": "Vorschaubild ändern", "upload_form.video_description": "Beschreibe für Menschen mit einer Hör- oder Sehbehinderung", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 367efe1cd9b923..85f893c63ddc3e 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -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": "Προσωπικά", @@ -770,6 +777,7 @@ "status.bookmark": "Σελιδοδείκτης", "status.cancel_reblog_private": "Ακύρωση ενίσχυσης", "status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί", + "status.continued_thread": "Συνεχιζόμενο νήματος", "status.copy": "Αντιγραφή συνδέσμου ανάρτησης", "status.delete": "Διαγραφή", "status.detailed_status": "Προβολή λεπτομερούς συζήτησης", @@ -778,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": "Φιλτράρισμα αυτής της ανάρτησης", @@ -802,6 +811,7 @@ "status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.", "status.redraft": "Σβήσε & ξαναγράψε", "status.remove_bookmark": "Αφαίρεση σελιδοδείκτη", + "status.replied_in_thread": "Απαντήθηκε σε νήμα", "status.replied_to": "Απάντησε στον {name}", "status.reply": "Απάντησε", "status.replyAll": "Απάντησε στο νήμα συζήτησης", diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index c81f389b9dd2b1..b1d61ddd3dc746 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Rate limited", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", + "alt_text_badge.title": "Alt text", "announcement.announcement": "Announcement", "attachments_list.unprocessed": "(unprocessed)", "audio.hide": "Hide audio", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "You will lose all followers and people you follow from this server.", "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 +434,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}", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index d0563bb1b2c5cd..1e78745359aa28 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Rate limited", "alert.unexpected.message": "An unexpected error occurred.", "alert.unexpected.title": "Oops!", + "alt_text_badge.title": "Alt text", "announcement.announcement": "Announcement", "attachments_list.unprocessed": "(unprocessed)", "audio.hide": "Hide audio", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "You will lose all followers and people you follow from this server.", "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.", @@ -850,6 +852,11 @@ "upload_error.poll": "File upload not allowed with polls.", "upload_form.audio_description": "Describe for people who are deaf or hard of hearing", "upload_form.description": "Describe for people who are blind or have low vision", + "upload_form.drag_and_drop.instructions": "To pick up a media attachment, press space or enter. While dragging, use the arrow keys to move the media attachment in any given direction. Press space or enter again to drop the media attachment in its new position, or press escape to cancel.", + "upload_form.drag_and_drop.on_drag_cancel": "Dragging was cancelled. Media attachment {item} was dropped.", + "upload_form.drag_and_drop.on_drag_end": "Media attachment {item} was dropped.", + "upload_form.drag_and_drop.on_drag_over": "Media attachment {item} was moved.", + "upload_form.drag_and_drop.on_drag_start": "Picked up media attachment {item}.", "upload_form.edit": "Edit", "upload_form.thumbnail": "Change thumbnail", "upload_form.video_description": "Describe for people who are deaf, hard of hearing, blind or have low vision", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index e162e732d07dab..4268c385359327 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Mesaĝkvante limigita", "alert.unexpected.message": "Neatendita eraro okazis.", "alert.unexpected.title": "Aj!", + "alt_text_badge.title": "Alt-teksto", "announcement.announcement": "Anoncoj", "attachments_list.unprocessed": "(neprilaborita)", "audio.hide": "Kaŝi aŭdion", @@ -215,8 +216,28 @@ "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_will_lose_relationships": "Vi perdos ĉiujn sekvantojn kaj homojn, kiujn vi sekvas de ĉi tiu servilo.", + "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 .", + "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 .", + "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", @@ -253,6 +274,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.", @@ -283,16 +305,28 @@ "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", @@ -321,6 +355,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", @@ -328,6 +370,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.", @@ -381,13 +434,14 @@ "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", @@ -407,8 +461,15 @@ "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", @@ -427,6 +488,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", @@ -437,28 +499,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 {count, plural, one {# alia} other {# aliaj}} ŝ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 {count, plural, one {# alia} other {# aliaj}} 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:", @@ -474,7 +579,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", @@ -485,7 +590,22 @@ "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", @@ -495,8 +615,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", @@ -517,7 +637,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", @@ -547,6 +667,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}", @@ -566,7 +687,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", @@ -609,10 +732,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", @@ -640,8 +766,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}", @@ -651,14 +780,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}", @@ -677,9 +810,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", @@ -717,6 +852,11 @@ "upload_error.poll": "Alŝuto de dosiero ne permesita kun balotenketo.", "upload_form.audio_description": "Priskribi por homoj kiuj malfacile aŭdi", "upload_form.description": "Priskribi por personoj, kiuj estas blindaj aŭ havas vidmalsufiĉon", + "upload_form.drag_and_drop.instructions": "Por preni amaskomunikilaron aldonaĵon, premu spacoklavon aŭ enen-klavon. Dum trenado, uzu la sagoklavojn por movi la amaskomunikilaron aldonaĵon en iu ajn direkto. Premu spacoklavon aŭ enen-klavon denove por faligi la amaskomunikilaron aldonaĵon en ĝia nova pozicio, aŭ premu eskapan klavon por nuligi.", + "upload_form.drag_and_drop.on_drag_cancel": "Trenado estis nuligita. Amaskomunikila aldonaĵo {item} estis forigita.", + "upload_form.drag_and_drop.on_drag_end": "Amaskomunikila aldonaĵo {item} estis forigita.", + "upload_form.drag_and_drop.on_drag_over": "Amaskomunikila aldonaĵo {item} estis movita.", + "upload_form.drag_and_drop.on_drag_start": "Prenis amaskomunikilan aldonaĵon {item}.", "upload_form.edit": "Redakti", "upload_form.thumbnail": "Ŝanĝi etigita bildo", "upload_form.video_description": "Priskribi por homoj kiuj malfacile aŭdi aŭ vidi", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 968b01babc28eb..609175d94f7460 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Acción limitada", "alert.unexpected.message": "Ocurrió un error.", "alert.unexpected.title": "¡Epa!", + "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", "attachments_list.unprocessed": "[sin procesar]", "audio.hide": "Ocultar audio", @@ -221,7 +222,8 @@ "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} cuenta que seguís} other {{followingCountDisplay} cuentas que seguís}}.", + "domain_block_modal.you_will_lose_relationships": "Perderás a todos los seguidores y cuentas a las que seguís de este servidor.", "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 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "No se permite la subida de archivos en encuestas.", "upload_form.audio_description": "Agregá una descripción para personas con dificultades auditivas", "upload_form.description": "Agregá una descripción para personas con dificultades visuales", + "upload_form.drag_and_drop.instructions": "Para recoger un archivo multimedia, pulsá la barra espaciadora o la tecla Enter. Mientras arrastrás, usá las teclas de flecha para mover el archivo multimedia en cualquier dirección. Volvé a pulsar la barra espaciadora o la tecla Enter para soltar el archivo multimedia en su nueva posición, o pulsá la tecla Escape para cancelar.", + "upload_form.drag_and_drop.on_drag_cancel": "Se canceló el arrastre. Se eliminó el archivo adjunto {item}.", + "upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} ha sido eliminado.", + "upload_form.drag_and_drop.on_drag_over": "El archivo adjunto {item} fue movido.", + "upload_form.drag_and_drop.on_drag_start": "Se ha recogido el archivo adjunto {item}.", "upload_form.edit": "Editar", "upload_form.thumbnail": "Cambiar miniatura", "upload_form.video_description": "Agregá una descripción para personas con dificultades auditivas o visuales", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index 5c8f44d4a7f5d7..7c2e4003380f9b 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Tarifa limitada", "alert.unexpected.message": "Hubo un error inesperado.", "alert.unexpected.title": "¡Ups!", + "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", @@ -94,7 +95,7 @@ "block_modal.they_cant_mention": "No pueden mencionarte ni seguirte.", "block_modal.they_cant_see_posts": "No pueden ver tus publicaciones y tú no verás las de ellos.", "block_modal.they_will_know": "Pueden ver que están bloqueados.", - "block_modal.title": "¿Bloquear usuario?", + "block_modal.title": "¿Deseas bloquear al 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": "¿Deseas impulsar la publicación?", @@ -172,9 +173,9 @@ "confirmations.block.confirm": "Bloquear", "confirmations.delete.confirm": "Eliminar", "confirmations.delete.message": "¿Estás seguro de que quieres borrar esta publicación?", - "confirmations.delete.title": "¿Eliminar publicación?", + "confirmations.delete.title": "¿Deseas eliminar la publicación?", "confirmations.delete_list.confirm": "Eliminar", - "confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?", + "confirmations.delete_list.message": "¿Estás seguro de que quieres eliminar esta lista de forma permanente?", "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?", @@ -190,7 +191,7 @@ "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": "¿Sobreescribir publicación?", + "confirmations.reply.title": "¿Deseas sobreescribir la 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?", @@ -220,8 +221,9 @@ "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.title": "¿Deseas bloquear el dominio?", + "domain_block_modal.you_will_lose_num_followers": "Vas a perder {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} y {followingCount, plural, one {{followingCountDisplay} persona a la que sigues} other {{followingCountDisplay} personas a las que sigas}}.", + "domain_block_modal.you_will_lose_relationships": "Perderás todos los seguidores y las personas que sigues de este servidor.", "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.", @@ -432,10 +434,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}", @@ -465,7 +467,7 @@ "mute_modal.show_options": "Mostrar opciones", "mute_modal.they_can_mention_and_follow": "Pueden mencionarte y seguirte, pero no verás nada de ellos.", "mute_modal.they_wont_know": "No sabrán que han sido silenciados.", - "mute_modal.title": "¿Silenciar usuario?", + "mute_modal.title": "¿Deseas silenciar el usuario?", "mute_modal.you_wont_see_mentions": "No verás publicaciones que los mencionen.", "mute_modal.you_wont_see_posts": "Todavía pueden ver tus publicaciones, pero tú no verás las de ellos.", "navigation_bar.about": "Acerca de", @@ -850,6 +852,11 @@ "upload_error.poll": "Subida de archivos no permitida con encuestas.", "upload_form.audio_description": "Describir para personas con problemas auditivos", "upload_form.description": "Describir para los usuarios con dificultad visual", + "upload_form.drag_and_drop.instructions": "Para recoger un archivo multimedia, pulsa la barra espaciadora o la tecla Enter. Mientras arrastras, utiliza las teclas de flecha para mover el archivo multimedia en cualquier dirección. Vuelve a pulsar la barra espaciadora o la tecla Enter para soltar el archivo multimedia en su nueva posición, o pulsa Escape para cancelar.", + "upload_form.drag_and_drop.on_drag_cancel": "Se canceló el arrastre. Se eliminó el archivo adjunto {item}.", + "upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} ha sido eliminado.", + "upload_form.drag_and_drop.on_drag_over": "El archivo adjunto {item} se ha movido.", + "upload_form.drag_and_drop.on_drag_start": "Se ha recogido el archivo adjunto {item}.", "upload_form.edit": "Editar", "upload_form.thumbnail": "Cambiar miniatura", "upload_form.video_description": "Describir para personas con problemas auditivos o visuales", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 6a428e353b3e69..b8414893382ace 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Tráfico limitado", "alert.unexpected.message": "Hubo un error inesperado.", "alert.unexpected.title": "¡Ups!", + "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "Perderás a todos los seguidores y gente a la que sigas de este servidor.", "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 +269,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 +344,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", @@ -432,10 +434,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}", @@ -637,7 +639,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", @@ -850,6 +852,11 @@ "upload_error.poll": "No se permite la subida de archivos con encuestas.", "upload_form.audio_description": "Describir para personas con problemas auditivos", "upload_form.description": "Describir para personas con discapacidad visual", + "upload_form.drag_and_drop.instructions": "Para recoger un archivo multimedia, pulsa la barra espaciadora o la tecla Enter. Mientras arrastras, utiliza las teclas de flecha para mover el archivo multimedia en cualquier dirección. Vuelve a pulsar la barra espaciadora o la tecla Enter para soltar el archivo multimedia en su nueva posición, o pulsa Escape para cancelar.", + "upload_form.drag_and_drop.on_drag_cancel": "Se canceló el arrastre. Se eliminó el archivo adjunto {item}.", + "upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} ha sido eliminado.", + "upload_form.drag_and_drop.on_drag_over": "El archivo adjunto {item} se ha movido.", + "upload_form.drag_and_drop.on_drag_start": "Se ha recogido el archivo adjunto {item}.", "upload_form.edit": "Editar", "upload_form.thumbnail": "Cambiar miniatura", "upload_form.video_description": "Describir para personas con problemas auditivos o visuales", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 5b8e8369f6a437..69df3c4140ebc5 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -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", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index acdd27ce2bea5d..63449e934210ee 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Abiadura mugatua", "alert.unexpected.message": "Ustekabeko errore bat gertatu da.", "alert.unexpected.title": "Ene!", + "alt_text_badge.title": "Testu alternatiboa", "announcement.announcement": "Iragarpena", "attachments_list.unprocessed": "(prozesatu gabe)", "audio.hide": "Ezkutatu audioa", @@ -221,7 +222,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 +432,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", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index fba8d902351362..d510c2a6a455c9 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -85,9 +85,11 @@ "alert.rate_limited.title": "محدودیت تعداد", "alert.unexpected.message": "خطایی غیرمنتظره رخ داد.", "alert.unexpected.title": "ای وای!", + "alt_text_badge.title": "متن جایگزین", "announcement.announcement": "اعلامیه", "attachments_list.unprocessed": "(پردازش نشده)", "audio.hide": "نهفتن صدا", + "block_modal.remote_users_caveat": "ما از کارساز {domain} خواهیم خواست که به تصمیم شما احترام بگذارد. با این حال، تضمینی برای رعایت آن وجود ندارد زیرا برخی کارسازها ممکن است بلوک‌ها را به‌طور متفاوتی مدیریت کنند. فرسته‌های عمومی ممکن است همچنان برای کاربران که وارد نشده قابل مشاهده باشند.", "block_modal.show_less": "نمایش کم‌تر", "block_modal.show_more": "نمایش بیش‌تر", "block_modal.they_cant_mention": "نمی‌توانند نامتان را برده یا پی‌تان بگیرند.", @@ -220,8 +222,10 @@ "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_will_lose_relationships": "شما تمام پیگیرکنندگان و افرادی که از این کارساز پیگیری می‌کنید را از دست خواهید داد.", "domain_block_modal.you_wont_see_posts": "فرسته‌ها یا آگاهی‌ها از کاربران روی این کارساز را نخواهید دید.", + "domain_pill.activitypub_lets_connect": "این به شما اجازه می‌دهد تا نه تنها در ماستودون، بلکه در برنامه‌های اجتماعی مختلف نیز با افراد ارتباط برقرار کرده و تعامل داشته باشید.", + "domain_pill.activitypub_like_language": "ActivityPub مانند زبانی است که ماستودون با دیگر شبکه‌های اجتماعی صحبت می‌کند.", "domain_pill.server": "کارساز", "domain_pill.their_handle": "شناسه‌اش:", "domain_pill.their_server": "خانهٔ رقمیش. جایی که همهٔ فرسته‌هایش می‌زیند.", @@ -422,8 +426,6 @@ "keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جست‌وجو", "keyboard_shortcuts.up": "بالا بردن در سیاهه", "lightbox.close": "بستن", - "lightbox.compress": "فشرده‌سازی جعبهٔ نمایش تصویر", - "lightbox.expand": "گسترش جعبهٔ نمایش تصویر", "lightbox.next": "بعدی", "lightbox.previous": "قبلی", "limited_account_hint.action": "به هر روی نمایه نشان داده شود", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 681f5d5bb20a9a..2e4cd661d5049c 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Pyyntömäärää rajoitettu", "alert.unexpected.message": "Tapahtui odottamaton virhe.", "alert.unexpected.title": "Hups!", + "alt_text_badge.title": "Vaihtoehtoinen teksti", "announcement.announcement": "Tiedote", "attachments_list.unprocessed": "(käsittelemätön)", "audio.hide": "Piilota ääni", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Menetät {followersCount, plural, one {{followersCountDisplay} seuraajasi} other {{followersCountDisplay} seuraajaasi}} ja {followingCount, plural, one {{followingCountDisplay} seurattusi} other {{followingCountDisplay} seurattuasi}}.", + "domain_block_modal.you_will_lose_relationships": "Menetät kaikki tämän palvelimen seuraajasi ja seurattusi.", "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 +434,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}", @@ -795,7 +797,7 @@ "status.history.edited": "{name} muokkasi {date}", "status.load_more": "Lataa lisää", "status.media.open": "Avaa napsauttamalla", - "status.media.show": "Napsauta näyttääksesi", + "status.media.show": "Näytä napsauttamalla", "status.media_hidden": "Media piilotettu", "status.mention": "Mainitse @{name}", "status.more": "Enemmän", @@ -850,6 +852,11 @@ "upload_error.poll": "Tiedostojen lisääminen äänestysten oheen ei ole sallittua.", "upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille", "upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille", + "upload_form.drag_and_drop.instructions": "Valitse medialiite painamalla välilyöntiä tai enteriä. Vetäessäsi käytä nuolinäppäimiä siirtääksesi medialiitettä vastaavaan suuntaan. Paina välilyöntiä tai enteriä uudelleen pudottaaksesi medialiitteen uuteen kohtaansa, tai peru siirto painamalla escape-näppäintä.", + "upload_form.drag_and_drop.on_drag_cancel": "Veto peruttiin. Medialiitettä {item} ei siirretty.", + "upload_form.drag_and_drop.on_drag_end": "Medialiite {item} pudotettiin.", + "upload_form.drag_and_drop.on_drag_over": "Medialiitettä {item} siirrettiin.", + "upload_form.drag_and_drop.on_drag_start": "Valittiin medialiite {item}.", "upload_form.edit": "Muokkaa", "upload_form.thumbnail": "Vaihda pienoiskuva", "upload_form.video_description": "Kuvaile sisältöä kuuroille, kuulorajoitteisille, sokeille tai näkörajoitteisille", diff --git a/app/javascript/mastodon/locales/fil.json b/app/javascript/mastodon/locales/fil.json index 31004560912a6e..40292c269126e9 100644 --- a/app/javascript/mastodon/locales/fil.json +++ b/app/javascript/mastodon/locales/fil.json @@ -3,9 +3,15 @@ "about.contact": "Kontak:", "about.disclaimer": "Ang Mastodon ay software na malaya at bukas-na-pinagmulan, at isang tatak-pangkalakal ng Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Hindi makuha ang dahilan", + "about.domain_blocks.preamble": "Sa kadalasan, hinahayaan ka ng Mastodon na makita ang mga content sa, at makipag-interact sa users ng, ibang servers sa fediverse. Narito ang exceptions na ginawa sa partikular na server na ito.", + "about.domain_blocks.silenced.explanation": "Sa kadalasan, hindi mo makikita ang profiles at content mula sa server na ito, maliban na lang kung sasadyain mo silang hanapin o piliing magawa ito sa pamamagitan ng mga sumusunod.", "about.domain_blocks.silenced.title": "Limitado", + "about.domain_blocks.suspended.explanation": "Walang data mula sa server na ito ang mapoproseso, maiimbak o maipagpapaplitan. Sa gayon. imposibleng magawa ang interaksiyon o komunikasyon sa ibang users sa server na ito.", "about.domain_blocks.suspended.title": "Suspendido", + "about.not_available": "Hindi available ang impormasyong ito.", + "about.powered_by": "Decentralisadong social media na pinapagana ng {mastodon}", "about.rules": "Mga alituntunin ng server", + "account.account_note_header": "Note na personal", "account.add_or_remove_from_list": "I-dagdag o tanggalin mula sa mga listahan", "account.badges.bot": "Pakusa", "account.badges.group": "Pangkat", @@ -134,7 +140,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:", @@ -217,7 +222,7 @@ "link_preview.author": "Ni/ng {name}", "lists.account.add": "Idagdag sa talaan", "lists.account.remove": "Tanggalin mula sa talaan", - "lists.delete": "Burahin ang talaan", + "lists.delete": "Burahin ang listahan", "lists.new.create": "Idagdag sa talaan", "lists.new.title_placeholder": "Bagong pangalan ng talaan", "lists.replies_policy.title": "Ipakita ang mga tugon sa:", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index 793a75bb05a5f5..c7e752d3783823 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Avmarkaður títtleiki", "alert.unexpected.message": "Ein óvæntaður feilur kom fyri.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Annar tekstur", "announcement.announcement": "Kunngerð", "attachments_list.unprocessed": "(óviðgjørt)", "audio.hide": "Fjal ljóð", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "Tú fer at missa allar fylgjarar og øll tey, tú fylgir á hesum ambætaranum.", "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 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "Ikki loyvt at leggja fílur upp í spurnarkanningum.", "upload_form.audio_description": "Lýs fyri teimum, sum eru deyv ella hava ringa hoyrn", "upload_form.description": "Lýs fyri teimum, sum eru blind ella eru sjónveik", + "upload_form.drag_and_drop.instructions": "Fyri at heinta eitt miðlaviðfesti, trýst á millumrúm ella returknapp. Meðan tú dregur, brúka pílarnar fyri at flyta miðaviðfesti í einhvønn rætning. Trýst á millumrúm ella returknapp aftur fyri at sleppa miðlaviðfestinum í nýggja staðnum ella trýst á esc-knappin fyri at angra.", + "upload_form.drag_and_drop.on_drag_cancel": "Draging varð steðgað. Miðlaviðfestið {item} varð slept.", + "upload_form.drag_and_drop.on_drag_end": "Miðlaviðfestið {item} var slept.", + "upload_form.drag_and_drop.on_drag_over": "Miðlaviðfestið {item} var flutt.", + "upload_form.drag_and_drop.on_drag_start": "Heintaði miðlaviðfestið {item}.", "upload_form.edit": "Rætta", "upload_form.thumbnail": "Broyt smámynd", "upload_form.video_description": "Lýs fyri teimum, sum eru deyv, hava ringa hoyrn, eru blind ella eru sjónveik", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 8e33c6844290cc..bdceb9bd30d036 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Débit limité", "alert.unexpected.message": "Une erreur inattendue s’est produite.", "alert.unexpected.title": "Oups!", + "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", @@ -164,7 +165,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)", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Vous allez perdre {followersCount, plural, one {{followersCountDisplay} abonné·e} other {{followersCountDisplay} abonné·e·s}} et {followingCount, plural, one {{followingCountDisplay} personne que vous suivez} other {{followingCountDisplay} personnes que vous suivez}}.", + "domain_block_modal.you_will_lose_relationships": "Vous allez perdre tous les abonné·e·s et les personnes que vous suivez sur ce serveur.", "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.", @@ -432,10 +434,10 @@ "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", + "lightbox.zoom_in": "Zoomer sur la taille réelle", + "lightbox.zoom_out": "Zoomer pour adapter", "limited_account_hint.action": "Afficher le profil quand même", "limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.", "link_preview.author": "Par {name}", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index e73ddf734f1b5e..2acad020935f04 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Nombre de requêtes limité", "alert.unexpected.message": "Une erreur inattendue s’est produite.", "alert.unexpected.title": "Oups !", + "alt_text_badge.title": "Texte Alt", "announcement.announcement": "Annonce", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", @@ -164,7 +165,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 l’avertissement de contenu", "compose_form.spoiler.unmarked": "Ajouter un avertissement de contenu", "compose_form.spoiler_placeholder": "Avertissement de contenu (optionnel)", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Vous allez perdre {followersCount, plural, one {{followersCountDisplay} abonné·e} other {{followersCountDisplay} abonné·e·s}} et {followingCount, plural, one {{followingCountDisplay} personne que vous suivez} other {{followingCountDisplay} personnes que vous suivez}}.", + "domain_block_modal.you_will_lose_relationships": "Vous allez perdre tous les abonné·e·s et les personnes que vous suivez sur ce serveur.", "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.", @@ -432,10 +434,10 @@ "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", + "lightbox.zoom_in": "Zoomer sur la taille réelle", + "lightbox.zoom_out": "Zoomer pour adapter", "limited_account_hint.action": "Afficher le profil quand même", "limited_account_hint.title": "Ce profil a été masqué par la modération de {domain}.", "link_preview.author": "Par {name}", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index 2443692133af18..1d71ef36c69d77 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -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 dy’t 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", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 11da6b64e94d31..84c76478d1b6c6 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Rátatheoranta", "alert.unexpected.message": "Tharla earráid gan choinne.", "alert.unexpected.title": "Hiúps!", + "alt_text_badge.title": "Téacs alt", "announcement.announcement": "Fógra", "attachments_list.unprocessed": "(neamhphróiseáilte)", "audio.hide": "Cuir fuaim i bhfolach", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Caillfidh tú {followersCount, plural, one {{followersCountDisplay} leantóir} two {{followersCountDisplay} leantóirí} few {{followersCountDisplay} leantóirí} many {{followersCountDisplay} leantóirí} other {{followersCountDisplay} leantóirí}} agus {followingCount, plural, one {{followingCountDisplay} duine atá á leanúint agat} two {{followingCountDisplay} daoine atá á leanúint agat} few {{followingCountDisplay} daoine atá á leanúint agat} many {{followingCountDisplay} daoine atá á leanúint agat} other {{followingCountDisplay} daoine atá á leanúint agat}}.", + "domain_block_modal.you_will_lose_relationships": "Caillfidh tú gach leantóir agus duine a leanann tú ó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 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "Ní cheadaítear uaslódáil comhad le pobalbhreith.", "upload_form.audio_description": "Déan cur síos ar dhaoine bodhra nó lagéisteachta", "upload_form.description": "Describe for the visually impaired", + "upload_form.drag_and_drop.instructions": "Chun ceangaltán meán a phiocadh suas, brúigh spás nó cuir isteach. Agus tú ag tarraingt, bain úsáid as na heochracha saigheada chun an ceangaltán meán a bhogadh i dtreo ar bith. Brúigh spás nó cuir isteach arís chun an ceangaltán meán a scaoileadh ina phost nua, nó brúigh éalú chun cealú.", + "upload_form.drag_and_drop.on_drag_cancel": "Cuireadh an tarraingt ar ceal. Scaoileadh ceangaltán meán {item}.", + "upload_form.drag_and_drop.on_drag_end": "Scaoileadh ceangaltán meán {item}.", + "upload_form.drag_and_drop.on_drag_over": "Bogadh ceangaltán meán {item}.", + "upload_form.drag_and_drop.on_drag_start": "Roghnaíodh ceangaltán meán {item}.", "upload_form.edit": "Cuir in eagar", "upload_form.thumbnail": "Athraigh mionsamhail", "upload_form.video_description": "Déan cur síos ar dhaoine atá bodhar, lagéisteachta, dall nó lagamhairc", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index 2b93662694aed6..ecbc11f3a2b7fa 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -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}", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index d35bcd8cf5b2ab..3bc9e1ee590dfd 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Límite de intentos", "alert.unexpected.message": "Aconteceu un fallo non agardado.", "alert.unexpected.title": "Vaites!", + "alt_text_badge.title": "Texto Alt", "announcement.announcement": "Anuncio", "attachments_list.unprocessed": "(sen procesar)", "audio.hide": "Agochar audio", @@ -221,7 +222,8 @@ "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_will_lose_relationships": "Vas perder todas as seguidoras e seguimentos a persoas deste servidor.", "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 +370,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 +434,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 +465,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 +529,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 {count, plural, one {# máis} other {# máis}} 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", @@ -850,6 +852,11 @@ "upload_error.poll": "Non se poden subir ficheiros nas enquisas.", "upload_form.audio_description": "Describir para persoas con problemas auditivos", "upload_form.description": "Describir para persoas cegas ou con problemas visuais", + "upload_form.drag_and_drop.instructions": "Preme en Espazo ou Enter para escoller un anexo multimedia. Ao arrastrar usa as teclas de frecha para mover o anexo en todas direccións.Preme Espazo ou Enter outra vez para soltalo na súa nova posición, ou preme Escape para desbotar.", + "upload_form.drag_and_drop.on_drag_cancel": "Cancelouse o movemento. O anexo {item} soltouse.", + "upload_form.drag_and_drop.on_drag_end": "Soltouse o anexo multimedia {item}.", + "upload_form.drag_and_drop.on_drag_over": "Moveuse o anexo multimedia {item}.", + "upload_form.drag_and_drop.on_drag_start": "Escolleuse o anexo multimedia {item}.", "upload_form.edit": "Editar", "upload_form.thumbnail": "Cambiar a miniatura", "upload_form.video_description": "Describe para persoas con problemas visuais ou auditivos", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 5e6ab56c238909..4ce0d41620d5dc 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -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}", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index 58b04a20cd363f..4a513c1c073e3e 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -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": "फिर भी प्रोफाइल दिखाओ", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index d4ced224634fe6..34a9949afd1a1c 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -221,7 +221,8 @@ "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_will_lose_num_followers": "El fogsz veszíteni {followersCount, plural, one {{followersCountDisplay} követőt} other {{followersCountDisplay} követőt}} és {followingCount, plural, one {{followingCountDisplay} követett személyt} other {{followingCountDisplay} követett személyt}}.", + "domain_block_modal.you_will_lose_relationships": "Minden követőt és követett személyt el fogsz veszíteni erről a kiszolgálóról.", "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 +433,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", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index a81abb82f014a1..9e5ae790453057 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -271,8 +271,6 @@ "keyboard_shortcuts.unfocus": "տեքստի/որոնման տիրոյթից ապասեւեռուելու համար", "keyboard_shortcuts.up": "ցանկով վերեւ շարժուելու համար", "lightbox.close": "Փակել", - "lightbox.compress": "Փակել պատկերի դիտման պատուհանը", - "lightbox.expand": "Բացել պատկերի դիտման պատուհանը", "lightbox.next": "Յաջորդ", "lightbox.previous": "Նախորդ", "lists.account.add": "Աւելացնել ցանկին", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 9e7b583375bd78..35482297f03b07 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -221,7 +221,6 @@ "domain_block_modal.they_cant_follow": "Necuno de iste servitor pote sequer te.", "domain_block_modal.they_wont_know": "Ille non sapera que ille ha essite blocate.", "domain_block_modal.title": "Blocar dominio?", - "domain_block_modal.you_will_lose_followers": "Tote tu sequitores de iste servitor essera removite.", "domain_block_modal.you_wont_see_posts": "Tu non videra messages e notificationes de usatores sur iste servitor.", "domain_pill.activitypub_lets_connect": "Illo te permitte connecter e interager con personas non solmente sur Mastodon, ma tamben sur altere applicationes social.", "domain_pill.activitypub_like_language": "ActivityPub es como le linguage commun que Mastodon parla con altere retes social.", @@ -423,8 +422,6 @@ "keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca", "keyboard_shortcuts.up": "Displaciar in alto in le lista", "lightbox.close": "Clauder", - "lightbox.compress": "Comprimer le quadro de visualisation de imagine", - "lightbox.expand": "Expander le quadro de visualisation de imagine", "lightbox.next": "Sequente", "lightbox.previous": "Precedente", "limited_account_hint.action": "Monstrar profilo in omne caso", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 687c32c1b155cf..f5c71d4a36e3ca 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -219,7 +219,6 @@ "domain_block_modal.they_cant_follow": "Tidak ada seorangpun dari server ini yang dapat mengikuti anda.", "domain_block_modal.they_wont_know": "Mereka tidak akan tahu bahwa mereka diblokir.", "domain_block_modal.title": "Blokir domain?", - "domain_block_modal.you_will_lose_followers": "Semua pengikut anda dari server ini akan dihapus.", "domain_block_modal.you_wont_see_posts": "Anda tidak akan melihat postingan atau notifikasi dari pengguna di server ini.", "domain_pill.activitypub_lets_connect": "Ini memungkinkan anda terhubung dan berinteraksi dengan orang-orang tidak hanya di Mastodon, tetapi juga di berbagai aplikasi sosial.", "domain_pill.activitypub_like_language": "ActivityPub seperti bahasa yang digunakan Mastodon dengan jejaring sosial lainnya.", @@ -381,8 +380,6 @@ "keyboard_shortcuts.unfocus": "untuk tidak fokus pada area teks/pencarian", "keyboard_shortcuts.up": "untuk memindah ke atas pada daftar", "lightbox.close": "Tutup", - "lightbox.compress": "Kompres kotak tampilan gambar", - "lightbox.expand": "Besarkan kotak tampilan gambar", "lightbox.next": "Selanjutnya", "lightbox.previous": "Sebelumnya", "limited_account_hint.action": "Tetap tampilkan profil", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index 322680101922a1..d91c49e83f9bcb 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -206,7 +206,6 @@ "domain_block_modal.they_cant_follow": "Nequi de ti-ci servitor posse sequer te.", "domain_block_modal.they_wont_know": "Ne va esser conscient pri li bloccada.", "domain_block_modal.title": "Bloccar dominia?", - "domain_block_modal.you_will_lose_followers": "Omni tui sequitores de ti-ci servitor va esser efaciat.", "domain_block_modal.you_wont_see_posts": "Tu ne va vider postas ni notificationes de usatores sur ti-ci servitor.", "domain_pill.activitypub_lets_connect": "It possibilisa tui conexiones e interactiones con persones ne solmen sur Mastodon, ma anc tra diferent social aplis.", "domain_pill.activitypub_like_language": "ActivityPub es li lingue usat de Mastodon por parlar con altri social retages.", @@ -396,8 +395,6 @@ "keyboard_shortcuts.unfocus": "Desinfocar text-area de composition/serchar", "keyboard_shortcuts.up": "Mover ad-supra in li liste", "lightbox.close": "Cluder", - "lightbox.compress": "Compresser vise-buxe de image", - "lightbox.expand": "Expander vise-buxe de image", "lightbox.next": "Sequent", "lightbox.previous": "Precedent", "limited_account_hint.action": "Monstrar profil totvez", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index bb0a86ac2bbec9..bfc248a845e79e 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -1,6 +1,7 @@ { "about.blocks": "Jerata servili", "about.contact": "Kontaktajo:", + "about.disclaimer": "Mastodon esas libera, publikfonta e komercmarko di Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Expliko nedisponebla", "about.domain_blocks.preamble": "Mastodon generale permisas on vidar kontenajo e interagar kun uzanti de irga altra servilo en fediverso. Existas eceptioni quo facesis che ca partikulara servilo.", "about.domain_blocks.silenced.explanation": "On generale ne vidar profili e kontenajo de ca servilo, se on ne reale trovar o voluntale juntar per sequar.", @@ -10,6 +11,7 @@ "about.not_available": "Ca informo ne igesis che ca servilo.", "about.powered_by": "Necentraligita sociala ret quo povigesas da {mastodon}", "about.rules": "Servilreguli", + "account.account_note_header": "Personala noto", "account.add_or_remove_from_list": "Insertez o removez de listi", "account.badges.bot": "Boto", "account.badges.group": "Grupo", @@ -29,9 +31,12 @@ "account.featured_tags.last_status_never": "Nula posti", "account.featured_tags.title": "Estalita hashtagi di {name}", "account.follow": "Sequar", + "account.follow_back": "Anke sequez", "account.followers": "Sequanti", "account.followers.empty": "Nulu sequas ca uzanto til nun.", + "account.followers_counter": "{count, plural,one {{counter} sequanto} other {{counter} sequanti}}", "account.following": "Sequata", + "account.following_counter": "{count, plural,one {{counter} sequato} other {{counter} sequati}}", "account.follows.empty": "Ca uzanto ne sequa irgu til nun.", "account.go_to_profile": "Irez al profilo", "account.hide_reblogs": "Celez repeti de @{name}", @@ -47,6 +52,7 @@ "account.mute_notifications_short": "Silencigez avizi", "account.mute_short": "Silencigez", "account.muted": "Silencigata", + "account.mutual": "Mutuala", "account.no_bio": "Deskriptajo ne provizesis.", "account.open_original_page": "Apertez originala pagino", "account.posts": "Mesaji", @@ -56,6 +62,7 @@ "account.requested_follow": "{name} demandis sequar tu", "account.share": "Partigez profilo di @{name}", "account.show_reblogs": "Montrez repeti de @{name}", + "account.statuses_counter": "{count, plural,one {{counter} mesajo} other {{counter} mesaji}}", "account.unblock": "Desblokusar @{name}", "account.unblock_domain": "Desblokusar {domain}", "account.unblock_short": "Desblokusar", @@ -78,10 +85,21 @@ "alert.rate_limited.title": "Demandi limitizita", "alert.unexpected.message": "Neexpektita eroro eventis.", "alert.unexpected.title": "Problemo!", + "alt_text_badge.title": "Alternativa texto", "announcement.announcement": "Anunco", "attachments_list.unprocessed": "(neprocedita)", "audio.hide": "Celez audio", + "block_modal.remote_users_caveat": "Ni questionos {domain} di la servilo por respektar vua decido. Publika posti forsan ankore estas videbla a neenirinta uzanti.", + "block_modal.show_less": "Montrar mine", + "block_modal.show_more": "Montrar plue", + "block_modal.they_cant_mention": "Oli ne povas mencionar o sequar vu.", + "block_modal.they_cant_see_posts": "Oli ne povas vidar vua mesaji e vu ne vidos vidar olia.", + "block_modal.they_will_know": "Oli povas vidar ke oli esas blokusita.", + "block_modal.title": "Blokusar uzanto?", + "block_modal.you_wont_see_mentions": "Vu ne vidos mesaji qua mencionas oli.", "boost_modal.combo": "Vu povas pulsar {combo} por omisar co venontafoye", + "boost_modal.reblog": "Ka repetar posto?", + "boost_modal.undo_reblog": "Ka desrepetar posto?", "bundle_column_error.copy_stacktrace": "Kopierorraporto", "bundle_column_error.error.body": "La demandita pagino ne povas strukturigesar. Forsan ol esas eroro en kodexo hike o vidilkoncilieblesproblemo.", "bundle_column_error.error.title": "Ach!", @@ -138,30 +156,47 @@ "compose_form.lock_disclaimer.lock": "klefagesas", "compose_form.placeholder": "Quo esas en tua spirito?", "compose_form.poll.duration": "Votpostoduro", + "compose_form.poll.multiple": "Multopla selekteso", + "compose_form.poll.option_placeholder": "Selektato {number}", + "compose_form.poll.single": "Selektez un", "compose_form.poll.switch_to_multiple": "Chanjez votposto por permisar multiselektaji", "compose_form.poll.switch_to_single": "Chanjez votposto por permisar una selektajo", + "compose_form.poll.type": "Stilo", + "compose_form.publish": "Posto", "compose_form.publish_form": "Publish", + "compose_form.reply": "Respondez", + "compose_form.save_changes": "Aktualigez", "compose_form.spoiler.marked": "Text is hidden behind warning", "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler_placeholder": "Kontenajaverto (selektebla)", "confirmation_modal.cancel": "Anulez", "confirmations.block.confirm": "Restriktez", "confirmations.delete.confirm": "Efacez", "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.delete.title": "Ka efacar posto?", "confirmations.delete_list.confirm": "Efacez", "confirmations.delete_list.message": "Ka vu certe volas netempale efacar ca listo?", + "confirmations.delete_list.title": "Ka efacar listo?", "confirmations.discard_edit_media.confirm": "Efacez", "confirmations.discard_edit_media.message": "Vu havas nesparita chanji di mediodeskript o prevido, vu volas jus efacar?", "confirmations.edit.confirm": "Modifikez", "confirmations.edit.message": "Modifikar nun remplasos la mesajo quon vu nune skribas. Ka vu certe volas procedar?", + "confirmations.edit.title": "Ka remplasar posto?", "confirmations.logout.confirm": "Ekirez", "confirmations.logout.message": "Ka tu certe volas ekirar?", + "confirmations.logout.title": "Ka ekirar?", "confirmations.mute.confirm": "Silencigez", "confirmations.redraft.confirm": "Efacez e riskisez", "confirmations.redraft.message": "Ka vu certe volas efacar ca posto e riskisigar ol? Favoriziti e repeti esos perdita, e respondi al posto originala esos orfanigita.", + "confirmations.redraft.title": "Ka efacar & riskisar posto?", "confirmations.reply.confirm": "Respondez", "confirmations.reply.message": "Respondar nun remplos mesajo quon vu nun igas. Ka vu certe volas durar?", + "confirmations.reply.title": "Ka remplasar posto?", "confirmations.unfollow.confirm": "Desequez", "confirmations.unfollow.message": "Ka vu certe volas desequar {name}?", + "confirmations.unfollow.title": "Ka dessequar uzanto?", + "content_warning.hide": "Celez posto", + "content_warning.show": "Montrez nur", "conversation.delete": "Efacez konverso", "conversation.mark_as_read": "Markizez quale lektita", "conversation.open": "Videz konverso", @@ -181,6 +216,28 @@ "dismissable_banner.explore_statuses": "Yen posti del tota reto sociala qui esas populara hodie. Posti plu nova kun plu repeti e favoriziti esas rangizita plu alte.", "dismissable_banner.explore_tags": "Ca hashtagi bezonas plu famoza inter personi che ca e altra servili di la necentraligita situo nun.", "dismissable_banner.public_timeline": "Yen la posti maxim recenta da personi che la reto sociala quin personi che {domain} sequas.", + "domain_block_modal.block": "Blokusez servilo", + "domain_block_modal.block_account_instead": "Blokusez @{name} vice", + "domain_block_modal.they_can_interact_with_old_posts": "Personi de ca servilo povas interagar kun vua desnova posti.", + "domain_block_modal.they_cant_follow": "Nulu de ca servilo povas sequar vu.", + "domain_block_modal.they_wont_know": "Lu ne savos ke lu blokusesis.", + "domain_block_modal.title": "Ka blokusar domeno?", + "domain_block_modal.you_will_lose_num_followers": "Vu desganos {followersCount, plural, one {{followersCountDisplay} sequanto} other {{followersCountDisplay} sequanti}} e {followingCount, plural, one {{followingCountDisplay} persono quan vu sequas} other {{followingCountDisplay} personi quan vu sequas}}.", + "domain_block_modal.you_will_lose_relationships": "Vu desganos omna sequanti e sequati de ca servilo.", + "domain_block_modal.you_wont_see_posts": "Vu ne vidos postoi o savigi de uzanti en ca servilo.", + "domain_pill.activitypub_lets_connect": "Ol povigas vu kuneskas e interagar kun personi ne nur sur Mastodon, o anke kun dessama socia softwari.", + "domain_pill.activitypub_like_language": "ActivityPub esas kam linguo quan Mastodon parolas kun altra socia reti.", + "domain_pill.server": "Servilo", + "domain_pill.their_handle": "Lua nomo:", + "domain_pill.their_server": "Lua komputala hemo, e havas omna lua posti.", + "domain_pill.their_username": "Lua unika identesilo sur lua servilo. Posible trovar uzanti kun sama uzantonomo sur dessama servili.", + "domain_pill.username": "Uzantonomo", + "domain_pill.whats_in_a_handle": "Quo esas nomo?", + "domain_pill.who_they_are": "Pro ke nomo esas deskripto di ulu, vu povas interagar kun personi tra socia interreto kun .", + "domain_pill.who_you_are": "Pro ke vua nomo esas deskripto pri vu e vua situo, personi povas interagar kun vu tra socia interreto kun .", + "domain_pill.your_handle": "Vua nomo:", + "domain_pill.your_server": "Vua komputerala hemo qua havas omna vua posti. On povas transferar a altra servili ulatempe e anke adportar vua sequanti.", + "domain_pill.your_username": "Vua unika identesilo sur lua servilo. Posible trovar uzanti kun sama uzantonomo sur dessama servili.", "embed.instructions": "Embed this status on your website by copying the code below.", "embed.preview": "Co esas quon ol semblos tale:", "emoji_button.activity": "Ago", @@ -217,6 +274,7 @@ "empty_column.list": "There is nothing in this list yet.", "empty_column.lists": "Vu ne havas irga listi til nun. Kande vu kreas talo, ol montresos hike.", "empty_column.mutes": "Vu ne silencigis irga uzanti til nun.", + "empty_column.notification_requests": "Finis. Kande vu recevas nova savigi, oli aparos hike segun vua preferaji.", "empty_column.notifications": "Tu havas ankore nula savigo. Komunikez kun altri por debutar la konverso.", "empty_column.public": "Esas nulo hike! Skribez ulo publike, o manuale sequez uzeri de altra instaluri por plenigar ol.", "error.unexpected_crash.explanation": "Pro eroro en nia kodexo o vidilkonciliebloproblemo, ca pagino ne povas korekte montresar.", @@ -247,12 +305,30 @@ "filter_modal.select_filter.subtitle": "Usez disponebla grupo o kreez novajo", "filter_modal.select_filter.title": "Filtragez ca posto", "filter_modal.title.status": "Filtragez posto", + "filter_warning.matches_filter": "Sama kam filtrilo \"{title}\"", + "filtered_notifications_banner.pending_requests": "De {count, plural,=0 {nulu} one {1 persono} other {# personi}} quan vu forsan konocas", + "filtered_notifications_banner.title": "Filtrilita savigi", "firehose.all": "Omno", "firehose.local": "Ca servilo", "firehose.remote": "Altra servili", "follow_request.authorize": "Yurizar", "follow_request.reject": "Refuzar", "follow_requests.unlocked_explanation": "Quankam vua konto ne klefklozesis, la {domain} laborero pensas ke vu forsan volas kontralar sequodemandi de ca konti manuale.", + "follow_suggestions.curated_suggestion": "Selektato de jeranto", + "follow_suggestions.dismiss": "Ne montrez pluse", + "follow_suggestions.featured_longer": "Selektesis da la grupo di {domain}", + "follow_suggestions.friends_of_friends_longer": "Populara inter personi quan vu sequas", + "follow_suggestions.hints.featured": "Ca profilo selektesis da la grupo di {domain}.", + "follow_suggestions.hints.friends_of_friends": "Ca profilo esas populara inter personi quan vu sequas.", + "follow_suggestions.hints.most_followed": "Vua profilo esas un de maxim sequita sur {domain}.", + "follow_suggestions.hints.most_interactions": "Ca profilo recente populareskis sur {domain}.", + "follow_suggestions.hints.similar_to_recently_followed": "Ca profilo esas simila a la profili quan vu recente sequis.", + "follow_suggestions.personalized_suggestion": "Personalita sugestato", + "follow_suggestions.popular_suggestion": "Populara sugestato", + "follow_suggestions.popular_suggestion_longer": "Populara sur {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Simila a profili quan vu recente sequis", + "follow_suggestions.view_all": "Videz omno", + "follow_suggestions.who_to_follow": "Sequindo", "followed_tags": "Hashtagi sequita", "footer.about": "Pri co", "footer.directory": "Profilcheflisto", @@ -279,6 +355,14 @@ "hashtag.follow": "Sequez hashtago", "hashtag.unfollow": "Desequez hashtago", "hashtags.and_other": "…e {count, plural, one {# plusa}other {# plusa}}", + "hints.profiles.followers_may_be_missing": "Sequanti di ca profilo forsan ne esas hike.", + "hints.profiles.follows_may_be_missing": "Sequati di ca profilo forsan ne esas hike.", + "hints.profiles.posts_may_be_missing": "Kelka posti sur ca profilo forsan ne esas hike.", + "hints.profiles.see_more_followers": "Vidar plu multa sequanti sur {domain}", + "hints.profiles.see_more_follows": "Vidar plu multa sequati sur {domain}", + "hints.profiles.see_more_posts": "Vidar plu multa posti sur {domain}", + "hints.threads.replies_may_be_missing": "Respondi de altra servili forsan ne esas hike.", + "hints.threads.see_more": "Vidar plu multa demandi sur {domain}", "home.column_settings.show_reblogs": "Montrar repeti", "home.column_settings.show_replies": "Montrar respondi", "home.hide_announcements": "Celez anunci", @@ -286,6 +370,17 @@ "home.pending_critical_update.link": "Vidar aktualigaji", "home.pending_critical_update.title": "Sekuresala aktualigajo gravega disponebla!", "home.show_announcements": "Montrez anunci", + "ignore_notifications_modal.disclaimer": "Mastodon ne povas savigar uzanti ke vu ignoris olia savigi. Ignorar savigi ne cesos ipse mesaji sendesar.", + "ignore_notifications_modal.filter_instead": "Filtrar vice", + "ignore_notifications_modal.filter_to_act_users": "Vu povos aceptar, refuzar o raportar uzanti", + "ignore_notifications_modal.filter_to_avoid_confusion": "Filtro helpas evitar posibla konfuzo", + "ignore_notifications_modal.filter_to_review_separately": "Vu povas kontrolar filtrita savigi separe", + "ignore_notifications_modal.ignore": "Ignorez savigi", + "ignore_notifications_modal.limited_accounts_title": "Ka ignorar savigi de jerita konti?", + "ignore_notifications_modal.new_accounts_title": "Ka ignorar savigi de nova konti?", + "ignore_notifications_modal.not_followers_title": "Ka ignorar savigi de personi qua ne sequas vu?", + "ignore_notifications_modal.not_following_title": "Ka ignorar savigi de personi quan vu ne sequas?", + "ignore_notifications_modal.private_mentions_title": "Ka ignorar savigi de nekonocita privata mencionii?", "interaction_modal.description.favourite": "Kun konto che Mastodon, vu povas favorizar ca posto por savigar la autoro ke vu prizas ol e sparar ol por pose.", "interaction_modal.description.follow": "Per konto che Mastodon, vu povas sequar {name} por ganar ola posti en vua hemniuzeto.", "interaction_modal.description.reblog": "Per konto che Mastodon, vu povas repetar ca posti por dissemar lo a vua propra sequati.", @@ -339,13 +434,15 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Klozar", - "lightbox.compress": "Kompresez imajvidbuxo", - "lightbox.expand": "Expansez imajvidbuxo", "lightbox.next": "Nexta", "lightbox.previous": "Antea", + "lightbox.zoom_in": "Grandigez a reala grandeso", + "lightbox.zoom_out": "Grandigez por fitigar", "limited_account_hint.action": "Jus montrez profilo", "limited_account_hint.title": "Ca profilo celesas dal jereri di {domain}.", "link_preview.author": "Da {name}", + "link_preview.more_from_author": "Plua de {name}", + "link_preview.shares": "{count, plural,one {{counter} posto} other {{counter} posti}}", "lists.account.add": "Insertez a listo", "lists.account.remove": "Efacez de listo", "lists.delete": "Efacez listo", @@ -362,8 +459,19 @@ "lists.subheading": "Vua listi", "load_pending": "{count, plural, one {# nova kozo} other {# nova kozi}}", "loading_indicator.label": "Kargante…", + "media_gallery.hide": "Celez", "moved_to_account_banner.text": "Vua konto {disabledAccount} es nune desaktiva pro ke vu movis a {movedToAccount}.", + "mute_modal.hide_from_notifications": "Celez de savigi", + "mute_modal.hide_options": "Celez preferaji", + "mute_modal.indefinite": "Til me dessilencigas lu", + "mute_modal.show_options": "Montrez preferaji", + "mute_modal.they_can_mention_and_follow": "Lu povas mencionar e sequar vu, ma vu ne vidos lu.", + "mute_modal.they_wont_know": "Lu ne savos ke lu silencigesis.", + "mute_modal.title": "Ka silencigar uzanto?", + "mute_modal.you_wont_see_mentions": "Vu ne vidos posti qua mencionas lu.", + "mute_modal.you_wont_see_posts": "Lu ankore povas vidar vua posti, ma vu ne vidos lua.", "navigation_bar.about": "Pri co", + "navigation_bar.administration": "Administro", "navigation_bar.advanced_interface": "Apertez per retintervizajo", "navigation_bar.blocks": "Blokusita uzeri", "navigation_bar.bookmarks": "Libromarki", @@ -380,6 +488,7 @@ "navigation_bar.follows_and_followers": "Sequati e sequanti", "navigation_bar.lists": "Listi", "navigation_bar.logout": "Ekirar", + "navigation_bar.moderation": "Jero", "navigation_bar.mutes": "Celita uzeri", "navigation_bar.opened_in_classic_interface": "Posti, konti e altra pagini specifika apertesas en la retovidilo klasika.", "navigation_bar.personal": "Personala", @@ -390,20 +499,71 @@ "navigation_bar.security": "Sekureso", "not_signed_in_indicator.not_signed_in": "Vu mustas enirar por acesar ca moyeno.", "notification.admin.report": "{name} raportizis {target}", + "notification.admin.report_account": "{name} raportis {count, plural,one {1 posto} other {# posti}} de {target} pro {category}", + "notification.admin.report_account_other": "{name} raportis {count, plural,one {1 posto} other {# posti}} de {target}", + "notification.admin.report_statuses": "{name} raportis {target} pro {category}", + "notification.admin.report_statuses_other": "{name} raportis {target}", "notification.admin.sign_up": "{name} registresis", + "notification.admin.sign_up.name_and_others": "{name} e {count, plural,one {# altru} other {#altri}} enrejistris", "notification.favourite": "{name} favorizis tua mesajo", + "notification.favourite.name_and_others_with_link": "{name} e {count, plural,one {# altru} other {# altri}} favorizis vua posto", "notification.follow": "{name} sequeskis tu", + "notification.follow.name_and_others": "{name} e {count, plural,one {# altru} other {#altri}} sequis vu", "notification.follow_request": "{name} demandas sequar vu", + "notification.follow_request.name_and_others": "{name} e {count, plural,one {# altru} other {# altri}} volas sequar vu", + "notification.label.mention": "Mencionez", + "notification.label.private_mention": "Privata menciono", + "notification.label.private_reply": "Privata respondo", + "notification.label.reply": "Respondez", + "notification.mention": "Mencionez", + "notification.moderation-warning.learn_more": "Lernez pluse", + "notification.moderation_warning": "Vu recevis jeraverto", + "notification.moderation_warning.action_delete_statuses": "Kelka vua posti efacesis.", + "notification.moderation_warning.action_disable": "Vua konto estas desaktivigita.", + "notification.moderation_warning.action_mark_statuses_as_sensitive": "Kelka vua posti markizesis quale sentoza.", + "notification.moderation_warning.action_none": "Vua konto recevis jeraverto.", + "notification.moderation_warning.action_sensitive": "Vua posti markizesos quale sentoza pos nun.", + "notification.moderation_warning.action_silence": "Vua konto limitizesis.", + "notification.moderation_warning.action_suspend": "Vua konto restriktesis.", "notification.own_poll": "Vua votposto finigis", + "notification.poll": "Votposto quan vu partoprenis finis", "notification.reblog": "{name} repetis tua mesajo", + "notification.reblog.name_and_others_with_link": "{name} e {count, plural,one {# altru} other {#altri}} repetis vua posto", + "notification.relationships_severance_event": "Desganis konekteso kun {name}", + "notification.relationships_severance_event.account_suspension": "Administranto de {from} restriktis {target}, do vu ne povas plue recevar novaji de lu o interagar kun lu.", + "notification.relationships_severance_event.domain_block": "Administranto de {from} blokusis {target}, e anke {followersCount} de vua sequanti e {followingCount, plural, one {# konto} other {# konti}} quan vu sequas.", + "notification.relationships_severance_event.learn_more": "Lernez pluse", + "notification.relationships_severance_event.user_domain_block": "Vu blokusis {target}, do efacis {followersCount} de vua sequanti e {followingCount, plural, one {# konto} other {#konti}} quan vu sequis.", "notification.status": "{name} nove postigis", "notification.update": "{name} modifikis posto", + "notification_requests.accept": "Aceptez", + "notification_requests.accept_multiple": "{count, plural, one {Aceptar # demando…} other {Aceptar # demandi…}}", + "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceptar demando} other {Aceptar demandi}}", + "notification_requests.confirm_accept_multiple.message": "Vu aceptos {count, plural, one {1 savigdemando} other {# savigdemandi}}. Ka vu certe volas durar?", + "notification_requests.confirm_accept_multiple.title": "Ka aceptar savigdemandi?", + "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Ignorez demando} other {Ignorez demandi}}", + "notification_requests.confirm_dismiss_multiple.message": "Vu ignoros {count, plural, one {1 savigdemando} other {# savigdemandi}}. Vu ne povas facile ganar {count, plural, one {ol} other {oli}} pluse. Ka vu esas certe ke vu volas durar?", + "notification_requests.confirm_dismiss_multiple.title": "Ka ignorar savigdemandi?", + "notification_requests.dismiss": "Ignorez", + "notification_requests.dismiss_multiple": "{count, plural,one {Ignorez # demando…} other {Ignorez # demandi…}}", + "notification_requests.edit_selection": "Modifikez", + "notification_requests.exit_selection": "Finas", + "notification_requests.explainer_for_limited_account": "Savigi de ca konto filtresis pro ke la konto limitizesis da jeranto.", + "notification_requests.explainer_for_limited_remote_account": "Savigi de ca konto filtresis pro ke la konto o olua servilo limitizesis da jeranto.", + "notification_requests.maximize": "Parmontrez", + "notification_requests.minimize_banner": "Celez banero di filtrita savigi", + "notification_requests.notifications_from": "Savigi de {name}", + "notification_requests.title": "Filtrita savigi", + "notification_requests.view": "Videz savigi", "notifications.clear": "Efacar savigi", "notifications.clear_confirmation": "Ka tu esas certa, ke tu volas efacar omna tua savigi?", + "notifications.clear_title": "Ka efacar savigi?", "notifications.column_settings.admin.report": "Nova raporti:", "notifications.column_settings.admin.sign_up": "Nova registranti:", "notifications.column_settings.alert": "Desktopavizi", "notifications.column_settings.favourite": "Favoriziti:", + "notifications.column_settings.filter_bar.advanced": "Montrez omna kategorii", + "notifications.column_settings.filter_bar.category": "Rapidfiltrilbaro", "notifications.column_settings.follow": "Nova sequanti:", "notifications.column_settings.follow_request": "Nova sequodemandi:", "notifications.column_settings.mention": "Mencioni:", @@ -429,6 +589,23 @@ "notifications.permission_denied": "Desktopavizi esas nedisplonebla pro antea refuzita vidilpermisdemando", "notifications.permission_denied_alert": "Desktopavizi ne povas aktivigesar pro ke vidilpermiso refuzesis", "notifications.permission_required": "Desktopavizi esas nedisplonebla pro ke bezonata permiso ne donesis.", + "notifications.policy.accept": "Aceptez", + "notifications.policy.accept_hint": "Montrez en savigi", + "notifications.policy.drop": "Ignorez", + "notifications.policy.drop_hint": "Nihiligez lu", + "notifications.policy.filter": "Filtrez", + "notifications.policy.filter_hint": "Sendez a enbuxo di filtrita savigi", + "notifications.policy.filter_limited_accounts_hint": "Limitizesis da serviljeranti", + "notifications.policy.filter_limited_accounts_title": "Jerita konti", + "notifications.policy.filter_new_accounts.hint": "Kreesis depos {days, plural, one {1 dio} other {# dii}}", + "notifications.policy.filter_new_accounts_title": "Nova konti", + "notifications.policy.filter_not_followers_hint": "Inkluzanta personi qua sequas vu min kam {days, plural, one {1 dio} other {# dii}}", + "notifications.policy.filter_not_followers_title": "Nesequanti", + "notifications.policy.filter_not_following_hint": "Til vu manuale aprobas lu", + "notifications.policy.filter_not_following_title": "Nesequati", + "notifications.policy.filter_private_mentions_hint": "Filtrita se ol ne esas respondo a vua sua menciono o se vu sequas la sendanto", + "notifications.policy.filter_private_mentions_title": "Nekonocita privata mencioni", + "notifications.policy.title": "Regular savigi de…", "notifications_permission_banner.enable": "Aktivigez desktopavizi", "notifications_permission_banner.how_to_control": "Por ganar avizi kande Mastodon ne esas apertita, aktivigez dekstopavizi. Vu povas precize regularar quale interakti facas deskstopavizi tra la supera {icon} butono pos oli aktivigesis.", "notifications_permission_banner.title": "Irga kozo ne pasas vu", @@ -466,6 +643,10 @@ "onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.title": "Share your profile", + "onboarding.tips.2fa": "Ka vu savas? Vu povas sekurigar vua konto per pozar 2-faktora verifiko en preferaji de vua konto. Telefonilnombro ne bezonesis!", + "onboarding.tips.accounts_from_other_servers": "Ka vu savas? Vu povas interagar kun profili sur altra servili senrupte!", + "onboarding.tips.migration": "Ka vu savas? Se vu sentas ke {domain} ne esas apta por vu en la futuro, vu povas transferar a altra servilo di Mastodon sen malganar vua sequanti!", + "onboarding.tips.verification": "Ka vu savas? Vu povas verifikar vua konto per pozi ligilo a vua profilo di Mastodon sur vua sua retsituo e adjuntar la retsituo a vua profilo. Senpage!", "password_confirmation.exceeds_maxlength": "La konfirmo dil pasvorto superesas la limito pri longeso di pasvorti", "password_confirmation.mismatching": "La konfirmo dil pasvorto ne egalesas", "picture_in_picture.restore": "Retropozez", @@ -480,7 +661,15 @@ "poll_button.add_poll": "Insertez votposto", "poll_button.remove_poll": "Efacez votposto", "privacy.change": "Aranjar privateso di mesaji", + "privacy.direct.long": "Omnu quan mencionesis en la posto", + "privacy.direct.short": "Specifika personi", + "privacy.private.long": "Nur vua sequanti", + "privacy.private.short": "Sequanti", + "privacy.public.long": "Ulu de e ne de Mastodon", "privacy.public.short": "Publike", + "privacy.unlisted.additional": "Co kondutas exakte kam publika, escepte la posto ne aparos en viva novajari o gretiketi, exploro, o sercho di Mastodon, mem se vu esas volunta totkonte.", + "privacy.unlisted.long": "Min multa algoritmoridikuli", + "privacy.unlisted.short": "Deslauta publiko", "privacy_policy.last_updated": "Antea novajo ye {date}", "privacy_policy.title": "Privatesguidilo", "recommended": "Rekomendata", @@ -498,7 +687,9 @@ "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", "relative_time.today": "hodie", + "reply_indicator.attachments": "{count, plural, one {# atachajo} other {# atachaji}}", "reply_indicator.cancel": "Nihiligar", + "reply_indicator.poll": "Votposto", "report.block": "Restriktez", "report.block_explanation": "Vu ne vidos olia posti. Oli ne povas vidar vua posti o sequar vu. Oli savos ke oli restriktesis.", "report.categories.legal": "Legala", @@ -541,9 +732,13 @@ "report.unfollow_explanation": "Vu sequas ca konto. Por ne vidar olia posti en vua hemniuzeto pluse, desequez oli.", "report_notification.attached_statuses": "{count, plural,one {{count} posti} other {{count} posti}} adjuntesas", "report_notification.categories.legal": "Legala", + "report_notification.categories.legal_sentence": "deslegala kontenajo", "report_notification.categories.other": "Altra", + "report_notification.categories.other_sentence": "altra", "report_notification.categories.spam": "Spamo", + "report_notification.categories.spam_sentence": "sendacho", "report_notification.categories.violation": "Regulnesequo", + "report_notification.categories.violation_sentence": "regulviolaco", "report_notification.open": "Apertez raporto", "search.no_recent_searches": "Nula serchi recenta", "search.placeholder": "Serchez", @@ -571,8 +766,11 @@ "server_banner.about_active_users": "Personi quo uzas ca servilo dum antea 30 dii (monate aktiva uzanti)", "server_banner.active_users": "aktiva uzanti", "server_banner.administered_by": "Administresis da:", + "server_banner.is_one_of_many": "{domain} esas 1 de multa sendependa servili di Mastodon quan vu povas uzar por partoprenar en la fediverso.", "server_banner.server_stats": "Servilstatistiko:", "sign_in_banner.create_account": "Kreez konto", + "sign_in_banner.follow_anyone": "On povas sequar ulu sur tota fediverso e vidar omno ye kronologia ordino. Nula algoritmi, reklami o klikatrapo omnaloke.", + "sign_in_banner.mastodon_is": "Mastodon esas la maxim bona voyo por saveskar eventi.", "sign_in_banner.sign_in": "Enirez", "sign_in_banner.sso_redirect": "Enirar o krear konto", "status.admin_account": "Apertez jerintervizajo por @{name}", @@ -582,14 +780,18 @@ "status.bookmark": "Libromarko", "status.cancel_reblog_private": "Desrepetez", "status.cannot_reblog": "Ca posto ne povas repetesar", + "status.continued_thread": "Durigita postaro", "status.copy": "Copy link to status", "status.delete": "Efacar", "status.detailed_status": "Detala konversvido", "status.direct": "Private mencionez @{name}", "status.direct_indicator": "Privata menciono", "status.edit": "Modifikez", + "status.edited": "Recente modifikesis ye {date}", "status.edited_x_times": "Modifikesis {count, plural, one {{count} foyo} other {{count} foyi}}", + "status.embed": "Ganez adherkodexo", "status.favourite": "Favorizar", + "status.favourites": "{count, plural, one {favorizo} other {favorizi}}", "status.filter": "Filtragez ca posto", "status.history.created": "{name} kreis ye {date}", "status.history.edited": "{name} modifikis ye {date}", @@ -608,9 +810,11 @@ "status.reblog": "Repetez", "status.reblog_private": "Repetez kun originala videbleso", "status.reblogged_by": "{name} repetis", + "status.reblogs": "{count, plural, one {repeto} other {repeti}}", "status.reblogs.empty": "Nulu ja repetis ca posto. Kande ulu facas lo, lu montresos hike.", "status.redraft": "Efacez e riskisigez", "status.remove_bookmark": "Efacez libromarko", + "status.replied_in_thread": "Respondesis en postaro", "status.replied_to": "Respondis a {name}", "status.reply": "Respondar", "status.replyAll": "Respondar a filo", @@ -648,6 +852,11 @@ "upload_error.poll": "Failadchargo ne permisesas kun votposti.", "upload_form.audio_description": "Deskriptez por personi kun audnekapableso", "upload_form.description": "Deskriptez por personi kun vidnekapableso", + "upload_form.drag_and_drop.instructions": "Por tenar mediatachajo, presez spaco o eniro. Presez spaco o eniro itere por destenar la mediatachajo en olua nova loko, o presez eskapo por anular.", + "upload_form.drag_and_drop.on_drag_cancel": "Tiro anulesis. Mediatachajo {item} destenesis.", + "upload_form.drag_and_drop.on_drag_end": "Mediatachajo {item} destenesis.", + "upload_form.drag_and_drop.on_drag_over": "Mediatachajo {item} movigesis.", + "upload_form.drag_and_drop.on_drag_start": "Tenis mediatachajo {item}.", "upload_form.edit": "Modifikez", "upload_form.thumbnail": "Chanjez imajeto", "upload_form.video_description": "Deskriptez por personi kun audnekapableso o vidnekapableso", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index fb807429f7056f..c78c5d78428216 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -221,7 +221,6 @@ "domain_block_modal.they_cant_follow": "Enginn frá þessum netþjóni getur fylgst með þér.", "domain_block_modal.they_wont_know": "Viðkomandi mun ekki vita að hann hafi verið útilokaður.", "domain_block_modal.title": "Útiloka lén?", - "domain_block_modal.you_will_lose_followers": "Allir fylgjendur þínir af þessum netþjóni verða fjarlægðir.", "domain_block_modal.you_wont_see_posts": "Þú munt ekki sjá neinar færslur eða tilkynningar frá notendum á þessum netþjóni.", "domain_pill.activitypub_lets_connect": "Það gerir þér kleift að tengjast og eiga í samskiptum við fólk, ekki bara á Mastodon, heldur einnig á mörgum öðrum mismunandi samfélagsmiðlum.", "domain_pill.activitypub_like_language": "ActivityPub er eins og tungumál sem Mastodon notar til að tala við önnur samfélagsnet.", @@ -432,8 +431,6 @@ "keyboard_shortcuts.unfocus": "Taka virkni úr textainnsetningarreit eða leit", "keyboard_shortcuts.up": "Fara ofar í listanum", "lightbox.close": "Loka", - "lightbox.compress": "Þjappa myndskoðunarreit", - "lightbox.expand": "Fletta út myndskoðunarreit", "lightbox.next": "Næsta", "lightbox.previous": "Fyrra", "limited_account_hint.action": "Birta notandasniðið samt", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 97518c586268a9..ef709516c23bee 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Limitazione per eccesso di richieste", "alert.unexpected.message": "Si è verificato un errore imprevisto.", "alert.unexpected.title": "Oops!", + "alt_text_badge.title": "Testo alternativo", "announcement.announcement": "Annuncio", "attachments_list.unprocessed": "(non elaborato)", "audio.hide": "Nascondi audio", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Nessuno da questo server può seguirti.", "domain_block_modal.they_wont_know": "Non sapranno di essere stati bloccati.", "domain_block_modal.title": "Bloccare il dominio?", - "domain_block_modal.you_will_lose_followers": "Tutti i tuoi seguaci da questo server verranno rimossi.", + "domain_block_modal.you_will_lose_num_followers": "Perderai {followersCount, plural, one {{followersCountDisplay} seguace} other {{followersCountDisplay} seguaci}} e {followingCount, plural, one {{followingCountDisplay} persona che segui} other {{followingCountDisplay} persone che segui}}.", + "domain_block_modal.you_will_lose_relationships": "Perderai tutti i seguaci e le persone che segui da questo server.", "domain_block_modal.you_wont_see_posts": "Non vedrai post o notifiche dagli utenti su questo server.", "domain_pill.activitypub_lets_connect": "Ti consente di connetterti e interagire con le persone non solo su Mastodon, ma anche su diverse app social.", "domain_pill.activitypub_like_language": "ActivityPub è come la lingua che Mastodon parla con altri social network.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "Rimuove il focus sull'area di composizione testuale/ricerca", "keyboard_shortcuts.up": "Scorre in su nell'elenco", "lightbox.close": "Chiudi", - "lightbox.compress": "Comprimi casella di visualizzazione immagine", - "lightbox.expand": "Espandi casella di visualizzazione immagine", "lightbox.next": "Successivo", "lightbox.previous": "Precedente", + "lightbox.zoom_in": "Ingrandisci alla dimensione attuale", + "lightbox.zoom_out": "Ingrandisci per adattarsi", "limited_account_hint.action": "Mostra comunque il profilo", "limited_account_hint.title": "Questo profilo è stato nascosto dai moderatori di {domain}.", "link_preview.author": "Di {name}", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 38492a73612b16..f5e7cc9c0484c3 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -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": "Mastodonからほかのソーシャルアプリのユーザーへ、そのまた別のアプリのユーザーへと、それぞれが互いにつながり関わり合うことをこのActivityPubの仕組みが実現しています。", "domain_pill.activitypub_like_language": "ActivityPubとは、Mastodonがほかのサーバーと会話をするときにしゃべる「言葉」のようなものです。", @@ -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}", @@ -457,6 +456,7 @@ "lists.subheading": "あなたのリスト", "load_pending": "{count}件の新着", "loading_indicator.label": "読み込み中…", + "media_gallery.hide": "隠す", "moved_to_account_banner.text": "あなたのアカウント『{disabledAccount}』は『{movedToAccount}』に移動したため現在無効になっています。", "mute_modal.hide_from_notifications": "通知をオフにする", "mute_modal.hide_options": "オプションを閉じる", @@ -785,6 +785,7 @@ "status.edit": "編集", "status.edited": "最終更新日 {date}", "status.edited_x_times": "{count}回編集", + "status.embed": "埋め込みコードを取得", "status.favourite": "お気に入り", "status.favourites": "{count, plural, one {お気に入り} other {お気に入り}}", "status.filter": "この投稿をフィルターする", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index 822fb59e6f85f8..9e2c9f3af8079a 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -73,6 +73,7 @@ "alert.rate_limited.title": "Aktum s talast", "alert.unexpected.message": "Yeḍra-d unezri ur netturaǧu ara.", "alert.unexpected.title": "Ayhuh!", + "alt_text_badge.title": "Aḍris asegzan", "announcement.announcement": "Ulɣu", "audio.hide": "Ffer amesli", "block_modal.show_less": "Ssken-d drus", @@ -82,6 +83,7 @@ "block_modal.title": "Sewḥel aseqdac ?", "block_modal.you_wont_see_mentions": "Ur tezmireḍ ara ad twaliḍ tisuffaɣ anda d-yettwabdar.", "boost_modal.combo": "Tzemreḍ ad tsiteḍ ɣef {combo} akken ad tzegleḍ aya tikelt i d-iteddun", + "boost_modal.reblog": "Zuzer tasuffeɣt?", "bundle_column_error.copy_stacktrace": "Nɣel tuccḍa n uneqqis", "bundle_column_error.error.title": "Uh, ala !", "bundle_column_error.network.title": "Tuccḍa deg uẓeṭṭa", @@ -190,7 +192,7 @@ "domain_pill.server": "Aqeddac", "domain_pill.username": "Isem n useqdac", "domain_pill.your_server": "D axxam-inek·inem umḍin, anda i zedɣent akk tsuffaɣ-ik·im. Ur k·m-yeεǧib ara wa? Ssenfel-d iqeddacen melmi i ak·m-yehwa, awi-d daɣen ineḍfaren-ik·im yid-k·m.", - "embed.instructions": "Ẓẓu addad-agi deg usmel-inek s wenγal n tangalt yellan sdaw-agi.", + "embed.instructions": "Ẓẓu addad-agi deg usmel-inek·inem s wenɣal n tangalt yellan sdaw-agi.", "embed.preview": "Akka ara d-iban:", "emoji_button.activity": "Aqeddic", "emoji_button.clear": "Sfeḍ", @@ -332,8 +334,6 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "i tulin ɣer d asawen n tebdart", "lightbox.close": "Mdel", - "lightbox.compress": "Ḥemmeẓ tamnaḍt n uskan n tugna", - "lightbox.expand": "Simeɣer tamnaḍt n uskan n tugna", "lightbox.next": "Ɣer zdat", "lightbox.previous": "Ɣer deffir", "limited_account_hint.action": "Wali amaɣnu akken yebɣu yili", @@ -356,7 +356,7 @@ "lists.subheading": "Tibdarin-ik·im", "load_pending": "{count, plural, one {# n uferdis amaynut} other {# n yiferdisen imaynuten}}", "loading_indicator.label": "Yessalay-d …", - "media_gallery.hide": "Ffer-it", + "media_gallery.hide": "Seggelmes", "mute_modal.hide_from_notifications": "Ffer-it deg ulɣuten", "mute_modal.hide_options": "Ffer tinefrunin", "mute_modal.indefinite": "Alamma ssnesreɣ asgugem fell-as", @@ -590,6 +590,7 @@ "status.direct_indicator": "Abdar uslig", "status.edit": "Ẓreg", "status.edited_x_times": "Tettwaẓreg {count, plural, one {{count} n tikkelt} other {{count} n tikkal}}", + "status.embed": "Awi-d tangalt n weslaɣ", "status.favourite": "Amenyaf", "status.favourites": "{count, plural, one {n usmenyaf} other {n ismenyafen}}", "status.filter": "Sizdeg tassufeɣt-a", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index cf2082e105d42f..2054dfc0ff7ff1 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -31,7 +31,7 @@ "account.featured_tags.last_status_never": "게시물 없음", "account.featured_tags.title": "{name} 님의 추천 해시태그", "account.follow": "팔로우", - "account.follow_back": "맞팔로우 하기", + "account.follow_back": "맞팔로우", "account.followers": "팔로워", "account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.", "account.followers_counter": "{count, plural, other {팔로워 {counter}명}}", @@ -85,6 +85,7 @@ "alert.rate_limited.title": "빈도 제한됨", "alert.unexpected.message": "예상하지 못한 에러가 발생했습니다.", "alert.unexpected.title": "앗!", + "alt_text_badge.title": "대체 문구", "announcement.announcement": "공지사항", "attachments_list.unprocessed": "(처리 안 됨)", "audio.hide": "소리 숨기기", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "{followersCount, plural, other {{followersCountDisplay} 명의 팔로워}}와 {followingCount, plural, other {{followingCountDisplay} 명의 팔로우}}를 잃게 됩니다.", + "domain_block_modal.you_will_lose_relationships": "이 서버의 팔로워와 팔로우를 모두 잃게 됩니다.", "domain_block_modal.you_wont_see_posts": "이 서버 사용자의 게시물이나 알림을 보지 않게 됩니다.", "domain_pill.activitypub_lets_connect": "이것은 마스토돈 뿐만이 아니라 다른 소셜 앱들을 넘나들며 사람들을 연결하고 상호작용 할 수 있게 합니다.", "domain_pill.activitypub_like_language": "액티비티펍은 마스토돈이 다른 소셜 네트워크와 대화할 때 쓰는 언어 같은 것입니다.", @@ -432,10 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "파일 업로드는 설문과 함께 쓸 수 없습니다.", "upload_form.audio_description": "청각장애인이나 저청각자를 위한 설명", "upload_form.description": "시각장애인이나 저시력자를 위한 설명", + "upload_form.drag_and_drop.instructions": "미디어 첨부파일을 집으려면 스페이스나 엔터를 누르세요. 드래그 하는 동안 방향키를 이용해 원하는 방향으로 이동할 수 있습니다. 스페이스나 엔터를 다시 눌러 새 위치에 놓거나 ESC를 이용해 취소할 수 있습니다.", + "upload_form.drag_and_drop.on_drag_cancel": "드래그가 취소되었습니다. 미디어 첨부파일 {item}은 이동되지 않았습니다.", + "upload_form.drag_and_drop.on_drag_end": "미디어 첨부파일 {item}은 이동되지 않았습니다.", + "upload_form.drag_and_drop.on_drag_over": "미디어 첨부파일 {item}이 이동되었습니다.", + "upload_form.drag_and_drop.on_drag_start": "미디어 첨부파일 {item}을 집었습니다.", "upload_form.edit": "수정", "upload_form.thumbnail": "썸네일 변경", "upload_form.video_description": "청각장애인, 저청각자, 시각장애인, 저시력자를 위한 설명", diff --git a/app/javascript/mastodon/locales/ku.json b/app/javascript/mastodon/locales/ku.json index dd10000d1813c8..86ecf984464718 100644 --- a/app/javascript/mastodon/locales/ku.json +++ b/app/javascript/mastodon/locales/ku.json @@ -293,8 +293,6 @@ "keyboard_shortcuts.unfocus": "Bal nede cîhê nivîsê /lêgerînê", "keyboard_shortcuts.up": "Di lîsteyê de rake jor", "lightbox.close": "Bigire", - "lightbox.compress": "Qutîya wêneya nîşan dike bitepisîne", - "lightbox.expand": "Qutîya wêneya nîşan dike fireh bike", "lightbox.next": "Pêş", "lightbox.previous": "Paş", "limited_account_hint.action": "Bi heman awayî profîlê nîşan bide", diff --git a/app/javascript/mastodon/locales/kw.json b/app/javascript/mastodon/locales/kw.json index 60b8321d53be76..cef24aa3b78a0a 100644 --- a/app/javascript/mastodon/locales/kw.json +++ b/app/javascript/mastodon/locales/kw.json @@ -195,8 +195,6 @@ "keyboard_shortcuts.unfocus": "Anfogella tekstva gomposya/hwilas", "keyboard_shortcuts.up": "Movya war-vann y'n rol", "lightbox.close": "Degea", - "lightbox.compress": "Kula kist a weles aven", - "lightbox.expand": "Efani kist a weles aven", "lightbox.next": "Nessa", "lightbox.previous": "Kynsa", "lists.account.add": "Keworra dhe rol", diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json index d894cc01c68788..ac95b590e3b307 100644 --- a/app/javascript/mastodon/locales/la.json +++ b/app/javascript/mastodon/locales/la.json @@ -58,7 +58,6 @@ "disabled_account_banner.text": "Ratio tua {disabledAccount} debilitata est.", "dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.", "dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", - "domain_block_modal.you_will_lose_followers": "Omnes sectatores tuī ex hoc servō removēbuntur.", "domain_block_modal.you_wont_see_posts": "Nuntios aut notificātiōnēs ab usoribus in hōc servō nōn vidēbis.", "domain_pill.activitypub_like_language": "ActivityPub est velut lingua quam Mastodon cum aliīs sociālibus rētibus loquitur.", "domain_pill.your_handle": "Tuus nominulus:", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index 72bf26050106c4..c5026fa33b7738 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -34,7 +34,9 @@ "account.follow_back": "Sige tamyen", "account.followers": "Suivantes", "account.followers.empty": "Por agora dingun no sige a este utilizador.", + "account.followers_counter": "{count, plural, one {{counter} suivante} other {{counter} suivantes}}", "account.following": "Sigiendo", + "account.following_counter": "{count, plural, other {Sigiendo a {counter}}}", "account.follows.empty": "Este utilizador ainda no sige a dingun.", "account.go_to_profile": "Va al profil", "account.hide_reblogs": "Eskonde repartajasyones de @{name}", @@ -60,6 +62,7 @@ "account.requested_follow": "{name} tiene solisitado segirte", "account.share": "Partaja el profil de @{name}", "account.show_reblogs": "Amostra repartajasyones de @{name}", + "account.statuses_counter": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}}", "account.unblock": "Dezbloka a @{name}", "account.unblock_domain": "Dezbloka domeno {domain}", "account.unblock_short": "Dezbloka", @@ -212,7 +215,6 @@ "domain_block_modal.they_cant_follow": "Dingun de este sirvidor puede segirte.", "domain_block_modal.they_wont_know": "No savra ke tiene sido blokado.", "domain_block_modal.title": "Bloka el domeno?", - "domain_block_modal.you_will_lose_followers": "Se efasaran todos tus suivantes de este sirvidor.", "domain_block_modal.you_wont_see_posts": "No veras publikasyones ni avizos de utilizadores en este sirvidor.", "domain_pill.server": "Sirvidor", "domain_pill.their_handle": "Su alias:", @@ -393,8 +395,6 @@ "keyboard_shortcuts.unfocus": "No enfoka en el area de eskrivir/bushkeda", "keyboard_shortcuts.up": "Move verso arriva en la lista", "lightbox.close": "Serra", - "lightbox.compress": "Kompresa kuadro de imaje", - "lightbox.expand": "Espande kuadro de imaje", "lightbox.next": "Sigiente", "lightbox.previous": "Anterior", "limited_account_hint.action": "Amostra el profil entanto", @@ -418,6 +418,7 @@ "lists.subheading": "Tus listas", "load_pending": "{count, plural, one {# muevo elemento} other {# muevos elementos}}", "loading_indicator.label": "Eskargando…", + "media_gallery.hide": "Eskonde", "moved_to_account_banner.text": "Tu kuento {disabledAccount} esta aktualmente inkapasitado porke transferates a {movedToAccount}.", "mute_modal.hide_from_notifications": "Eskonde de avizos", "mute_modal.hide_options": "Eskonde opsyones", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 5a510f5b96c986..043dcfb05d7f0c 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -1,7 +1,7 @@ { "about.blocks": "Prižiūrimi serveriai", "about.contact": "Kontaktai:", - "about.disclaimer": "„Mastodon“ – tai nemokama atvirojo kodo programinė įranga ir „Mastodon“ gGmbH prekės ženklas.", + "about.disclaimer": "„Mastodon“ – tai nemokama atvirojo kodo programinė įranga ir „Mastodon gGmbH“ prekės ženklas.", "about.domain_blocks.no_reason_available": "Priežastis nepateikta", "about.domain_blocks.preamble": "„Mastodon“ paprastai leidžia peržiūrėti turinį ir bendrauti su naudotojais iš bet kurio kito fediverse esančio serverio. Šios yra išimtys, kurios buvo padarytos šiame konkrečiame serveryje.", "about.domain_blocks.silenced.explanation": "Paprastai nematysi profilių ir turinio iš šio serverio, nebent jį aiškiai ieškosi arba pasirinksi jį sekant.", @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Sparta apribota.", "alert.unexpected.message": "Įvyko netikėta klaida.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Alternatyvus tekstas", "announcement.announcement": "Skelbimas", "attachments_list.unprocessed": "(neapdorotas)", "audio.hide": "Slėpti garsą", @@ -98,7 +99,7 @@ "block_modal.you_wont_see_mentions": "Nematysi įrašus, kuriuose jie paminimi.", "boost_modal.combo": "Galima paspausti {combo}, kad praleisti tai kitą kartą", "boost_modal.reblog": "Pasidalinti įrašą?", - "boost_modal.undo_reblog": "Panaikinti pasidalintą įrašą?", + "boost_modal.undo_reblog": "Nebepasidalinti įrašo?", "bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą", "bundle_column_error.error.body": "Paprašytos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.", "bundle_column_error.error.title": "O, ne!", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Niekas iš šio serverio negali tavęs sekti.", "domain_block_modal.they_wont_know": "Jie nežinos, kad buvo užblokuoti.", "domain_block_modal.title": "Blokuoti serverį?", - "domain_block_modal.you_will_lose_followers": "Visi tavo sekėjai iš šio serverio bus pašalinti.", + "domain_block_modal.you_will_lose_num_followers": "Prarasi {followersCount, plural, one {{followersCountDisplay} sekėją} few {{followersCountDisplay} sekėjus} many {{followersCountDisplay} sekėjo} other {{followersCountDisplay} sekėjų}} ir {followingCount, plural, one {{followingCountDisplay} žmogų, kurį seki} few {{followingCountDisplay} žmones, kuriuos seki} many {{followingCountDisplay} žmonės, kuriuos seki} other {{followingCountDisplay} žmonių, kurių seki}}.", + "domain_block_modal.you_will_lose_relationships": "Prarasi visus sekėjus ir žmones, kuriuos seki iš šio serverio.", "domain_block_modal.you_wont_see_posts": "Nematysi naudotojų įrašų ar pranešimų šiame serveryje.", "domain_pill.activitypub_lets_connect": "Tai leidžia tau prisijungti ir bendrauti su žmonėmis ne tik „Mastodon“ platformoje, bet ir įvairiose socialinėse programėlėse.", "domain_pill.activitypub_like_language": "„ActivityPub“ – tai tarsi kalba, kuria „Mastodon“ kalba su kitais socialiniais tinklais.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "Nebefokusuoti rengykles teksto sritį / paiešką", "keyboard_shortcuts.up": "Perkelti į viršų sąraše", "lightbox.close": "Uždaryti", - "lightbox.compress": "Suspausti vaizdo peržiūros langelį", - "lightbox.expand": "Išplėsti vaizdo peržiūros langelį", "lightbox.next": "Kitas", "lightbox.previous": "Ankstesnis", + "lightbox.zoom_in": "Padidink iki tikrojo dydžio", + "lightbox.zoom_out": "Padidink, kad tilptų", "limited_account_hint.action": "Vis tiek rodyti profilį", "limited_account_hint.title": "Šį profilį paslėpė {domain} prižiūrėtojai.", "link_preview.author": "Sukūrė {name}", @@ -766,7 +768,7 @@ "status.admin_status": "Atidaryti šį įrašą prižiūrėjimo sąsajoje", "status.block": "Blokuoti @{name}", "status.bookmark": "Pridėti į žymės", - "status.cancel_reblog_private": "Nebepakelti", + "status.cancel_reblog_private": "Nebepasidalinti", "status.cannot_reblog": "Šis įrašas negali būti pakeltas.", "status.continued_thread": "Tęsiama gijoje", "status.copy": "Kopijuoti nuorodą į įrašą", @@ -838,6 +840,11 @@ "upload_error.poll": "Failų įkėlimas neleidžiamas su apklausomis.", "upload_form.audio_description": "Aprašyk žmonėms, kurie yra kurtieji ar neprigirdintys.", "upload_form.description": "Aprašyk žmonėms, kurie yra aklieji arba silpnaregiai.", + "upload_form.drag_and_drop.instructions": "Kad paimtum medijos priedą, paspausk tarpo arba įvedimo klavišą. Tempant naudok rodyklių klavišus, kad perkeltum medijos priedą bet kuria kryptimi. Dar kartą paspausk tarpo arba įvedimo klavišą, kad nuleistum medijos priedą naujoje vietoje, arba paspausk grįžimo klavišą, kad atšauktum.", + "upload_form.drag_and_drop.on_drag_cancel": "Nutempimas buvo atšauktas. Medijos priedas {item} buvo nuleistas.", + "upload_form.drag_and_drop.on_drag_end": "Medijos priedas {item} buvo nuleistas.", + "upload_form.drag_and_drop.on_drag_over": "Medijos priedas {item} buvo perkeltas.", + "upload_form.drag_and_drop.on_drag_start": "Paimtas medijos priedas {item}.", "upload_form.edit": "Redaguoti", "upload_form.thumbnail": "Keisti miniatiūrą", "upload_form.video_description": "Aprašyk žmonėms, kurie yra kurtieji, neprigirdintys, aklieji ar silpnaregiai.", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 53b3c0fcaa22a9..1e973ffd3ea5bf 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -215,7 +215,6 @@ "domain_block_modal.they_cant_follow": "Neviens šajā serverī nevar Tev sekot.", "domain_block_modal.they_wont_know": "Viņi nezinās, ka tikuši bloķēti.", "domain_block_modal.title": "Bloķēt domēnu?", - "domain_block_modal.you_will_lose_followers": "Tiks noņemti visi tavi sekotāji no šī servera.", "domain_pill.server": "Serveris", "domain_pill.username": "Lietotājvārds", "embed.instructions": "Iestrādā šo ziņu savā mājaslapā, kopējot zemāk redzamo kodu.", @@ -385,8 +384,6 @@ "keyboard_shortcuts.unfocus": "Atfokusēt veidojamā teksta/meklēšanas lauku", "keyboard_shortcuts.up": "Pārvietoties augšup sarakstā", "lightbox.close": "Aizvērt", - "lightbox.compress": "Saspiest attēla skata lodziņu", - "lightbox.expand": "Izvērst attēla skata lodziņu", "lightbox.next": "Tālāk", "lightbox.previous": "Iepriekšējais", "limited_account_hint.action": "Tik un tā rādīt profilu", diff --git a/app/javascript/mastodon/locales/mr.json b/app/javascript/mastodon/locales/mr.json index 47c3a55e55c6fa..aa8169616e70e3 100644 --- a/app/javascript/mastodon/locales/mr.json +++ b/app/javascript/mastodon/locales/mr.json @@ -169,8 +169,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": "तरीही प्रोफाइल दाखवा", diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json index 44403ec959486e..cbd57ab356994d 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -360,8 +360,6 @@ "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "Pindah ke atas dalam senarai", "lightbox.close": "Tutup", - "lightbox.compress": "Kecilkan kotak paparan imej", - "lightbox.expand": "Besarkan kotak paparan imej", "lightbox.next": "Seterusnya", "lightbox.previous": "Sebelumnya", "limited_account_hint.action": "Paparkan profil", diff --git a/app/javascript/mastodon/locales/my.json b/app/javascript/mastodon/locales/my.json index e93b47fd542f14..c97de733354ad6 100644 --- a/app/javascript/mastodon/locales/my.json +++ b/app/javascript/mastodon/locales/my.json @@ -339,8 +339,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": "ဘာပဲဖြစ်ဖြစ် ပရိုဖိုင်ကို ပြပါ", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index 1043ca8376caf8..1c31574deaffe4 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Dataverkeer beperkt", "alert.unexpected.message": "Er deed zich een onverwachte fout voor", "alert.unexpected.title": "Oeps!", + "alt_text_badge.title": "Alt-tekst", "announcement.announcement": "Mededeling", "attachments_list.unprocessed": "(niet verwerkt)", "audio.hide": "Audio verbergen", @@ -216,12 +217,13 @@ "dismissable_banner.explore_tags": "Deze hashtags winnen aan populariteit op het sociale web (fediverse). Hashtags die door meer verschillende mensen worden gebruikt staan hoger.", "dismissable_banner.public_timeline": "Dit zijn de meest recente openbare berichten van accounts op het sociale web (fediverse) die door mensen op {domain} worden gevolgd.", "domain_block_modal.block": "Server blokkeren", - "domain_block_modal.block_account_instead": "In plaats hiervan {name} blokkeren", + "domain_block_modal.block_account_instead": "Alleen {name} blokkeren", "domain_block_modal.they_can_interact_with_old_posts": "Mensen op deze server kunnen interactie hebben met jouw oude berichten.", "domain_block_modal.they_cant_follow": "Niemand op deze server kan jou volgen.", "domain_block_modal.they_wont_know": "Ze krijgen niet te weten dat ze worden geblokkeerd.", "domain_block_modal.title": "Server blokkeren?", - "domain_block_modal.you_will_lose_followers": "Al jouw volgers van deze server worden ontvolgd.", + "domain_block_modal.you_will_lose_num_followers": "Je verliest {followersCount, plural, one {{followersCountDisplay} volger} other {{followersCountDisplay} volgers}} en {followingCount, plural, one {{followingCountDisplay} persoon die jij volgt} other {{followingCountDisplay} personen die jij volgt}}.", + "domain_block_modal.you_will_lose_relationships": "Je verliest alle volgers en mensen die je volgt van deze server.", "domain_block_modal.you_wont_see_posts": "Je ziet geen berichten of meldingen meer van gebruikers op deze server.", "domain_pill.activitypub_lets_connect": "Het zorgt ervoor dat je niet alleen maar kunt verbinden en communiceren met mensen op Mastodon, maar ook met andere sociale apps.", "domain_pill.activitypub_like_language": "ActivityPub is de taal die Mastodon met andere sociale netwerken spreekt.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "Tekst- en zoekveld ontfocussen", "keyboard_shortcuts.up": "Naar boven in de lijst bewegen", "lightbox.close": "Sluiten", - "lightbox.compress": "Afbeelding passend weergeven", - "lightbox.expand": "Afbeelding groot weergeven", "lightbox.next": "Volgende", "lightbox.previous": "Vorige", + "lightbox.zoom_in": "Oorspronkelijke grootte weergeven", + "lightbox.zoom_out": "Passend weergeven", "limited_account_hint.action": "Alsnog het profiel tonen", "limited_account_hint.title": "Dit profiel is door de moderatoren van {domain} verborgen.", "link_preview.author": "Door {name}", @@ -850,6 +852,11 @@ "upload_error.poll": "Het uploaden van bestanden is bij peilingen niet toegestaan.", "upload_form.audio_description": "Omschrijf dit voor dove of slechthorende mensen", "upload_form.description": "Omschrijf dit voor blinde of slechtziende mensen", + "upload_form.drag_and_drop.instructions": "Druk op spatie of enter om een mediabijlage op te pakken. Gebruik de pijltjestoetsen om de bijlage in een bepaalde richting te verplaatsen. Druk opnieuw op de spatiebalk of enter om de mediabijlage op de nieuwe positie te plaatsen, of druk op escape om te annuleren.", + "upload_form.drag_and_drop.on_drag_cancel": "Slepen is geannuleerd. Mediabijlage {item} is niet verplaatst.", + "upload_form.drag_and_drop.on_drag_end": "Mediabijlage {item} is niet verplaatst.", + "upload_form.drag_and_drop.on_drag_over": "Mediabijlage {item} is verplaatst.", + "upload_form.drag_and_drop.on_drag_start": "Mediabijlage {item} is opgepakt.", "upload_form.edit": "Bewerken", "upload_form.thumbnail": "Miniatuurafbeelding wijzigen", "upload_form.video_description": "Omschrijf dit voor dove, slechthorende, blinde of slechtziende mensen", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index c4b5f0291df130..69883a54953084 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Redusert kapasitet", "alert.unexpected.message": "Det oppstod eit uventa problem.", "alert.unexpected.title": "Oi sann!", + "alt_text_badge.title": "Alternativ tekst", "announcement.announcement": "Kunngjering", "attachments_list.unprocessed": "(ubehandla)", "audio.hide": "Gøym lyd", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Ingen på denne tenaren kan fylgja deg.", "domain_block_modal.they_wont_know": "Dei veit ikkje at dei er blokkerte.", "domain_block_modal.title": "Blokker domenet?", - "domain_block_modal.you_will_lose_followers": "Alle fylgjarane dine frå denne tenaren blir fjerna.", + "domain_block_modal.you_will_lose_num_followers": "Du vil mista {followersCount, plural, one {{followersCountDisplay} fylgjar} other {{followersCountDisplay} fylgjarar}} og {followingCount, plural, one {{followingCountDisplay} person du fylgjer} other {{followingCountDisplay} folk du fylgjer}}.", + "domain_block_modal.you_will_lose_relationships": "Du vil mista alle fylgjarar og folk du fylgjer på denne tenaren.", "domain_block_modal.you_wont_see_posts": "Du vil ikkje sjå innlegg eller varslingar frå brukarar på denne tenaren.", "domain_pill.activitypub_lets_connect": "Den lar deg kople til og samhandle med folk ikkje berre på Mastodon, men òg på tvers av forskjellige sosiale appar.", "domain_pill.activitypub_like_language": "ActivityPub er som språket Mastodon snakkar med andre sosiale nettverk.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "for å fokusere vekk skrive-/søkefeltet", "keyboard_shortcuts.up": "Flytt opp på lista", "lightbox.close": "Lukk", - "lightbox.compress": "Komprimer biletvisningsboksen", - "lightbox.expand": "Utvid biletvisningsboksen", "lightbox.next": "Neste", "lightbox.previous": "Førre", + "lightbox.zoom_in": "Zoom til faktisk storleik", + "lightbox.zoom_out": "Vis heile", "limited_account_hint.action": "Vis profilen likevel", "limited_account_hint.title": "Denne profilen er skjult av moderatorane på {domain}.", "link_preview.author": "Av {name}", @@ -850,6 +852,11 @@ "upload_error.poll": "Filopplasting er ikkje lov for rundspørjingar.", "upload_form.audio_description": "Skildre for dei med nedsett høyrsel", "upload_form.description": "Skildre for blinde og svaksynte", + "upload_form.drag_and_drop.instructions": "For å plukka opp eit medievedlegg, trykkjer du på mellomrom eller enter. Når du dreg, brukar du piltastane for å flytta vedlegget i den retninga du vil. Deretter trykkjer du mellomrom eller enter att for å sleppa vedlegget på den nye plassen, eller trykk escape for å avbryta.", + "upload_form.drag_and_drop.on_drag_cancel": "Du avbraut draginga. Medievedlegget {item} vart sleppt.", + "upload_form.drag_and_drop.on_drag_end": "Medeivedlegget {item} vart sleppt.", + "upload_form.drag_and_drop.on_drag_over": "Medievedlegget {item} vart flytta.", + "upload_form.drag_and_drop.on_drag_start": "Plukka opp medievedlegget {item}.", "upload_form.edit": "Rediger", "upload_form.thumbnail": "Bytt miniatyrbilete", "upload_form.video_description": "Skildre for dei med nedsett høyrsel eller redusert syn", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 1222f404241e9f..8cd3387eaf968c 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -221,7 +221,6 @@ "domain_block_modal.they_cant_follow": "Ingen fra denne serveren kan følge deg.", "domain_block_modal.they_wont_know": "De kommer ikke til å få vite at du har valgt å blokkere dem.", "domain_block_modal.title": "Blokker domenet?", - "domain_block_modal.you_will_lose_followers": "Alle dine følgere fra denne serveren vil bli fjernet.", "domain_block_modal.you_wont_see_posts": "Du vil ikke se innlegg eller få varsler fra brukere på denne serveren.", "domain_pill.activitypub_lets_connect": "Den lar deg koble til og samhandle med folk ikke bare på Mastodon, men også på tvers av forskjellige sosiale apper.", "domain_pill.activitypub_like_language": "ActivityPub er liksom språket Mastodon snakker med andre sosiale nettverk.", @@ -432,8 +431,6 @@ "keyboard_shortcuts.unfocus": "Fjern fokus fra komponerings-/søkefeltet", "keyboard_shortcuts.up": "Flytt oppover i listen", "lightbox.close": "Lukk", - "lightbox.compress": "Komprimer bildevisningsboks", - "lightbox.expand": "Ekspander bildevisning boks", "lightbox.next": "Neste", "lightbox.previous": "Forrige", "limited_account_hint.action": "Vis profil likevel", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 22193f82aa41e5..9dbd123c9be92a 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -297,8 +297,6 @@ "keyboard_shortcuts.unfocus": "quitar lo camp tèxte/de recèrca", "keyboard_shortcuts.up": "far montar dins la lista", "lightbox.close": "Tampar", - "lightbox.compress": "Fenèstra de visualizacion dels imatges compressats", - "lightbox.expand": "Espandir la fenèstra de visualizacion d’imatge", "lightbox.next": "Seguent", "lightbox.previous": "Precedent", "limited_account_hint.action": "Afichar lo perfil de tota manièra", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index d415bb38119c89..4dc74db8cbed73 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Ograniczenie liczby zapytań", "alert.unexpected.message": "Wystąpił nieoczekiwany błąd.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Tekst alternatywny", "announcement.announcement": "Ogłoszenie", "attachments_list.unprocessed": "(nieprzetworzone)", "audio.hide": "Ukryj dźwięk", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Nikt z tego serwera nie może Cię obserwować.", "domain_block_modal.they_wont_know": "Użytkownik nie dowie się, że został zablokowany.", "domain_block_modal.title": "Zablokować domenę?", - "domain_block_modal.you_will_lose_followers": "Wszyscy twoi obserwujący z tego serwera zostaną usunięci.", + "domain_block_modal.you_will_lose_num_followers": "Utracisz {followersCount, plural, one {jednego obserwującego} other {{followersCountDisplay} obserwujących}} i {followingCount, plural, one {jedną osobę którą obserwujesz} few {{followingCountDisplay} osoby które obserwujesz} other {{followingCountDisplay} osób które obserwujesz}}.", + "domain_block_modal.you_will_lose_relationships": "Utracisz wszystkich obserwujących z tego serwera i wszystkie osoby które obserwujesz na tym serwerze.", "domain_block_modal.you_wont_see_posts": "Nie zobaczysz postów ani powiadomień od użytkowników na tym serwerze.", "domain_pill.activitypub_lets_connect": "Pozwala połączyć się z ludźmi na Mastodonie, jak i na innych serwisach społecznościowych.", "domain_pill.activitypub_like_language": "ActivityPub jest językiem używanym przez Mastodon do wymiany danych z innymi serwisami społecznościowymi.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "aby opuścić pole wyszukiwania/pisania", "keyboard_shortcuts.up": "aby przejść na górę listy", "lightbox.close": "Zamknij", - "lightbox.compress": "Zmniejsz pole widoku obrazu", - "lightbox.expand": "Rozwiń pole widoku obrazu", "lightbox.next": "Następne", "lightbox.previous": "Poprzednie", + "lightbox.zoom_in": "Rozmiar rzeczywisty", + "lightbox.zoom_out": "Dopasuj", "limited_account_hint.action": "Pokaż profil mimo to", "limited_account_hint.title": "Ten profil został ukryty przez moderatorów {domain}.", "link_preview.author": "{name}", @@ -850,6 +852,11 @@ "upload_error.poll": "Dołączanie plików nie dozwolone z głosowaniami.", "upload_form.audio_description": "Opisz dla osób niesłyszących i niedosłyszących", "upload_form.description": "Wprowadź opis dla niewidomych i niedowidzących", + "upload_form.drag_and_drop.instructions": "Naciśnij spację lub enter żeby podnieść załącznik. Podczas przeciągania, strzałki przesuwają załącznik. Naciśnięcie spacji lub entera upuści załącznik w nowym miejscu, a escape anuluje przesuwanie.", + "upload_form.drag_and_drop.on_drag_cancel": "Przesuwanie anulowane. Załącznik {item} upuszczony.", + "upload_form.drag_and_drop.on_drag_end": "Upuszczono załącznik {item}.", + "upload_form.drag_and_drop.on_drag_over": "Przesunięto załącznik {item}.", + "upload_form.drag_and_drop.on_drag_start": "Podniesiono załącznik {item}.", "upload_form.edit": "Edytuj", "upload_form.thumbnail": "Zmień miniaturę", "upload_form.video_description": "Opisz dla osób niesłyszących, niedosłyszących, niewidomych i niedowidzących", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 053ae25822b277..d1a3ecdaa73aff 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Tentativas limitadas", "alert.unexpected.message": "Ocorreu um erro inesperado.", "alert.unexpected.title": "Eita!", + "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Comunicados", "attachments_list.unprocessed": "(não processado)", "audio.hide": "Ocultar áudio", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Ninguém deste servidor pode lhe seguir.", "domain_block_modal.they_wont_know": "Eles não saberão que foram bloqueados.", "domain_block_modal.title": "Dominio do bloco", - "domain_block_modal.you_will_lose_followers": "Todos os seus seguidores deste servidor serão removidos.", + "domain_block_modal.you_will_lose_num_followers": "Você perderá {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} e {followingCount, plural, one {{followingCountDisplay} pessoa que você segue} other {{followingCountDisplay} pessoas que você segue}}.", + "domain_block_modal.you_will_lose_relationships": "Você irá perder todos os seguidores e pessoas que você segue neste servidor.", "domain_block_modal.you_wont_see_posts": "Você não verá postagens ou notificações de usuários neste servidor.", "domain_pill.activitypub_lets_connect": "Ele permite que você se conecte e interaja com pessoas não apenas no Mastodon, mas também em diferentes aplicativos sociais.", "domain_pill.activitypub_like_language": "ActivityPub é como a linguagem que o Mastodon fala com outras redes sociais.", @@ -432,10 +434,9 @@ "keyboard_shortcuts.unfocus": "desfocar de tudo", "keyboard_shortcuts.up": "mover para cima", "lightbox.close": "Fechar", - "lightbox.compress": "Fechar imagem", - "lightbox.expand": "Abrir imagem", "lightbox.next": "Próximo", "lightbox.previous": "Anterior", + "lightbox.zoom_in": "Voltar para o tamanho real", "limited_account_hint.action": "Exibir perfil mesmo assim", "limited_account_hint.title": "Este perfil foi ocultado pelos moderadores do {domain}.", "link_preview.author": "Por {name}", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index ed4bb9ba010a6d..6be7e03b393d3a 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -221,7 +221,6 @@ "domain_block_modal.they_cant_follow": "Ninguém deste servidor pode segui-lo.", "domain_block_modal.they_wont_know": "Eles não saberão que foram bloqueados.", "domain_block_modal.title": "Bloquear domínio?", - "domain_block_modal.you_will_lose_followers": "Todos os seus seguidores deste servidor serão removidos.", "domain_block_modal.you_wont_see_posts": "Não verá publicações ou notificações de utilizadores neste servidor.", "domain_pill.activitypub_lets_connect": "Permite-lhe conectar e interagir com pessoas não só no Mastodon, mas também em diferentes aplicações sociais.", "domain_pill.activitypub_like_language": "O ActivityPub é como a linguagem que o Mastodon fala com outras redes sociais.", @@ -432,8 +431,6 @@ "keyboard_shortcuts.unfocus": "para remover o foco da área de texto/pesquisa", "keyboard_shortcuts.up": "para mover para cima na lista", "lightbox.close": "Fechar", - "lightbox.compress": "Compactar caixa de visualização de imagem", - "lightbox.expand": "Expandir caixa de visualização de imagem", "lightbox.next": "Próximo", "lightbox.previous": "Anterior", "limited_account_hint.action": "Exibir perfil mesmo assim", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 73b8140de65845..a61f4b0d4fd41d 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -334,8 +334,6 @@ "keyboard_shortcuts.unfocus": "Părăsește zona de text/bara de căutare", "keyboard_shortcuts.up": "Urcă în listă", "lightbox.close": "Închide", - "lightbox.compress": "Închide panoul de vizualizare a imaginilor", - "lightbox.expand": "Deschide panoul de vizualizare a imaginilor", "lightbox.next": "Înainte", "lightbox.previous": "Înapoi", "limited_account_hint.action": "Afișează profilul oricum", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index d97b1658c552ae..9bd2ed5b4e7be7 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -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 говорит с другими социальными сетями.", @@ -431,8 +430,6 @@ "keyboard_shortcuts.unfocus": "убрать фокус с поля ввода/поиска", "keyboard_shortcuts.up": "вверх по списку", "lightbox.close": "Закрыть", - "lightbox.compress": "Сжать окно просмотра изображений", - "lightbox.expand": "Развернуть окно просмотра изображений", "lightbox.next": "Далее", "lightbox.previous": "Назад", "limited_account_hint.action": "Все равно показать профиль", diff --git a/app/javascript/mastodon/locales/sa.json b/app/javascript/mastodon/locales/sa.json index 85bd9aa9ddc79e..2d48f688d58971 100644 --- a/app/javascript/mastodon/locales/sa.json +++ b/app/javascript/mastodon/locales/sa.json @@ -299,8 +299,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": "प्रोफैलं दर्शय कथञ्चित्", diff --git a/app/javascript/mastodon/locales/sc.json b/app/javascript/mastodon/locales/sc.json index 071643a1538f1a..bb7d062b95e31b 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -350,8 +350,6 @@ "keyboard_shortcuts.unfocus": "Essi de s'àrea de cumpositzione de testu o de chirca", "keyboard_shortcuts.up": "Move in susu in sa lista", "lightbox.close": "Serra", - "lightbox.compress": "Cumprime sa casella de visualizatzione de is immàgines", - "lightbox.expand": "Ismànnia sa casella de visualizatzione de is immàgines", "lightbox.next": "Imbeniente", "lightbox.previous": "Pretzedente", "limited_account_hint.title": "Custu profilu est istadu cuadu dae sa moderatzione de {domain}.", diff --git a/app/javascript/mastodon/locales/sco.json b/app/javascript/mastodon/locales/sco.json index 269e29a86ff6ff..c14f1cc51acda0 100644 --- a/app/javascript/mastodon/locales/sco.json +++ b/app/javascript/mastodon/locales/sco.json @@ -284,8 +284,6 @@ "keyboard_shortcuts.unfocus": "Unfocus scrieve textarea/seirch", "keyboard_shortcuts.up": "Muive up in the list", "lightbox.close": "Shut", - "lightbox.compress": "Compress image view box", - "lightbox.expand": "Expand image view box", "lightbox.next": "Neist", "lightbox.previous": "Last ane", "limited_account_hint.action": "Shaw profile onieweys", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index d21dc5e1ab4fa9..ddf341584c0d85 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -34,7 +34,9 @@ "account.follow_back": "Sledovať späť", "account.followers": "Sledovatelia", "account.followers.empty": "Tento účet ešte nikto nesleduje.", + "account.followers_counter": "{count, plural, one {{counter} sledujúci} other {{counter} sledujúci}}", "account.following": "Sledovaný účet", + "account.following_counter": "{count, plural, one {{counter} sledovaných} other {{counter} sledovaných}}", "account.follows.empty": "Tento účet ešte nikoho nesleduje.", "account.go_to_profile": "Prejsť na profil", "account.hide_reblogs": "Skryť zdieľania od @{name}", @@ -60,6 +62,7 @@ "account.requested_follow": "{name} vás chce sledovať", "account.share": "Zdieľaj profil @{name}", "account.show_reblogs": "Zobrazovať zdieľania od @{name}", + "account.statuses_counter": "{count, plural, one {{counter} príspevok} other {{counter} príspevkov}}", "account.unblock": "Odblokovať @{name}", "account.unblock_domain": "Odblokovať doménu {domain}", "account.unblock_short": "Odblokovať", @@ -215,7 +218,6 @@ "domain_block_modal.they_cant_follow": "Nikto z tohoto servera ťa nemôže nasledovať.", "domain_block_modal.they_wont_know": "Nebude vedieť, že bol/a zablokovaný/á.", "domain_block_modal.title": "Blokovať doménu?", - "domain_block_modal.you_will_lose_followers": "Všetci tvoji nasledovatelia z tohto servera budú odstránení.", "domain_block_modal.you_wont_see_posts": "Neuvidíš príspevky, ani oboznámenia od užívateľov na tomto serveri.", "domain_pill.activitypub_like_language": "ActivityPub je ako jazyk, ktorým Mastodon hovorí s ostatnými sociálnymi sieťami.", "domain_pill.server": "Server", @@ -396,8 +398,6 @@ "keyboard_shortcuts.unfocus": "Odísť z textového poľa", "keyboard_shortcuts.up": "Posunúť sa vyššie v zozname", "lightbox.close": "Zatvoriť", - "lightbox.compress": "Zmenšiť náhľad obrázku", - "lightbox.expand": "Rozšíriť náhľad obrázku", "lightbox.next": "Ďalej", "lightbox.previous": "Späť", "limited_account_hint.action": "Aj tak zobraziť profil", @@ -420,6 +420,7 @@ "lists.subheading": "Vaše zoznamy", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položiek} other {# nových položiek}}", "loading_indicator.label": "Načítavanie…", + "media_gallery.hide": "Skryť", "moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálne deaktivovaný, pretože ste sa presunuli na {movedToAccount}.", "mute_modal.hide_from_notifications": "Ukryť z upozornení", "mute_modal.hide_options": "Skryť možnosti", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index bdc1d5606289ab..71bee6822b3c64 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -217,7 +217,6 @@ "domain_block_modal.they_cant_follow": "Nihče s tega strežnika vam ne more slediti.", "domain_block_modal.they_wont_know": "Ne bodo vedeli, da so blokirani.", "domain_block_modal.title": "Blokiraj domeno?", - "domain_block_modal.you_will_lose_followers": "Vsi vaši sledilci s tega strežnika bodo odstranjeni.", "domain_block_modal.you_wont_see_posts": "Objav ali obvestil uporabnikov s tega strežnika ne boste videli.", "domain_pill.activitypub_lets_connect": "Omogoča vam povezovanje in interakcijo z ljudmi, ki niso samo na Mastodonu, ampak tudi na drugih družabnih platformah.", "domain_pill.activitypub_like_language": "Protokol ActivityPub je kot jezik, s katerim se Mastodon pogovarja z drugimi družabnimi omrežji.", @@ -412,8 +411,6 @@ "keyboard_shortcuts.unfocus": "Odstrani pozornost z območja za sestavljanje besedila/iskanje", "keyboard_shortcuts.up": "Premakni navzgor po seznamu", "lightbox.close": "Zapri", - "lightbox.compress": "Strni ogledno polje slike", - "lightbox.expand": "Razširi ogledno polje slike", "lightbox.next": "Naslednji", "lightbox.previous": "Prejšnji", "limited_account_hint.action": "Vseeno pokaži profil", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index ea3c6d5c7c66c6..084ac9945fae18 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Shpejtësi e kufizuar", "alert.unexpected.message": "Ndodhi një gabim të papritur.", "alert.unexpected.title": "Hëm!", + "alt_text_badge.title": "Tekst alternativ", "announcement.announcement": "Lajmërim", "attachments_list.unprocessed": "(e papërpunuar)", "audio.hide": "Fshihe audion", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "S’mund t’ju ndjekë askush nga ky shërbyes.", "domain_block_modal.they_wont_know": "S’do ta dinë se janë bllokuar.", "domain_block_modal.title": "Të bllokohet përkatësia?", - "domain_block_modal.you_will_lose_followers": "Krejt ndjekësit tuaj nga ky shërbyes do të hiqen.", + "domain_block_modal.you_will_lose_num_followers": "Do të humbni {followersCount, plural, one {{followersCountDisplay} ndjekës} other {{followersCountDisplay} ndjekës}} dhe {followingCount, plural, one {{followingCountDisplay} person që ndiqni} other {{followingCountDisplay} vetë që ndiqni}}.", + "domain_block_modal.you_will_lose_relationships": "Do të humbni krejt ndjekësit dhe personat që ndiqni nga ky shërbyes.", "domain_block_modal.you_wont_see_posts": "S’do të shihni postime, apo njoftime nga përdorues në këtë shërbyes.", "domain_pill.activitypub_lets_connect": "Ju lejon të lidheni dhe ndërveproni me persona jo thjesht në Mastodon, por edhe nëpër aplikacione të ndryshme shoqërore.", "domain_pill.activitypub_like_language": "ActivityPub është si gjuha me të cilën Mastodon-i komunikon me rrjete të tjerë shoqërorë.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "Për heqjen e fokusit nga fusha e hartimit të mesazheve apo kërkimeve", "keyboard_shortcuts.up": "Për ngjitje sipër nëpër listë", "lightbox.close": "Mbylle", - "lightbox.compress": "Ngjeshe kuadratin e parjes së figurave", - "lightbox.expand": "Zgjeroje kuadratin e parjes së figurave", "lightbox.next": "Pasuesja", "lightbox.previous": "E mëparshmja", + "lightbox.zoom_in": "Ktheje në madhësinë origjinale", + "lightbox.zoom_out": "Zmadhoje të përshtatet", "limited_account_hint.action": "Shfaqe profilin sido qoftë", "limited_account_hint.title": "Ky profil është fshehur nga moderatorët e {domain}.", "link_preview.author": "Nga {name}", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index de30ca280fae12..1053d581c323f5 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -209,7 +209,6 @@ "domain_block_modal.they_cant_follow": "Niko sa ovog servera ne može da vas prati.", "domain_block_modal.they_wont_know": "Neće znati da su blokirani.", "domain_block_modal.title": "Blokirati domen?", - "domain_block_modal.you_will_lose_followers": "Svi vaši pratioci sa ovog servera će biti uklonjeni.", "domain_block_modal.you_wont_see_posts": "Nećete videti objave ili obaveštenja korisnika na ovom serveru.", "domain_pill.activitypub_lets_connect": "Omogućuje vam da se povežete i komunicirate sa ljudima ne samo na Mastodon-u, već i u različitim društvenim aplikacijama.", "domain_pill.activitypub_like_language": "ActivityPub je kao jezik kojim Mastodon govori sa drugim društvenim mrežama.", @@ -399,8 +398,6 @@ "keyboard_shortcuts.unfocus": "Ukloni fokus sa polja za unos teksta/pretrage", "keyboard_shortcuts.up": "Premesti nagore u listi", "lightbox.close": "Zatvori", - "lightbox.compress": "Komprimuj okvir za prikaz slike", - "lightbox.expand": "Proširi okvir za prikaz slike", "lightbox.next": "Sledeće", "lightbox.previous": "Prethodno", "limited_account_hint.action": "Ipak prikaži profil", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 255215a1671f72..9529c41fe301df 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -209,7 +209,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 говори са другим друштвеним мрежама.", @@ -399,8 +398,6 @@ "keyboard_shortcuts.unfocus": "Уклони фокус са поља за унос текста/претраге", "keyboard_shortcuts.up": "Премести нагоре у листи", "lightbox.close": "Затвори", - "lightbox.compress": "Компримуј оквир за приказ слике", - "lightbox.expand": "Прошири оквир за приказ слике", "lightbox.next": "Следеће", "lightbox.previous": "Претходно", "limited_account_hint.action": "Ипак прикажи профил", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 4d560a6495e451..b1e5a95edf55a2 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -219,7 +219,6 @@ "domain_block_modal.they_cant_follow": "Ingen från denna server kan följa dig.", "domain_block_modal.they_wont_know": "De kommer inte veta att de har blockerats.", "domain_block_modal.title": "Blockera domän?", - "domain_block_modal.you_will_lose_followers": "Alla dina följare från denna server kommer att tas bort.", "domain_block_modal.you_wont_see_posts": "Du kommer inte att se inlägg eller meddelanden från användare på den här servern.", "domain_pill.activitypub_lets_connect": "Det låter dig ansluta och interagera med människor inte bara på Mastodon, men även på andra sociala appar.", "domain_pill.activitypub_like_language": "ActivityPub är som språket Mastodon talar med andra sociala nätverk.", @@ -429,8 +428,6 @@ "keyboard_shortcuts.unfocus": "för att avfokusera skrivfält/sökfält", "keyboard_shortcuts.up": "för att flytta uppåt i listan", "lightbox.close": "Stäng", - "lightbox.compress": "Komprimera bildvyrutan", - "lightbox.expand": "Utöka bildvyrutan", "lightbox.next": "Nästa", "lightbox.previous": "Tidigare", "limited_account_hint.action": "Visa profil ändå", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 9578431ff741b2..160b6ec4e69be0 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "มีการจำกัดอัตรา", "alert.unexpected.message": "เกิดข้อผิดพลาดที่ไม่คาดคิด", "alert.unexpected.title": "อุปส์!", + "alt_text_badge.title": "ข้อความแสดงแทน", "announcement.announcement": "ประกาศ", "attachments_list.unprocessed": "(ยังไม่ได้ประมวลผล)", "audio.hide": "ซ่อนเสียง", @@ -221,7 +222,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 พูดกับเครือข่ายสังคมอื่น ๆ", @@ -432,8 +432,6 @@ "keyboard_shortcuts.unfocus": "เลิกโฟกัสพื้นที่เขียนข้อความ/การค้นหา", "keyboard_shortcuts.up": "ย้ายขึ้นในรายการ", "lightbox.close": "ปิด", - "lightbox.compress": "บีบอัดกล่องดูภาพ", - "lightbox.expand": "ขยายกล่องดูภาพ", "lightbox.next": "ถัดไป", "lightbox.previous": "ก่อนหน้า", "limited_account_hint.action": "แสดงโปรไฟล์ต่อไป", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 6c21026bdbd0e4..ba5395b7bd3d0f 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -163,7 +163,6 @@ "dismissable_banner.explore_tags": "suni ni la jan mute li lukin e toki pi toki ni. jan mute li kepeken toki la toki ni li lon sewi.", "dismissable_banner.public_timeline": "toki ni li sin. jan li pali e toki ni la jan ante mute pi ma {domain} li kute e jan ni.", "domain_block_modal.block": "o weka e ma", - "domain_block_modal.you_will_lose_followers": "ma ni la jan alasa ale sina li weka", "domain_block_modal.you_wont_see_posts": "sina ken ala lukin e toki tan jan pi ma ni", "domain_pill.server": "ma", "domain_pill.username": "nimi jan", @@ -252,8 +251,6 @@ "keyboard_shortcuts.toot": "o toki", "keyboard_shortcuts.up": "o tawa sewi lon lipu", "lightbox.close": "o pini", - "lightbox.compress": "o lili e sitelen", - "lightbox.expand": "o suli e sitelen", "lightbox.next": "sinpin", "lightbox.previous": "monsi", "link_preview.author": "tan {name}", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index d4d7d3d113929c..6feae5d137d8ef 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Aşırı istek gönderildi", "alert.unexpected.message": "Beklenmedik bir hata oluştu.", "alert.unexpected.title": "Hay aksi!", + "alt_text_badge.title": "Alternatif metin", "announcement.announcement": "Duyuru", "attachments_list.unprocessed": "(işlenmemiş)", "audio.hide": "Sesi gizle", @@ -221,7 +222,8 @@ "domain_block_modal.they_cant_follow": "Bu sunucudan hiç kimse sizi takip edemez.", "domain_block_modal.they_wont_know": "Engellendiklerini bilmeyecekler.", "domain_block_modal.title": "Alan adını engelle?", - "domain_block_modal.you_will_lose_followers": "Bu sunucudaki tüm takipçileriniz kaldırılacaktır.", + "domain_block_modal.you_will_lose_num_followers": "{followersCount, plural, one {{followersCountDisplay} takipçi} other {{followersCountDisplay} takipçi}} ve {followingCount, plural, one {{followingCountDisplay} takip ettiğiniz kişi} other {{followingCountDisplay} takip ettiğiniz kişi}} kaybedeceksiniz.", + "domain_block_modal.you_will_lose_relationships": "Bu sunucudaki tüm takip edenleri ve takip ettiklerinizi kaybedeceksiniz.", "domain_block_modal.you_wont_see_posts": "Bu sunucudaki kullanıcılardan gelen gönderileri veya bildirimleri göremezsiniz.", "domain_pill.activitypub_lets_connect": "Sadece Mastodon üzerindeki değil, diğer sosyal uygulamalardaki kişilerle de bağlantı kurmanıza ve etkileşmenize olanak sağlar.", "domain_pill.activitypub_like_language": "ActivityPub, Mastodon'un diğer sosyal ağlarla konuşmak için kullandığı dil gibidir.", @@ -432,10 +434,10 @@ "keyboard_shortcuts.unfocus": "Aramada bir gönderiye odaklanmamak için", "keyboard_shortcuts.up": "Listede yukarıya çıkmak için", "lightbox.close": "Kapat", - "lightbox.compress": "Resim görüntüleme kutusunu sıkıştır", - "lightbox.expand": "Resim görüntüleme kutusunu genişlet", "lightbox.next": "Sonraki", "lightbox.previous": "Önceki", + "lightbox.zoom_in": "Özgün boyuta dön", + "lightbox.zoom_out": "Sığacak şekilde boyutla", "limited_account_hint.action": "Yine de profili göster", "limited_account_hint.title": "Bu profil {domain} moderatörleri tarafından gizlendi.", "link_preview.author": "Yazar: {name}", diff --git a/app/javascript/mastodon/locales/tt.json b/app/javascript/mastodon/locales/tt.json index 01429f9431b132..08bb7979a10d85 100644 --- a/app/javascript/mastodon/locales/tt.json +++ b/app/javascript/mastodon/locales/tt.json @@ -271,8 +271,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": "Барыбер профильне күрсәтергә", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index a1d3a872dfd91a..1753d0bebe44df 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Швидкість обмежена", "alert.unexpected.message": "Сталася неочікувана помилка.", "alert.unexpected.title": "Ой!", + "alt_text_badge.title": "Альтернативний текст", "announcement.announcement": "Оголошення", "attachments_list.unprocessed": "(не оброблено)", "audio.hide": "Сховати аудіо", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Ви втратите {followersCount, plural, one {{followersCountDisplay} підписника} few {{followersCountDisplay} підписника} many {{followersCountDisplay} підписників} other {{followersCountDisplay} підписника}} та {followingCount, plural, one {{followingCountDisplay} особу, за якою ви стежите} few {{followingCountDisplay} особи, за якими ви стежите} many {{followingCountDisplay} осіб, за якими ви стежите} other {{followingCountDisplay} особу, за якою ви стежите}}.", + "domain_block_modal.you_will_lose_relationships": "Ви втратите всіх підписників і людей, на яких ви підписані.", "domain_block_modal.you_wont_see_posts": "Ви не бачитимете дописів і сповіщень від користувачів на цьому сервері.", "domain_pill.activitypub_lets_connect": "Це дозволяє вам спілкуватися та взаємодіяти з людьми не лише на Mastodon, але й у різних соціальних застосунках.", "domain_pill.activitypub_like_language": "ActivityPub - це як мова, якою Mastodon розмовляє з іншими соціальними мережами.", @@ -432,10 +434,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}", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 9fcd00ddc7c56a..770dcbaef55bde 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -3,7 +3,7 @@ "about.contact": "Liên lạc:", "about.disclaimer": "Mastodon là phần mềm tự do nguồn mở của Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Lý do không được cung cấp", - "about.domain_blocks.preamble": "Mastodon cho phép bạn tương tác nội dung và giao tiếp với mọi người từ bất kỳ máy chủ nào khác trong mạng liên hợp. Còn máy chủ này có những ngoại lệ riêng.", + "about.domain_blocks.preamble": "Mastodon cho phép bạn đọc nội dung và giao tiếp với mọi người từ bất kỳ máy chủ nào. Còn đây là những ngoại lệ trên máy chủ này.", "about.domain_blocks.silenced.explanation": "Nói chung, bạn sẽ không thấy người và nội dung từ máy chủ này, trừ khi bạn tự tìm kiếm hoặc tự theo dõi.", "about.domain_blocks.silenced.title": "Hạn chế", "about.domain_blocks.suspended.explanation": "Dữ liệu từ máy chủ này sẽ không được xử lý, lưu trữ hoặc trao đổi. Mọi tương tác hoặc giao tiếp với người từ máy chủ này đều bị cấm.", @@ -34,9 +34,9 @@ "account.follow_back": "Theo dõi lại", "account.followers": "Người theo dõi", "account.followers.empty": "Chưa có người theo dõi nào.", - "account.followers_counter": "{count, plural, other {{counter} người theo dõi}}", + "account.followers_counter": "{count, plural, other {{counter} Người theo dõi}}", "account.following": "Đang theo dõi", - "account.following_counter": "{count, plural, other {{counter} đang theo dõi}}", + "account.following_counter": "{count, plural, other {{counter} Đang theo dõi}}", "account.follows.empty": "Người này chưa theo dõi ai.", "account.go_to_profile": "Xem hồ sơ", "account.hide_reblogs": "Ẩn tút @{name} đăng lại", @@ -62,7 +62,7 @@ "account.requested_follow": "{name} yêu cầu theo dõi bạn", "account.share": "Chia sẻ @{name}", "account.show_reblogs": "Hiện tút do @{name} đăng lại", - "account.statuses_counter": "{count, plural, other {{counter} tút}}", + "account.statuses_counter": "{count, plural, other {{counter} Tút}}", "account.unblock": "Bỏ chặn @{name}", "account.unblock_domain": "Bỏ ẩn {domain}", "account.unblock_short": "Bỏ chặn", @@ -76,7 +76,7 @@ "admin.dashboard.monthly_retention": "Tỉ lệ người dùng ở lại sau khi đăng ký", "admin.dashboard.retention.average": "Trung bình", "admin.dashboard.retention.cohort": "Tháng đăng ký", - "admin.dashboard.retention.cohort_size": "Người mới", + "admin.dashboard.retention.cohort_size": "Số người", "admin.impact_report.instance_accounts": "Hồ sơ tài khoản này sẽ xóa", "admin.impact_report.instance_followers": "Người theo dõi của thành viên máy chủ sẽ mất", "admin.impact_report.instance_follows": "Người theo dõi người dùng của họ sẽ mất", @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Vượt giới hạn", "alert.unexpected.message": "Đã xảy ra lỗi không mong muốn.", "alert.unexpected.title": "Ốiii!", + "alt_text_badge.title": "Văn bản thay thế", "announcement.announcement": "Có gì mới?", "attachments_list.unprocessed": "(chưa xử lí)", "audio.hide": "Ẩn âm thanh", @@ -145,7 +146,7 @@ "community.column_settings.remote_only": "Chỉ người ở máy chủ khác", "compose.language.change": "Chọn ngôn ngữ tút", "compose.language.search": "Tìm ngôn ngữ...", - "compose.published.body": "Đã đăng.", + "compose.published.body": "Tút đã được đăng.", "compose.published.open": "Xem lại", "compose.saved.body": "Đã lưu tút.", "compose_form.direct_message_warning_learn_more": "Tìm hiểu thêm", @@ -154,8 +155,8 @@ "compose_form.lock_disclaimer": "Tài khoản của bạn không {locked}. Bất cứ ai cũng có thể theo dõi và xem tút riêng tư của bạn.", "compose_form.lock_disclaimer.lock": "khóa", "compose_form.placeholder": "Bạn đang nghĩ gì?", - "compose_form.poll.duration": "Hết hạn vào", - "compose_form.poll.multiple": "Nhiều lựa chọn", + "compose_form.poll.duration": "Hết hạn sau", + "compose_form.poll.multiple": "Chọn nhiều", "compose_form.poll.option_placeholder": "Lựa chọn {number}", "compose_form.poll.single": "Chọn một", "compose_form.poll.switch_to_multiple": "Có thể chọn nhiều lựa chọn", @@ -170,31 +171,31 @@ "compose_form.spoiler_placeholder": "Nội dung ẩn (tùy chọn)", "confirmation_modal.cancel": "Hủy bỏ", "confirmations.block.confirm": "Chặn", - "confirmations.delete.confirm": "Xóa bỏ", - "confirmations.delete.message": "Bạn thật sự muốn xóa tút này?", - "confirmations.delete.title": "Xóa tút?", - "confirmations.delete_list.confirm": "Xóa bỏ", - "confirmations.delete_list.message": "Bạn thật sự muốn xóa vĩnh viễn danh sách này?", - "confirmations.delete_list.title": "Xóa danh sách?", + "confirmations.delete.confirm": "Vẫn xóa", + "confirmations.delete.message": "Bạn có chắc muốn xóa tút này?", + "confirmations.delete.title": "Xóa tút", + "confirmations.delete_list.confirm": "Vẫn xóa", + "confirmations.delete_list.message": "Bạn có chắc muốn xóa vĩnh viễn danh sách này?", + "confirmations.delete_list.title": "Xóa danh sách", "confirmations.discard_edit_media.confirm": "Bỏ qua", "confirmations.discard_edit_media.message": "Bạn chưa lưu thay đổi đối với phần mô tả hoặc bản xem trước của media, vẫn bỏ luôn?", "confirmations.edit.confirm": "Sửa", "confirmations.edit.message": "Nội dung tút cũ sẽ bị ghi đè, bạn có tiếp tục?", - "confirmations.edit.title": "Viết đè lên tút cũ?", + "confirmations.edit.title": "Ghi đè lên tút cũ", "confirmations.logout.confirm": "Đăng xuất", - "confirmations.logout.message": "Bạn có thật sự muốn thoát?", - "confirmations.logout.title": "Đăng xuất?", + "confirmations.logout.message": "Bạn có chắc muốn thoát?", + "confirmations.logout.title": "Đăng xuất", "confirmations.mute.confirm": "Ẩn", "confirmations.redraft.confirm": "Xóa & viết lại", - "confirmations.redraft.message": "Bạn thật sự muốn xóa tút và viết lại? Điều này sẽ xóa mất những lượt thích và đăng lại của tút, cũng như những trả lời sẽ không còn nội dung gốc.", - "confirmations.redraft.title": "Xóa & viết lại?", + "confirmations.redraft.message": "Điều này sẽ khiến những lượt thích và đăng lại của tút bị mất, cũng như những trả lời sẽ không còn nội dung gốc.", + "confirmations.redraft.title": "Xóa & viết lại", "confirmations.reply.confirm": "Trả lời", "confirmations.reply.message": "Nội dung bạn đang soạn thảo sẽ bị ghi đè, bạn có tiếp tục?", - "confirmations.reply.title": "Viết đè lên tút cũ?", + "confirmations.reply.title": "Ghi đè lên tút cũ", "confirmations.unfollow.confirm": "Bỏ theo dõi", - "confirmations.unfollow.message": "Bạn thật sự muốn bỏ theo dõi {name}?", - "confirmations.unfollow.title": "Bỏ theo dõi?", - "content_warning.hide": "Ẩn tút", + "confirmations.unfollow.message": "Bạn có chắc muốn bỏ theo dõi {name}?", + "confirmations.unfollow.title": "Bỏ theo dõi", + "content_warning.hide": "Ẩn lại", "content_warning.show": "Nhấn để xem", "conversation.delete": "Xóa tin nhắn này", "conversation.mark_as_read": "Đánh dấu là đã đọc", @@ -221,21 +222,22 @@ "domain_block_modal.they_cant_follow": "Không ai trên máy chủ này có thể theo dõi bạn.", "domain_block_modal.they_wont_know": "Họ sẽ không biết đã bị bạn chặn.", "domain_block_modal.title": "Chặn máy chủ?", - "domain_block_modal.you_will_lose_followers": "Những người theo dõi bạn ở máy chủ này sẽ bị xóa.", + "domain_block_modal.you_will_lose_num_followers": "Bạn sẽ mất {followersCount, plural, other {{followersCountDisplay} người theo dõi}} và {followingCount, plural, other {{followingCountDisplay} người bạn theo dõi}}.", + "domain_block_modal.you_will_lose_relationships": "Bạn sẽ mất tất cả người theo dõi và những người bạn theo dõi từ máy chủ này.", "domain_block_modal.you_wont_see_posts": "Bạn sẽ không thấy tút hoặc thông báo từ thành viên máy chủ này.", "domain_pill.activitypub_lets_connect": "Nó cho phép bạn kết nối và tương tác với mọi người không chỉ trên Mastodon mà còn trên các ứng dụng xã hội khác.", "domain_pill.activitypub_like_language": "ActivityPub giống như ngôn ngữ Mastodon giao tiếp với các mạng xã hội khác.", "domain_pill.server": "Máy chủ", "domain_pill.their_handle": "Địa chỉ Mastodon:", - "domain_pill.their_server": "Ngôi nhà kỹ thuật số, nơi lưu giữ tút của ai đó.", - "domain_pill.their_username": "Danh tính duy nhất của họ trên máy chủ này. Có thể có tên người dùng giống nhau trên các máy chủ khác.", + "domain_pill.their_server": "Nơi lưu trữ tút của người này.", + "domain_pill.their_username": "Độc nhất trên máy chủ này. Những máy chủ khác có thể cũng có tên người dùng giống vậy.", "domain_pill.username": "Tên người dùng", "domain_pill.whats_in_a_handle": "Địa chỉ Mastodon là gì?", "domain_pill.who_they_are": "Vì địa chỉ Mastodon cho biết một người là ai và họ ở đâu, nên bạn có thể tương tác với mọi người trên các nền tảng có .", "domain_pill.who_you_are": "Vì địa chỉ Mastodon cho biết bạn là ai và bạn ở đâu, nên bạn có thể tương tác với mọi người trên các nền tảng có .", "domain_pill.your_handle": "Địa chỉ Mastodon của bạn:", - "domain_pill.your_server": "Ngôi nhà kỹ thuật số, nơi lưu giữ tút của bạn. Không thích ở đây? Chuyển sang máy chủ khác và mang theo người theo dõi của bạn.", - "domain_pill.your_username": "Danh tính duy nhất của bạn trên máy chủ này. Có thể có tên người dùng giống bạn trên các máy chủ khác.", + "domain_pill.your_server": "Nơi lưu trữ tút của bạn. Không thích ở đây? Chuyển sang máy chủ khác và giữ nguyên người theo dõi của bạn.", + "domain_pill.your_username": "Chỉ riêng bạn trên máy chủ này. Những máy chủ khác có thể cũng có tên người dùng giống vậy.", "embed.instructions": "Sao chép đoạn mã dưới đây và chèn vào trang web của bạn.", "embed.preview": "Nó sẽ hiển thị như vầy:", "emoji_button.activity": "Hoạt động", @@ -322,7 +324,7 @@ "follow_suggestions.hints.most_interactions": "Người này đang thu hút sự chú ý trên {domain}.", "follow_suggestions.hints.similar_to_recently_followed": "Người này có nét giống những người mà bạn theo dõi gần đây.", "follow_suggestions.personalized_suggestion": "Gợi ý cá nhân hóa", - "follow_suggestions.popular_suggestion": "Những người nổi tiếng", + "follow_suggestions.popular_suggestion": "Người nổi tiếng", "follow_suggestions.popular_suggestion_longer": "Nổi tiếng trên {domain}", "follow_suggestions.similar_to_recently_followed_longer": "Tương tự những người mà bạn theo dõi gần đây", "follow_suggestions.view_all": "Xem tất cả", @@ -359,7 +361,7 @@ "hints.profiles.see_more_followers": "Xem thêm người theo dõi ở {domain}", "hints.profiles.see_more_follows": "Xem thêm người mà người này theo dõi ở {domain}", "hints.profiles.see_more_posts": "Xem thêm tút ở {domain}", - "hints.threads.replies_may_be_missing": "Lượt trả lời trên máy chủ khác có thể không đầy đủ.", + "hints.threads.replies_may_be_missing": "Lượt trả lời từ máy chủ khác có thể không đầy đủ.", "hints.threads.see_more": "Xem thêm ở {domain}", "home.column_settings.show_reblogs": "Hiện những lượt đăng lại", "home.column_settings.show_replies": "Hiện những tút dạng trả lời", @@ -432,12 +434,12 @@ "keyboard_shortcuts.unfocus": "đưa con trỏ ra khỏi ô soạn thảo hoặc ô tìm kiếm", "keyboard_shortcuts.up": "di chuyển lên trên danh sách", "lightbox.close": "Đóng", - "lightbox.compress": "Thu nhỏ hình", - "lightbox.expand": "Phóng to hình", "lightbox.next": "Tiếp", "lightbox.previous": "Trước", + "lightbox.zoom_in": "Kích cỡ gốc", + "lightbox.zoom_out": "Vừa màn hình", "limited_account_hint.action": "Vẫn cứ xem", - "limited_account_hint.title": "Người này đã bị ẩn bởi quản trị viên của {domain}.", + "limited_account_hint.title": "Người này đã bị ẩn bởi quản trị viên {domain}.", "link_preview.author": "Bởi {name}", "link_preview.more_from_author": "Thêm từ {name}", "link_preview.shares": "{count, plural, other {{counter} lượt chia sẻ}}", @@ -462,7 +464,7 @@ "mute_modal.hide_from_notifications": "Ẩn thông báo", "mute_modal.hide_options": "Tùy chọn ẩn", "mute_modal.indefinite": "Cho tới khi bỏ ẩn", - "mute_modal.show_options": "Hiển thị tùy chọn", + "mute_modal.show_options": "Thêm tùy chọn", "mute_modal.they_can_mention_and_follow": "Họ có thể nhắc đến và theo dõi bạn, nhưng bạn không thấy họ.", "mute_modal.they_wont_know": "Họ sẽ không biết đã bị bạn ẩn.", "mute_modal.title": "Ẩn người này?", @@ -480,7 +482,7 @@ "navigation_bar.domain_blocks": "Máy chủ đã ẩn", "navigation_bar.explore": "Xu hướng", "navigation_bar.favourites": "Tút thích", - "navigation_bar.filters": "Bộ lọc từ ngữ", + "navigation_bar.filters": "Từ khóa đã lọc", "navigation_bar.follow_requests": "Yêu cầu theo dõi", "navigation_bar.followed_tags": "Hashtag theo dõi", "navigation_bar.follows_and_followers": "Quan hệ", @@ -533,7 +535,7 @@ "notification.relationships_severance_event.learn_more": "Tìm hiểu thêm", "notification.relationships_severance_event.user_domain_block": "Bạn đã chặn {target}, xóa {followersCount} người theo dõi bạn và {followingCount, plural, other {# người}} theo dõi bạn.", "notification.status": "{name} đăng tút mới", - "notification.update": "{name} đã sửa tút", + "notification.update": "{name} cập nhật tút", "notification_requests.accept": "Chấp nhận", "notification_requests.accept_multiple": "{count, plural, other {Duyệt # yêu cầu…}}", "notification_requests.confirm_accept_multiple.button": "{count, plural, other {Yêu cầu cần duyệt}}", @@ -554,8 +556,8 @@ "notification_requests.title": "Thông báo đã lọc", "notification_requests.view": "Hiện thông báo", "notifications.clear": "Xóa hết thông báo", - "notifications.clear_confirmation": "Bạn thật sự muốn xóa vĩnh viễn tất cả thông báo của mình?", - "notifications.clear_title": "Xóa hết thông báo?", + "notifications.clear_confirmation": "Bạn có chắc muốn xóa vĩnh viễn tất cả thông báo của mình?", + "notifications.clear_title": "Xóa toàn bộ thông báo", "notifications.column_settings.admin.report": "Báo cáo mới:", "notifications.column_settings.admin.sign_up": "Người mới tham gia:", "notifications.column_settings.alert": "Báo trên máy tính", @@ -601,8 +603,8 @@ "notifications.policy.filter_not_followers_title": "Những người không theo dõi bạn", "notifications.policy.filter_not_following_hint": "Cho tới khi bạn duyệt họ", "notifications.policy.filter_not_following_title": "Những người bạn không theo dõi", - "notifications.policy.filter_private_mentions_hint": "Được lọc trừ khi nó trả lời lượt nhắc từ bạn hoặc nếu bạn theo dõi người gửi", - "notifications.policy.filter_private_mentions_title": "Lượt nhắc riêng tư không được yêu cầu", + "notifications.policy.filter_private_mentions_hint": "Trừ khi nó trả lời lượt nhắc từ bạn hoặc nếu bạn có theo dõi người gửi", + "notifications.policy.filter_private_mentions_title": "Lượt nhắn riêng không mong muốn", "notifications.policy.title": "Quản lý thông báo từ…", "notifications_permission_banner.enable": "Cho phép thông báo trên màn hình", "notifications_permission_banner.how_to_control": "Hãy bật thông báo trên màn hình để không bỏ lỡ những thông báo từ Mastodon. Một khi đã bật, bạn có thể lựa chọn từng loại thông báo khác nhau thông qua {icon} nút bên dưới.", @@ -621,7 +623,7 @@ "onboarding.profile.display_name_hint": "Tên đầy đủ hoặc biệt danh đều được…", "onboarding.profile.lead": "Bạn có thể cài đặt lại trong phần cài đặt, nơi thậm chí còn có nhiều tùy chọn hơn.", "onboarding.profile.note": "Giới thiệu", - "onboarding.profile.note_hint": "Bạn có thể @nhắnriêng ai đó hoặc #hashtags…", + "onboarding.profile.note_hint": "Bạn có thể @aiđó hoặc #hashtags…", "onboarding.profile.save_and_continue": "Lưu và tiếp tục", "onboarding.profile.title": "Thiết lập hồ sơ", "onboarding.profile.upload_avatar": "Tải lên ảnh đại diện", @@ -657,7 +659,7 @@ "poll.voted": "Bạn đã bình chọn rồi", "poll.votes": "{votes, plural, other {# lượt bình chọn}}", "poll_button.add_poll": "Tạo bình chọn", - "poll_button.remove_poll": "Hủy cuộc bình chọn", + "poll_button.remove_poll": "Xóa bình chọn", "privacy.change": "Chọn kiểu tút", "privacy.direct.long": "Những người được nhắc trong tút", "privacy.direct.short": "Người cụ thể", @@ -713,7 +715,7 @@ "report.reasons.other": "Một lý do khác", "report.reasons.other_description": "Vấn đề không nằm trong những mục trên", "report.reasons.spam": "Đây là spam", - "report.reasons.spam_description": "Liên kết độc hại, tạo tương tác giả hoặc trả lời lặp đi lặp lại", + "report.reasons.spam_description": "Liên kết độc hại, giả tương tác hoặc trả lời lặp đi lặp lại", "report.reasons.violation": "Vi phạm nội quy máy chủ", "report.reasons.violation_description": "Bạn nhận thấy nó vi phạm nội quy máy chủ", "report.rules.subtitle": "Chọn tất cả những gì phù hợp", @@ -738,7 +740,7 @@ "report_notification.categories.violation": "Vi phạm nội quy", "report_notification.categories.violation_sentence": "vi phạm nội quy", "report_notification.open": "Mở báo cáo", - "search.no_recent_searches": "Không có tìm kiếm gần đây", + "search.no_recent_searches": "Gần đây chưa tìm gì", "search.placeholder": "Tìm kiếm", "search.quick_action.account_search": "Người có tên {x}", "search.quick_action.go_to_account": "Xem trang {x}", @@ -748,12 +750,12 @@ "search.search_or_paste": "Tìm kiếm hoặc nhập URL", "search_popout.full_text_search_disabled_message": "Không khả dụng trên {domain}.", "search_popout.full_text_search_logged_out_message": "Cần đăng nhập trước.", - "search_popout.language_code": "Mã ngôn ngữ ISO", - "search_popout.options": "Tùy chọn tìm kiếm", + "search_popout.language_code": "mã ngôn ngữ ISO", + "search_popout.options": "Tìm nâng cao", "search_popout.quick_actions": "Thao tác nhanh", - "search_popout.recent": "Tìm kiếm gần đây", + "search_popout.recent": "Lượt tìm gần đây", "search_popout.specific_date": "ngày cụ thể", - "search_popout.user": "mọi người", + "search_popout.user": "địa chỉ Mastodon", "search_results.accounts": "Mọi người", "search_results.all": "Toàn bộ", "search_results.hashtags": "Hashtag", @@ -778,7 +780,7 @@ "status.bookmark": "Lưu", "status.cancel_reblog_private": "Hủy đăng lại", "status.cannot_reblog": "Không thể đăng lại tút này", - "status.continued_thread": "Tiếp tục trong chủ đề", + "status.continued_thread": "Tiếp tục chủ đề", "status.copy": "Sao chép URL", "status.delete": "Xóa", "status.detailed_status": "Xem chi tiết thêm", @@ -787,9 +789,9 @@ "status.edit": "Sửa", "status.edited": "Sửa lần cuối {date}", "status.edited_x_times": "Đã sửa {count, plural, other {{count} lần}}", - "status.embed": "Lấy mã nhúng", + "status.embed": "Nhúng", "status.favourite": "Thích", - "status.favourites": "{count, plural, other {lượt thích}}", + "status.favourites": "{count, plural, other {thích}}", "status.filter": "Lọc tút này", "status.history.created": "{name} đăng {date}", "status.history.edited": "{name} đã sửa {date}", @@ -812,7 +814,7 @@ "status.reblogs.empty": "Tút này chưa có ai đăng lại. Nếu có, nó sẽ hiển thị ở đây.", "status.redraft": "Xóa và viết lại", "status.remove_bookmark": "Bỏ lưu", - "status.replied_in_thread": "Trả lời trong chủ đề", + "status.replied_in_thread": "Trả lời thảo luận", "status.replied_to": "Trả lời {name}", "status.reply": "Trả lời", "status.replyAll": "Trả lời", @@ -850,6 +852,11 @@ "upload_error.poll": "Không cho phép đính kèm tập tin.", "upload_form.audio_description": "Mô tả cho người mất thính giác", "upload_form.description": "Mô tả cho người khiếm thị", + "upload_form.drag_and_drop.instructions": "Để chọn tập tin đính kèm, hãy nhấn phím cách hoặc phím Enter. Trong khi kéo, sử dụng các phím mũi tên để di chuyển tập tin đính kèm theo bất kỳ hướng nào. Nhấn phím cách hoặc phím Enter một lần nữa để thả tập tin đính kèm vào vị trí mới hoặc nhấn phím thoát để hủy.", + "upload_form.drag_and_drop.on_drag_cancel": "Kéo thả đã bị hủy bỏ. Tập tin đính kèm {item} bị bỏ qua.", + "upload_form.drag_and_drop.on_drag_end": "Tập tin đính kèm {item} bị bỏ qua.", + "upload_form.drag_and_drop.on_drag_over": "Tập tin đính kèm {item} đã bị dời.", + "upload_form.drag_and_drop.on_drag_start": "Đã chọn tập tin đính kèm {item}.", "upload_form.edit": "Biên tập", "upload_form.thumbnail": "Đổi ảnh thumbnail", "upload_form.video_description": "Mô tả cho người mất thị lực hoặc không thể nghe", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 6df3cde2085ab6..0a4505d4ee5482 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "频率受限", "alert.unexpected.message": "发生了意外错误。", "alert.unexpected.title": "哎呀!", + "alt_text_badge.title": "替代文本", "announcement.announcement": "公告", "attachments_list.unprocessed": "(未处理)", "audio.hide": "隐藏音频", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "你将失去 {followersCount, plural, other {{followersCountDisplay} 名关注者}}和 {followingCount, plural, other {{followingCountDisplay} 名关注}}。", + "domain_block_modal.you_will_lose_relationships": "你将失去在此实例上的所有关注和关注者。", "domain_block_modal.you_wont_see_posts": "你将不会看到此服务器上用户的嘟文或通知。", "domain_pill.activitypub_lets_connect": "它让你不仅能与Mastodon上的人交流互动,还能与其它不同社交应用上的人联系。", "domain_pill.activitypub_like_language": "ActivityPub就像Mastodon与其它社交网络交流时使用的语言。", @@ -432,10 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "投票中不允许上传文件。", "upload_form.audio_description": "为听障人士添加文字描述", "upload_form.description": "为视觉障碍人士添加文字说明", + "upload_form.drag_and_drop.instructions": "要选中某个媒体附件,请按空格键或回车键。在拖拽时,使用方向键将媒体附件移动到任何给定方向。再次按空格键或回车键可将媒体附件放置在新位置,或按 Esc 键取消。", + "upload_form.drag_and_drop.on_drag_cancel": "拖拽已终止。媒体附件 {item} 已被丢弃。", + "upload_form.drag_and_drop.on_drag_end": "媒体附件 {item} 已被丢弃。", + "upload_form.drag_and_drop.on_drag_over": "媒体附件 {item} 已被移动。", + "upload_form.drag_and_drop.on_drag_start": "已选中媒体附件 {item}。", "upload_form.edit": "编辑", "upload_form.thumbnail": "更改缩略图", "upload_form.video_description": "为听障人士和视障人士添加文字描述", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 6fc1b9d2673a3d..a081e5589706ff 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -208,7 +208,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 與其他社交網絡溝通所用的語言。", @@ -398,8 +397,6 @@ "keyboard_shortcuts.unfocus": "把標示移離文字輸入和搜索", "keyboard_shortcuts.up": "在列表往上移動", "lightbox.close": "關閉", - "lightbox.compress": "縮小檢視", - "lightbox.expand": "擴大檢視", "lightbox.next": "下一頁", "lightbox.previous": "上一頁", "limited_account_hint.action": "一律顯示個人檔案", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index d69f54f7c8b984..2047a69f44b8af 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "已限速", "alert.unexpected.message": "發生非預期的錯誤。", "alert.unexpected.title": "哎呀!", + "alt_text_badge.title": "ALT 說明文字", "announcement.announcement": "公告", "attachments_list.unprocessed": "(未經處理)", "audio.hide": "隱藏音訊", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "您將會失去 {followersCount, plural, other {{followersCountDisplay} 個跟隨者}} 與 {followingCount, plural, other {{followingCountDisplay} 個您跟隨之帳號}}.", + "domain_block_modal.you_will_lose_relationships": "您將失去所有的跟隨者與您自此伺服器跟隨之帳號。", "domain_block_modal.you_wont_see_posts": "您不會見到來自此伺服器使用者之任何嘟文或推播通知。", "domain_pill.activitypub_lets_connect": "它使您能於 Mastodon 及其他不同的社群應用程式與人連結及互動。", "domain_pill.activitypub_like_language": "ActivityPub 像是 Mastodon 與其他社群網路溝通時所用的語言。", @@ -432,10 +434,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}", @@ -850,6 +852,11 @@ "upload_error.poll": "不允許於投票時上傳檔案。", "upload_form.audio_description": "為聽障人士增加文字說明", "upload_form.description": "為視障人士增加文字說明", + "upload_form.drag_and_drop.instructions": "請按空白鍵或 Enter 鍵取多媒體附加檔案。使用方向鍵移動多媒體附加檔案。按下空白鍵或 Enter 鍵於新位置放置多媒體附加檔案,或按下 ESC 鍵取消。", + "upload_form.drag_and_drop.on_drag_cancel": "移動已取消。多媒體附加檔案 {item} 已被放置。", + "upload_form.drag_and_drop.on_drag_end": "多媒體附加檔案 {item} 已被放置。", + "upload_form.drag_and_drop.on_drag_over": "多媒體附加檔案 {item} 已被移動。", + "upload_form.drag_and_drop.on_drag_start": "多媒體附加檔案 {item} 已被選取。", "upload_form.edit": "編輯", "upload_form.thumbnail": "更改預覽圖", "upload_form.video_description": "為聽障或視障人士增加文字說明", diff --git a/app/javascript/mastodon/models/media_attachment.ts b/app/javascript/mastodon/models/media_attachment.ts new file mode 100644 index 00000000000000..0e5b9ab555e354 --- /dev/null +++ b/app/javascript/mastodon/models/media_attachment.ts @@ -0,0 +1,2 @@ +// Temporary until we type it correctly +export type MediaAttachment = Immutable.Map; diff --git a/app/javascript/mastodon/models/status.ts b/app/javascript/mastodon/models/status.ts index 3900df4e38e267..7f9144280cfc98 100644 --- a/app/javascript/mastodon/models/status.ts +++ b/app/javascript/mastodon/models/status.ts @@ -10,3 +10,5 @@ export type Status = Immutable.Map; type CardShape = Required; export type Card = RecordOf; + +export type MediaAttachment = Immutable.Map; diff --git a/app/javascript/mastodon/reducers/notification_policy.ts b/app/javascript/mastodon/reducers/notification_policy.ts index ed912dde5d648a..a883f9c1eed5e2 100644 --- a/app/javascript/mastodon/reducers/notification_policy.ts +++ b/app/javascript/mastodon/reducers/notification_policy.ts @@ -2,7 +2,7 @@ import { createReducer, isAnyOf } from '@reduxjs/toolkit'; import { fetchNotificationPolicy, - decreasePendingNotificationsCount, + decreasePendingRequestsCount, updateNotificationsPolicy, } from 'mastodon/actions/notification_policies'; import type { NotificationPolicy } from 'mastodon/models/notification_policy'; @@ -10,10 +10,9 @@ import type { NotificationPolicy } from 'mastodon/models/notification_policy'; export const notificationPolicyReducer = createReducer(null, (builder) => { builder - .addCase(decreasePendingNotificationsCount, (state, action) => { + .addCase(decreasePendingRequestsCount, (state, action) => { if (state) { - state.summary.pending_notifications_count -= action.payload; - state.summary.pending_requests_count -= 1; + state.summary.pending_requests_count -= action.payload; } }) .addMatcher( diff --git a/app/javascript/mastodon/utils/debounce.ts b/app/javascript/mastodon/utils/debounce.ts new file mode 100644 index 00000000000000..224a5389844aba --- /dev/null +++ b/app/javascript/mastodon/utils/debounce.ts @@ -0,0 +1,23 @@ +import { debounce } from 'lodash'; + +import type { AppDispatch } from 'mastodon/store'; + +export const debounceWithDispatchAndArguments = ( + fn: (dispatch: AppDispatch, ...args: T[]) => void, + { delay = 100 }, +) => { + let argumentBuffer: T[] = []; + let dispatchBuffer: AppDispatch; + + const wrapped = debounce(() => { + const tmpBuffer = argumentBuffer; + argumentBuffer = []; + fn(dispatchBuffer, ...tmpBuffer); + }, delay); + + return (dispatch: AppDispatch, ...args: T[]) => { + dispatchBuffer = dispatch; + argumentBuffer.push(...args); + wrapped(); + }; +}; diff --git a/app/javascript/material-icons/400-20px/mood-fill.svg b/app/javascript/material-icons/400-20px/mood-fill.svg index ef72aeef6e8f83..febf012902326c 100644 --- a/app/javascript/material-icons/400-20px/mood-fill.svg +++ b/app/javascript/material-icons/400-20px/mood-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-20px/mood.svg b/app/javascript/material-icons/400-20px/mood.svg index abb44c466339b3..898697c4cdbd2e 100644 --- a/app/javascript/material-icons/400-20px/mood.svg +++ b/app/javascript/material-icons/400-20px/mood.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-20px/warning-fill.svg b/app/javascript/material-icons/400-20px/warning-fill.svg index 85dd926d3934ff..a4fc7efc5321d7 100644 --- a/app/javascript/material-icons/400-20px/warning-fill.svg +++ b/app/javascript/material-icons/400-20px/warning-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-20px/warning.svg b/app/javascript/material-icons/400-20px/warning.svg index d7d45a32112f5d..d67ad689aacef8 100644 --- a/app/javascript/material-icons/400-20px/warning.svg +++ b/app/javascript/material-icons/400-20px/warning.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/add_photo_alternate-fill.svg b/app/javascript/material-icons/400-24px/add_photo_alternate-fill.svg index deb3f8e0d970d9..932454ac6a87d4 100644 --- a/app/javascript/material-icons/400-24px/add_photo_alternate-fill.svg +++ b/app/javascript/material-icons/400-24px/add_photo_alternate-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/add_photo_alternate.svg b/app/javascript/material-icons/400-24px/add_photo_alternate.svg index 0ae8ad841cfe37..80cd74f85be621 100644 --- a/app/javascript/material-icons/400-24px/add_photo_alternate.svg +++ b/app/javascript/material-icons/400-24px/add_photo_alternate.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/bookmarks-fill.svg b/app/javascript/material-icons/400-24px/bookmarks-fill.svg index f5231f925a273b..62e78c6b57ee0a 100644 --- a/app/javascript/material-icons/400-24px/bookmarks-fill.svg +++ b/app/javascript/material-icons/400-24px/bookmarks-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/bookmarks.svg b/app/javascript/material-icons/400-24px/bookmarks.svg index 67dffd6857fcbc..6a1ea474c0303f 100644 --- a/app/javascript/material-icons/400-24px/bookmarks.svg +++ b/app/javascript/material-icons/400-24px/bookmarks.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/headphones-fill.svg b/app/javascript/material-icons/400-24px/headphones-fill.svg new file mode 100644 index 00000000000000..acc5e9236905cc --- /dev/null +++ b/app/javascript/material-icons/400-24px/headphones-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/headphones.svg b/app/javascript/material-icons/400-24px/headphones.svg new file mode 100644 index 00000000000000..788b32354b972f --- /dev/null +++ b/app/javascript/material-icons/400-24px/headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/manufacturing.svg b/app/javascript/material-icons/400-24px/manufacturing.svg index e0946f5ba52434..f19180759c0df3 100644 --- a/app/javascript/material-icons/400-24px/manufacturing.svg +++ b/app/javascript/material-icons/400-24px/manufacturing.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/quiet_time-fill.svg b/app/javascript/material-icons/400-24px/quiet_time-fill.svg index aed5740db3dc89..b4595fa04576bb 100644 --- a/app/javascript/material-icons/400-24px/quiet_time-fill.svg +++ b/app/javascript/material-icons/400-24px/quiet_time-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/quiet_time.svg b/app/javascript/material-icons/400-24px/quiet_time.svg index 552da6658dfefa..9295548f4e935f 100644 --- a/app/javascript/material-icons/400-24px/quiet_time.svg +++ b/app/javascript/material-icons/400-24px/quiet_time.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/share-fill.svg b/app/javascript/material-icons/400-24px/share-fill.svg index 5a6b0d0a8dd7d9..dd9fa89c6cea14 100644 --- a/app/javascript/material-icons/400-24px/share-fill.svg +++ b/app/javascript/material-icons/400-24px/share-fill.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/share.svg b/app/javascript/material-icons/400-24px/share.svg index 6876cd42dad667..23e617121cdafa 100644 --- a/app/javascript/material-icons/400-24px/share.svg +++ b/app/javascript/material-icons/400-24px/share.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/styles/mailer.scss b/app/javascript/styles/mailer.scss index e5d0c05f81d97b..f46160889a7a49 100644 --- a/app/javascript/styles/mailer.scss +++ b/app/javascript/styles/mailer.scss @@ -168,6 +168,7 @@ table + p { // Utility classes .email-w-full { + table-layout: fixed; width: 100%; } @@ -365,6 +366,7 @@ table + p { .email-header-card-banner-td { border-radius: 12px 12px 0 0; + width: 236px; height: 80px; background-color: #f3f2f5 !important; background-position: center !important; @@ -522,6 +524,7 @@ table + p { height: 40px; text-align: center; mso-padding-alt: 0 35px; + word-break: normal; } .email-btn-a { @@ -587,7 +590,10 @@ table + p { p { font-size: 14px; line-height: 20px; + margin-bottom: 20px; color: #17063b; + white-space: pre-wrap; + unicode-bidi: plaintext; } a { @@ -598,6 +604,21 @@ table + p { color: #563acc !important; } } + + .invisible { + font-size: 0; + line-height: 0; + display: inline-block; + width: 0; + height: 0; + position: absolute; + } + + .ellipsis { + &::after { + content: '…'; + } + } } .email-status-media { diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index a6dc888e57289a..498cfe96392bc8 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -81,6 +81,18 @@ outline: $ui-button-icon-focus-outline; } + &--dangerous { + background-color: var(--error-background-color); + color: var(--on-error-color); + + &:active, + &:focus, + &:hover { + background-color: var(--error-active-background-color); + transition: none; + } + } + &--destructive { &:active, &:focus, @@ -93,7 +105,7 @@ &:disabled, &.disabled { background-color: $ui-primary-color; - cursor: default; + cursor: not-allowed; } &.copyable { @@ -230,6 +242,7 @@ flex: 0 0 auto; a { + display: flex; color: inherit; text-decoration: none; } @@ -299,6 +312,10 @@ } } + &--with-counter { + padding-inline-end: 4px; + } + &__counter { display: block; width: auto; @@ -636,19 +653,39 @@ body > [data-popper-placement] { } &__uploads { - display: flex; - gap: 8px; padding: 0 12px; - flex-wrap: wrap; - align-self: stretch; - align-items: flex-start; - align-content: flex-start; - justify-content: center; + aspect-ratio: 3/2; + } + + .media-gallery { + gap: 8px; } &__upload { - flex: 1 1 0; - min-width: calc(50% - 8px); + position: relative; + cursor: grab; + + &.dragging { + opacity: 0; + } + + &.overlay { + height: 100%; + border-radius: 8px; + pointer-events: none; + } + + &__drag-handle { + position: absolute; + top: 50%; + inset-inline-start: 0; + transform: translateY(-50%); + color: $white; + background: transparent; + border: 0; + padding: 8px 3px; + cursor: grab; + } &__actions { display: flex; @@ -669,8 +706,7 @@ body > [data-popper-placement] { &__thumbnail { width: 100%; - height: 144px; - border-radius: 6px; + height: 100%; background-position: center; background-size: cover; background-repeat: no-repeat; @@ -1465,6 +1501,15 @@ body > [data-popper-placement] { } } + &__action-bar__button-wrapper { + flex-basis: 0; + flex-grow: 1; + + &:last-child { + flex-grow: 0; + } + } + &--first-in-thread { border-top: 1px solid var(--background-border-color); } @@ -2708,7 +2753,7 @@ a.account__display-name { &__main { box-sizing: border-box; width: 100%; - flex: 0 0 auto; + flex: 0 1 auto; display: flex; flex-direction: column; @@ -3477,12 +3522,14 @@ $ui-header-logo-wordmark-width: 99px; margin-top: 10px; margin-bottom: 10px; height: calc(100% - 20px); - overflow-y: auto; + overflow: hidden; display: flex; flex-direction: column; - & > a { - flex: 0 0 auto; + &__menu { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; } .logo { @@ -3493,6 +3540,36 @@ $ui-header-logo-wordmark-width: 99px; &__logo { margin-bottom: 12px; } + + @media screen and (height <= 710px) { + &__portal { + display: none; + } + } + + @media screen and (height <= 765px) { + &__portal .trends__item:nth-child(n + 3) { + display: none; + } + } + + @media screen and (height <= 820px) { + &__portal .trends__item:nth-child(n + 4) { + display: none; + } + } + + @media screen and (height <= 920px) { + .column-link.column-link--optional { + display: none; + } + } + + @media screen and (height <= 1040px) { + .list-panel { + display: none; + } + } } .navigation-panel, @@ -3856,22 +3933,6 @@ $ui-header-logo-wordmark-width: 99px; } } - @media screen and (height <= 810px) { - .trends__item:nth-of-type(3) { - display: none; - } - } - - @media screen and (height <= 720px) { - .trends__item:nth-of-type(2) { - display: none; - } - } - - @media screen and (height <= 670px) { - display: none; - } - .trends__item { border-bottom: 0; padding: 10px; @@ -5780,6 +5841,7 @@ a.status-card { .icon { width: 24px; height: 24px; + filter: var(--overlay-icon-shadow); } &:hover, @@ -5874,6 +5936,10 @@ a.status-card { .icon-button { color: $white; + .icon { + filter: var(--overlay-icon-shadow); + } + &:hover, &:focus, &:active { @@ -5932,6 +5998,7 @@ a.status-card { .media-modal__page-dot { flex: 0 0 auto; background-color: $white; + filter: var(--overlay-icon-shadow); opacity: 0.4; height: 6px; width: 6px; @@ -6208,6 +6275,14 @@ a.status-card { display: flex; gap: 16px; align-items: center; + + strong { + font-weight: 700; + } + } + + &--deemphasized { + color: $secondary-text-color; } &__icon { @@ -6889,7 +6964,7 @@ a.status-card { .media-gallery__actions { position: absolute; - bottom: 6px; + top: 6px; inset-inline-end: 6px; display: flex; gap: 2px; @@ -6912,17 +6987,17 @@ a.status-card { .media-gallery__item__badges { position: absolute; bottom: 8px; - inset-inline-start: 8px; + inset-inline-end: 8px; display: flex; gap: 2px; + pointer-events: none; } -.media-gallery__alt__label, -.media-gallery__gifv__label { - display: flex; - align-items: center; - justify-content: center; +.media-gallery__alt__label { + display: block; + text-align: center; color: $white; + border: 0; background: rgba($black, 0.65); backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%); padding: 3px 8px; @@ -6930,8 +7005,41 @@ a.status-card { font-size: 12px; font-weight: 700; z-index: 1; - pointer-events: none; line-height: 20px; + cursor: pointer; + pointer-events: auto; + + &--non-interactive { + pointer-events: none; + } +} + +.media-gallery__alt__popover { + background: rgba($black, 0.65); + backdrop-filter: blur(10px) saturate(180%) contrast(75%) brightness(70%); + border-radius: 4px; + box-shadow: var(--dropdown-shadow); + padding: 16px; + min-width: 16em; + min-height: 2em; + max-width: 22em; + max-height: 30em; + overflow-y: auto; + + h4 { + font-size: 15px; + line-height: 20px; + font-weight: 500; + color: $white; + margin-bottom: 8px; + } + + p { + font-size: 15px; + line-height: 20px; + color: rgba($white, 0.85); + white-space: pre-line; + } } .attachment-list { @@ -7004,35 +7112,35 @@ a.status-card { width: 100%; min-height: 64px; display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: 50% 50%; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; gap: 2px; &--layout-2 { - .media-gallery__item:nth-child(1) { + & > .media-gallery__item:nth-child(1) { border-end-end-radius: 0; border-start-end-radius: 0; } - .media-gallery__item:nth-child(2) { + & > .media-gallery__item:nth-child(2) { border-start-start-radius: 0; border-end-start-radius: 0; } } &--layout-3 { - .media-gallery__item:nth-child(1) { + & > .media-gallery__item:nth-child(1) { border-end-end-radius: 0; border-start-end-radius: 0; } - .media-gallery__item:nth-child(2) { + & > .media-gallery__item:nth-child(2) { border-start-start-radius: 0; border-end-start-radius: 0; border-end-end-radius: 0; } - .media-gallery__item:nth-child(3) { + & > .media-gallery__item:nth-child(3) { border-start-start-radius: 0; border-end-start-radius: 0; border-start-end-radius: 0; @@ -7040,26 +7148,26 @@ a.status-card { } &--layout-4 { - .media-gallery__item:nth-child(1) { + & > .media-gallery__item:nth-child(1) { border-end-end-radius: 0; border-start-end-radius: 0; border-end-start-radius: 0; } - .media-gallery__item:nth-child(2) { + & > .media-gallery__item:nth-child(2) { border-start-start-radius: 0; border-end-start-radius: 0; border-end-end-radius: 0; } - .media-gallery__item:nth-child(3) { + & > .media-gallery__item:nth-child(3) { border-start-start-radius: 0; border-start-end-radius: 0; border-end-start-radius: 0; border-end-end-radius: 0; } - .media-gallery__item:nth-child(4) { + & > .media-gallery__item:nth-child(4) { border-start-start-radius: 0; border-end-start-radius: 0; border-start-end-radius: 0; @@ -7074,6 +7182,9 @@ a.status-card { position: relative; border-radius: 8px; overflow: hidden; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; + z-index: 1; &--tall { grid-row: span 2; @@ -7082,15 +7193,44 @@ a.status-card { &--wide { grid-column: span 2; } + + &--square { + aspect-ratio: 1; + } + + &__overlay { + position: absolute; + top: 0; + inset-inline-start: 0; + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + width: 100%; + height: 100%; + pointer-events: none; + padding: 8px; + z-index: 1; + + &--corner { + align-items: flex-start; + justify-content: flex-end; + } + + .icon { + color: $white; + filter: var(--overlay-icon-shadow); + } + } } .media-gallery__item-thumbnail { - cursor: zoom-in; + cursor: pointer; display: block; text-decoration: none; color: $secondary-text-color; position: relative; - z-index: 1; + z-index: -1; &, img { @@ -7110,7 +7250,7 @@ a.status-card { position: absolute; top: 0; inset-inline-start: 0; - z-index: 0; + z-index: -2; background: $base-overlay-background; &--hidden { @@ -7123,22 +7263,16 @@ a.status-card { overflow: hidden; position: relative; width: 100%; + z-index: -1; } .media-gallery__item-gifv-thumbnail { - cursor: zoom-in; + cursor: pointer; height: 100%; object-fit: cover; width: 100%; } -.media-gallery__item-thumbnail-label { - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); - overflow: hidden; - position: absolute; -} - /* End Media Gallery */ .detailed, @@ -7161,6 +7295,8 @@ a.status-card { border-radius: 8px; padding-bottom: 44px; width: 100%; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; &.editable { border-radius: 0; @@ -7217,6 +7353,7 @@ a.status-card { .video-player__controls { padding-top: 10px; background: transparent; + z-index: 1; } } @@ -7230,19 +7367,18 @@ a.status-card { color: $white; display: flex; align-items: center; + outline: 1px solid var(--media-outline-color); + outline-offset: -1px; + z-index: 2; &.editable { border-radius: 0; height: 100% !important; } - &:focus { - outline: 0; - } - video { display: block; - z-index: 1; + z-index: -2; } &.fullscreen { @@ -7261,7 +7397,7 @@ a.status-card { &__controls { position: absolute; direction: ltr; - z-index: 2; + z-index: -1; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; @@ -7576,26 +7712,16 @@ a.status-card { } .account-gallery__container { - display: flex; - flex-wrap: wrap; - padding: 4px 2px; -} + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 2px; -.account-gallery__item { - border: 0; - box-sizing: border-box; - display: block; - position: relative; - border-radius: 4px; - overflow: hidden; - margin: 2px; + .media-gallery__item { + border-radius: 0; + } - &__icons { - position: absolute; - top: 50%; - inset-inline-start: 50%; - transform: translate(-50%, -50%); - font-size: 24px; + .load-more { + grid-column: span 3; } } diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss index 1621220ccb522e..d049b2456c1795 100644 --- a/app/javascript/styles/mastodon/dashboard.scss +++ b/app/javascript/styles/mastodon/dashboard.scss @@ -86,9 +86,7 @@ color: $primary-text-color; transition: all 100ms ease-in; font-size: 14px; - padding: 0 16px; - line-height: 36px; - height: 36px; + padding: 8px 16px; text-decoration: none; margin-bottom: 4px; diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 56f7b893f3953b..957a28352267e4 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -312,6 +312,10 @@ code { ul { columns: 2; + + @media screen and (max-width: $mobile-breakpoint) { + columns: 1; + } } } diff --git a/app/javascript/styles/mastodon/reset.scss b/app/javascript/styles/mastodon/reset.scss index 5a4152826d9e4b..fc0305baf3cdb4 100644 --- a/app/javascript/styles/mastodon/reset.scss +++ b/app/javascript/styles/mastodon/reset.scss @@ -56,7 +56,6 @@ table { @supports not selector(::-webkit-scrollbar) { html { scrollbar-color: $action-button-color var(--background-border-color); - scrollbar-width: thin; } } diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 2becd85bc667ef..af8ccf5b3839ef 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -359,6 +359,10 @@ a.table-action-link { @media screen and (max-width: $no-gap-breakpoint) { border-top: 1px solid var(--background-border-color); } + + &--no-toolbar { + border-top: 1px solid var(--background-border-color); + } } @media screen and (width <= 870px) { diff --git a/app/javascript/styles/mastodon/variables.scss b/app/javascript/styles/mastodon/variables.scss index 17442b9748b668..baaec5f58f5942 100644 --- a/app/javascript/styles/mastodon/variables.scss +++ b/app/javascript/styles/mastodon/variables.scss @@ -87,7 +87,7 @@ $media-modal-media-max-width: 100%; // put margins on top and bottom of image to avoid the screen covered by image. $media-modal-media-max-height: 80%; -$no-gap-breakpoint: 1207px; +$no-gap-breakpoint: 1175px; $mobile-breakpoint: 630px; $font-sans-serif: 'mastodon-font-sans-serif' !default; @@ -111,4 +111,9 @@ $font-monospace: 'mastodon-font-monospace' !default; --surface-variant-active-background-color: #{lighten($ui-base-color, 4%)}; --on-surface-color: #{transparentize($ui-base-color, 0.5)}; --avatar-border-radius: 8px; + --media-outline-color: #{rgba(#fcf8ff, 0.15)}; + --overlay-icon-shadow: drop-shadow(0 0 8px #{rgba($base-shadow-color, 0.25)}); + --error-background-color: #{darken($error-red, 16%)}; + --error-active-background-color: #{darken($error-red, 12%)}; + --on-error-color: #fff; } diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9b55b928404445..7f9429c5e4aa10 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -342,7 +342,15 @@ def in_reply_to_uri end def converted_text - linkify([@status_parser.title.presence, @status_parser.spoiler_text.presence, @status_parser.url || @status_parser.uri].compact.join("\n\n")) + [formatted_title, @status_parser.spoiler_text.presence, formatted_url].compact.join("\n\n") + end + + def formatted_title + "

#{@status_parser.title}

" if @status_parser.title.present? + end + + def formatted_url + linkify(@status_parser.url || @status_parser.uri) end def unsupported_media_type?(mime_type) diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 864328631755ff..23b44be372f28e 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -74,6 +74,18 @@ def replies_uri_for(target, page_params = nil) account_status_replies_url(target.account, target, page_params) end + def likes_uri_for(target) + raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local? + + account_status_likes_url(target.account, target) + end + + def shares_uri_for(target) + raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local? + + account_status_shares_url(target.account, target) + end + def followers_uri_for(target) target.local? ? account_followers_url(target) : target.followers_url.presence end diff --git a/app/lib/admin/system_check/software_version_check.rb b/app/lib/admin/system_check/software_version_check.rb index e142feddf0d000..e5cacfe354bbaf 100644 --- a/app/lib/admin/system_check/software_version_check.rb +++ b/app/lib/admin/system_check/software_version_check.rb @@ -14,14 +14,16 @@ def pass? def message if software_updates.any?(&:urgent?) Admin::SystemCheck::Message.new(:software_version_critical_check, nil, admin_software_updates_path, true) - else + elsif software_updates.any?(&:patch_type?) Admin::SystemCheck::Message.new(:software_version_patch_check, nil, admin_software_updates_path) + else + Admin::SystemCheck::Message.new(:software_version_check, nil, admin_software_updates_path) end end private def software_updates - @software_updates ||= SoftwareUpdate.pending_to_a.filter { |update| update.urgent? || update.patch_type? } + @software_updates ||= SoftwareUpdate.pending_to_a end end diff --git a/app/lib/permalink_redirector.rb b/app/lib/permalink_redirector.rb index f551f69db852f9..142a05d10d3daa 100644 --- a/app/lib/permalink_redirector.rb +++ b/app/lib/permalink_redirector.rb @@ -83,6 +83,6 @@ def second_segment end def path_segments - @path_segments ||= @path.delete_prefix('/deck').delete_prefix('/').split('/') + @path_segments ||= @path.split('?')[0].delete_prefix('/deck').delete_prefix('/').split('/') end end diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb index 72a2c2e64e144a..fffbbb3c6db2df 100644 --- a/app/mailers/admin_mailer.rb +++ b/app/mailers/admin_mailer.rb @@ -9,6 +9,8 @@ class AdminMailer < ApplicationMailer before_action :process_params before_action :set_instance + after_action :set_important_headers!, only: :new_critical_software_updates + default to: -> { @me.user_email } def new_report(report) @@ -56,12 +58,6 @@ def new_software_updates def new_critical_software_updates @software_updates = SoftwareUpdate.where(urgent: true).to_a.sort_by(&:gem_version) - headers( - 'Importance' => 'high', - 'Priority' => 'urgent', - 'X-Priority' => '1' - ) - locale_for_account(@me) do mail subject: default_i18n_subject(instance: @instance) end @@ -82,4 +78,12 @@ def process_params def set_instance @instance = Rails.configuration.x.local_domain end + + def set_important_headers! + headers( + 'Importance' => 'high', + 'Priority' => 'urgent', + 'X-Priority' => '1' + ) + end end diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 6b21b4bedde1a4..4c374f5d57fde1 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -13,12 +13,14 @@ class NotificationMailer < ApplicationMailer before_action :set_account, only: [:follow, :favourite, :reblog, :follow_request] after_action :set_list_headers! + before_deliver :verify_functional_user + default to: -> { email_address_with_name(@user.email, @me.username) } layout 'mailer' def mention - return unless @user.functional? && @status.present? + return if @status.blank? locale_for_account(@me) do mail subject: default_i18n_subject(name: @status.account.acct) @@ -26,15 +28,13 @@ def mention end def follow - return unless @user.functional? - locale_for_account(@me) do mail subject: default_i18n_subject(name: @account.acct) end end def favourite - return unless @user.functional? && @status.present? + return if @status.blank? locale_for_account(@me) do mail subject: default_i18n_subject(name: @account.acct) @@ -42,7 +42,7 @@ def favourite end def reblog - return unless @user.functional? && @status.present? + return if @status.blank? locale_for_account(@me) do mail subject: default_i18n_subject(name: @account.acct) @@ -50,8 +50,6 @@ def reblog end def follow_request - return unless @user.functional? - locale_for_account(@me) do mail subject: default_i18n_subject(name: @account.acct) end @@ -75,6 +73,10 @@ def set_account @account = @notification.from_account end + def verify_functional_user + throw(:abort) unless @user.functional? + end + def set_list_headers! headers( 'List-ID' => "<#{@type}.#{@me.username}.#{Rails.configuration.x.local_domain}>", diff --git a/app/models/account.rb b/app/models/account.rb index a9c9d91c89c78b..6b56fb0eae61ba 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -68,8 +68,8 @@ class Account < ApplicationRecord DEFAULT_FIELDS_SIZE = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i INSTANCE_ACTOR_ID = -99 - USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i - MENTION_RE = %r{(? { defined?(@registrations_mode) } @@ -97,7 +99,7 @@ class Form::AdminSettings validates :show_domain_blocks, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks) } validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) } validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) } - validates :site_short_description, length: { maximum: 200 }, if: -> { defined?(@site_short_description) } + validates :site_short_description, length: { maximum: DESCRIPTION_LIMIT }, if: -> { defined?(@site_short_description) } validates :status_page_url, url: true, allow_blank: true validate :validate_site_uploads diff --git a/app/models/notification.rb b/app/models/notification.rb index 44a43d2ece0c65..695f39a316f6ca 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -20,6 +20,7 @@ class Notification < ApplicationRecord self.inheritance_column = nil include Paginable + include Redisable LEGACY_TYPE_CLASS_MAP = { 'Mention' => :mention, @@ -30,7 +31,9 @@ class Notification < ApplicationRecord 'Poll' => :poll, }.freeze - GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog).freeze + # `set_group_key!` needs to be updated if this list changes + GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze + MAXIMUM_GROUP_SPAN_HOURS = 12 # Please update app/javascript/api_types/notification.ts if you change this PROPERTIES = { @@ -123,6 +126,30 @@ def target_status end end + def set_group_key! + return if filtered? || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(type) + + type_prefix = case type + when :favourite, :reblog + [type, target_status&.id].join('-') + when :follow + type + else + raise NotImplementedError + end + redis_key = "notif-group/#{account.id}/#{type_prefix}" + hour_bucket = activity.created_at.utc.to_i / 1.hour.to_i + + # Reuse previous group if it does not span too large an amount of time + previous_bucket = redis.get(redis_key).to_i + hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS + + # We do not concern ourselves with race conditions since we use hour buckets + redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) + + self.group_key = "#{type_prefix}-#{hour_bucket}" + end + class << self def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false) requested_types = if types.empty? diff --git a/app/presenters/domain_block_preview_presenter.rb b/app/presenters/domain_block_preview_presenter.rb new file mode 100644 index 00000000000000..601f76273ddcdf --- /dev/null +++ b/app/presenters/domain_block_preview_presenter.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class DomainBlockPreviewPresenter < ActiveModelSerializers::Model + attributes :followers_count, :following_count +end diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb index 52ffaf71709d27..0d8bac9a09009e 100644 --- a/app/serializers/activitypub/note_serializer.rb +++ b/app/serializers/activitypub/note_serializer.rb @@ -21,6 +21,8 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer has_many :virtual_tags, key: :tag has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local? + has_one :likes, serializer: ActivityPub::CollectionSerializer, if: :local? + has_one :shares, serializer: ActivityPub::CollectionSerializer, if: :local? has_many :poll_options, key: :one_of, if: :poll_and_not_multiple? has_many :poll_options, key: :any_of, if: :poll_and_multiple? @@ -76,6 +78,22 @@ def replies ) end + def likes + ActivityPub::CollectionPresenter.new( + id: ActivityPub::TagManager.instance.likes_uri_for(object), + type: :unordered, + size: object.favourites_count + ) + end + + def shares + ActivityPub::CollectionPresenter.new( + id: ActivityPub::TagManager.instance.shares_uri_for(object), + type: :unordered, + size: object.reblogs_count + ) + end + def language? object.language.present? end diff --git a/app/serializers/rest/domain_block_preview_serializer.rb b/app/serializers/rest/domain_block_preview_serializer.rb new file mode 100644 index 00000000000000..fea8c2f1eea1f7 --- /dev/null +++ b/app/serializers/rest/domain_block_preview_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class REST::DomainBlockPreviewSerializer < ActiveModel::Serializer + attributes :following_count, :followers_count +end diff --git a/app/services/approve_appeal_service.rb b/app/services/approve_appeal_service.rb index b8a522b2a16d4a..3f8d1e2a3b59ea 100644 --- a/app/services/approve_appeal_service.rb +++ b/app/services/approve_appeal_service.rb @@ -53,7 +53,7 @@ def undo_delete_statuses! def undo_mark_statuses_as_sensitive! representative_account = Account.representative - @strike.statuses.includes(:media_attachments).find_each do |status| + @strike.statuses.kept.includes(:media_attachments).reorder(nil).find_each do |status| UpdateStatusService.new.call(status, representative_account.id, sensitive: false) if status.with_media? end end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 97eee0548763e6..9aebab787ee165 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -3,8 +3,6 @@ class NotifyService < BaseService include Redisable - MAXIMUM_GROUP_SPAN_HOURS = 12 - # TODO: the severed_relationships type probably warrants email notifications NON_EMAIL_TYPES = %i( admin.report @@ -216,7 +214,7 @@ def call(recipient, type, activity) return if drop? @notification.filtered = filter? - @notification.group_key = notification_group_key + @notification.set_group_key! @notification.save! # It's possible the underlying activity has been deleted @@ -236,23 +234,6 @@ def call(recipient, type, activity) private - def notification_group_key - return nil if @notification.filtered || Notification::GROUPABLE_NOTIFICATION_TYPES.exclude?(@notification.type) - - type_prefix = "#{@notification.type}-#{@notification.target_status.id}" - redis_key = "notif-group/#{@recipient.id}/#{type_prefix}" - hour_bucket = @notification.activity.created_at.utc.to_i / 1.hour.to_i - - # Reuse previous group if it does not span too large an amount of time - previous_bucket = redis.get(redis_key).to_i - hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS - - # We do not concern ourselves with race conditions since we use hour buckets - redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_SPAN_HOURS.hours.to_i) - - "#{type_prefix}-#{hour_bucket}" - end - def drop? DropCondition.new(@notification).drop? end diff --git a/app/views/admin/settings/branding/show.html.haml b/app/views/admin/settings/branding/show.html.haml index e03c16a25a88f8..62e9c724592d92 100644 --- a/app/views/admin/settings/branding/show.html.haml +++ b/app/views/admin/settings/branding/show.html.haml @@ -25,7 +25,7 @@ .fields-group = f.input :site_short_description, as: :text, - input_html: { rows: 2, maxlength: 200 }, + input_html: { rows: 2, maxlength: Form::AdminSettings::DESCRIPTION_LIMIT }, wrapper: :with_block_label .fields-row diff --git a/app/views/admin/tags/index.html.haml b/app/views/admin/tags/index.html.haml index 8d76d8ffa7469f..be699e5ab2be53 100644 --- a/app/views/admin/tags/index.html.haml +++ b/app/views/admin/tags/index.html.haml @@ -32,7 +32,7 @@ .batch-table .batch-table__body - if @tags.empty? - = nothing_here 'nothing-here--under-tabs' + = nothing_here 'nothing-here--under-tabs nothing-here--no-toolbar' - else = render partial: 'tag', collection: @tags diff --git a/app/views/admin/webhooks/_form.html.haml b/app/views/admin/webhooks/_form.html.haml index 2b948b9a6aa210..bdba08a45425cf 100644 --- a/app/views/admin/webhooks/_form.html.haml +++ b/app/views/admin/webhooks/_form.html.haml @@ -13,7 +13,8 @@ as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', - disabled: Webhook::EVENTS.filter { |event| !current_user.role.can?(Webhook.permission_for_event(event)) } + disabled: Webhook::EVENTS.filter { |event| !current_user.role.can?(Webhook.permission_for_event(event)) }, + label_method: ->(event) { tag.samp(event) } .fields-group = form.input :template, diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml index 1e5aac2976a77e..d58f1ccf4d38bb 100644 --- a/app/views/auth/registrations/new.html.haml +++ b/app/views/auth/registrations/new.html.haml @@ -21,7 +21,7 @@ = f.simple_fields_for :account do |ff| = ff.input :username, append: "@#{site_hostname}", - input_html: { 'aria-label': t('simple_form.labels.defaults.username'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: 30 }, + input_html: { 'aria-label': t('simple_form.labels.defaults.username'), autocomplete: 'off', placeholder: t('simple_form.labels.defaults.username'), pattern: '[a-zA-Z0-9_]+', maxlength: Account::USERNAME_LENGTH_LIMIT }, label: false, required: true, wrapper: :with_label diff --git a/app/views/disputes/strikes/show.html.haml b/app/views/disputes/strikes/show.html.haml index 2bfecebbff9af2..150dc06759188d 100644 --- a/app/views/disputes/strikes/show.html.haml +++ b/app/views/disputes/strikes/show.html.haml @@ -76,7 +76,7 @@ = simple_form_for(@appeal, url: disputes_strike_appeal_path(@strike)) do |f| .fields-group - = f.input :text, wrapper: :with_label, input_html: { maxlength: 500 } + = f.input :text, wrapper: :with_label, input_html: { maxlength: Appeal::TEXT_LENGTH_LIMIT } .actions = f.button :button, t('disputes.strikes.appeals.submit'), type: :submit diff --git a/app/views/settings/applications/_fields.html.haml b/app/views/settings/applications/_fields.html.haml deleted file mode 100644 index d5398489526b01..00000000000000 --- a/app/views/settings/applications/_fields.html.haml +++ /dev/null @@ -1,36 +0,0 @@ -.fields-group - = f.input :name, - label: t('activerecord.attributes.doorkeeper/application.name'), - wrapper: :with_label - -.fields-group - = f.input :website, - label: t('activerecord.attributes.doorkeeper/application.website'), - wrapper: :with_label - -.fields-group - = f.input :redirect_uri, - label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri'), - required: true, - wrapper: :with_block_label - - %p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe - -.field-group - .input.with_block_label - %label= t('activerecord.attributes.doorkeeper/application.scopes') - %span.hint= t('simple_form.hints.defaults.scopes') - - - Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value| - = f.input :scopes, - as: :check_boxes, - collection_wrapper_tag: 'ul', - collection: value.sort, - hint: false, - include_blank: false, - item_wrapper_tag: 'li', - label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) }, - label: false, - required: false, - selected: f.object.scopes.all, - wrapper: :with_block_label diff --git a/app/views/settings/applications/_form.html.haml b/app/views/settings/applications/_form.html.haml new file mode 100644 index 00000000000000..66ea8bc12bf00f --- /dev/null +++ b/app/views/settings/applications/_form.html.haml @@ -0,0 +1,36 @@ +.fields-group + = form.input :name, + label: t('activerecord.attributes.doorkeeper/application.name'), + wrapper: :with_label + +.fields-group + = form.input :website, + label: t('activerecord.attributes.doorkeeper/application.website'), + wrapper: :with_label + +.fields-group + = form.input :redirect_uri, + label: t('activerecord.attributes.doorkeeper/application.redirect_uri'), hint: t('doorkeeper.applications.help.redirect_uri'), + required: true, + wrapper: :with_block_label + + %p.hint= t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, Doorkeeper.configuration.native_redirect_uri)).html_safe + +.field-group + .input.with_block_label + %label= t('activerecord.attributes.doorkeeper/application.scopes') + %span.hint= t('simple_form.hints.defaults.scopes') + + - Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each_value do |value| + = form.input :scopes, + as: :check_boxes, + collection_wrapper_tag: 'ul', + collection: value.sort, + hint: false, + include_blank: false, + item_wrapper_tag: 'li', + label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) }, + label: false, + required: false, + selected: form.object.scopes.all, + wrapper: :with_block_label diff --git a/app/views/settings/applications/new.html.haml b/app/views/settings/applications/new.html.haml index aa2281fea14615..f6a546e8de143a 100644 --- a/app/views/settings/applications/new.html.haml +++ b/app/views/settings/applications/new.html.haml @@ -1,8 +1,8 @@ - content_for :page_title do = t('doorkeeper.applications.new.title') -= simple_form_for @application, url: settings_applications_path do |f| - = render 'fields', f: f += simple_form_for @application, url: settings_applications_path do |form| + = render form .actions - = f.button :button, t('doorkeeper.applications.buttons.submit'), type: :submit + = form.button :button, t('doorkeeper.applications.buttons.submit'), type: :submit diff --git a/app/views/settings/applications/show.html.haml b/app/views/settings/applications/show.html.haml index be1d13eae6fdf7..19630cf49b8ccb 100644 --- a/app/views/settings/applications/show.html.haml +++ b/app/views/settings/applications/show.html.haml @@ -23,8 +23,8 @@ %hr/ -= simple_form_for @application, url: settings_application_path(@application), method: :put do |f| - = render 'fields', f: f += simple_form_for @application, url: settings_application_path(@application), method: :put do |form| + = render form .actions - = f.button :button, t('generic.save_changes'), type: :submit + = form.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index 61ba79c4491f02..8fb21325197e3c 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -27,8 +27,8 @@ = f.simple_fields_for :fields do |fields_f| .row - = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name'), input_html: { maxlength: 255 } - = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value'), input_html: { maxlength: 255 } + = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name'), input_html: { maxlength: Account::Field::MAX_CHARACTERS_LOCAL } + = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value'), input_html: { maxlength: Account::Field::MAX_CHARACTERS_LOCAL } .fields-row .fields-row__column.fields-row__column-6 diff --git a/app/views/user_mailer/welcome.html.haml b/app/views/user_mailer/welcome.html.haml index 0f9cbf36ffb263..efc6cad3934526 100644 --- a/app/views/user_mailer/welcome.html.haml +++ b/app/views/user_mailer/welcome.html.haml @@ -9,7 +9,7 @@ %td %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr - %td.email-header-card-banner-td{ height: 140, background: full_asset_url(instance_presenter.thumbnail&.file&.url(:'@1x') || frontend_asset_path('images/preview.png')) } + %td.email-header-card-banner-td{ background: full_asset_url(instance_presenter.thumbnail&.file&.url(:'@1x') || frontend_asset_path('images/preview.png')) } %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-header-card-body-td diff --git a/config/initializers/opentelemetry.rb b/config/initializers/opentelemetry.rb index d121a95a366370..8edce03b909914 100644 --- a/config/initializers/opentelemetry.rb +++ b/config/initializers/opentelemetry.rb @@ -56,12 +56,13 @@ }, }) - prefix = ENV.fetch('OTEL_SERVICE_NAME_PREFIX', 'mastodon') + prefix = ENV.fetch('OTEL_SERVICE_NAME_PREFIX', 'mastodon') + separator = ENV.fetch('OTEL_SERVICE_NAME_SEPARATOR', '/') c.service_name = case $PROGRAM_NAME - when /puma/ then "#{prefix}/web" + when /puma/ then "#{prefix}#{separator}web" else - "#{prefix}/#{$PROGRAM_NAME.split('/').last}" + "#{prefix}#{separator}#{$PROGRAM_NAME.split('/').last}" end c.service_version = Mastodon::Version.to_s end diff --git a/config/initializers/regexp.rb b/config/initializers/regexp.rb deleted file mode 100644 index a820d2b5d3d473..00000000000000 --- a/config/initializers/regexp.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true - -# 0.5s is a fairly high timeout, but that should account for slow servers under load -Regexp.timeout = 0.5 if Regexp.respond_to?(:timeout=) diff --git a/config/locales/activerecord.be.yml b/config/locales/activerecord.be.yml index db6b632dc462c6..b1495c285552f0 100644 --- a/config/locales/activerecord.be.yml +++ b/config/locales/activerecord.be.yml @@ -15,6 +15,8 @@ be: user/invite_request: text: Прычына errors: + messages: + too_many_lines: перавышана абмежаванне ў %{limit} радкоў models: account: attributes: diff --git a/config/locales/activerecord.bg.yml b/config/locales/activerecord.bg.yml index 1e19d1effba69f..221be3f680e01a 100644 --- a/config/locales/activerecord.bg.yml +++ b/config/locales/activerecord.bg.yml @@ -15,6 +15,12 @@ bg: user/invite_request: text: Причина errors: + attributes: + domain: + invalid: не е действително име на домейн + messages: + invalid_domain_on_line: "%{value} не е действително име на домейн" + too_many_lines: е над ограничение от %{limit} реда models: account: attributes: diff --git a/config/locales/activerecord.el.yml b/config/locales/activerecord.el.yml index 1c3bcc6ebf58be..a47622161674da 100644 --- a/config/locales/activerecord.el.yml +++ b/config/locales/activerecord.el.yml @@ -15,6 +15,12 @@ el: user/invite_request: text: Αιτιολογία errors: + attributes: + domain: + invalid: δεν είναι έγκυρο όνομα τομέα + messages: + invalid_domain_on_line: το %{value} δεν είναι έγκυρο όνομα τομέα + too_many_lines: υπερβαίνει το όριο των %{limit} γραμμών models: account: attributes: diff --git a/config/locales/activerecord.eo.yml b/config/locales/activerecord.eo.yml index 99059e38568928..f99f726e231d84 100644 --- a/config/locales/activerecord.eo.yml +++ b/config/locales/activerecord.eo.yml @@ -15,6 +15,12 @@ eo: user/invite_request: text: Kialo errors: + attributes: + domain: + invalid: ne estas valida domajna nomo + messages: + invalid_domain_on_line: "%{value} ne estas valida domajna nomo" + too_many_lines: superas la limon de %{limit} linioj models: account: attributes: diff --git a/config/locales/activerecord.io.yml b/config/locales/activerecord.io.yml index 6426defc55a41d..2b0d5091985242 100644 --- a/config/locales/activerecord.io.yml +++ b/config/locales/activerecord.io.yml @@ -15,6 +15,12 @@ io: user/invite_request: text: Rezono errors: + attributes: + domain: + invalid: ne esas valida domennomo + messages: + invalid_domain_on_line: "%{value} ne esas valida domennomo" + too_many_lines: esas plu kam la limito qua esas %{limit} linei models: account: attributes: diff --git a/config/locales/activerecord.sk.yml b/config/locales/activerecord.sk.yml index 809d00647146db..68a9e447b9099c 100644 --- a/config/locales/activerecord.sk.yml +++ b/config/locales/activerecord.sk.yml @@ -15,6 +15,11 @@ sk: user/invite_request: text: Dôvod errors: + attributes: + domain: + invalid: nie je platný tvar domény + messages: + invalid_domain_on_line: "%{value} nie je platný tvar domény" models: account: attributes: diff --git a/config/locales/an.yml b/config/locales/an.yml index 2f181e0757da43..2db042f1b1ad30 100644 --- a/config/locales/an.yml +++ b/config/locales/an.yml @@ -1375,7 +1375,6 @@ an: delete: Borrar cuenta development: Desembolique edit_profile: Editar perfil - export: Exportar información featured_tags: Hashtags destacaus import: Importar import_and_export: Importar y exportar diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 81705acba045d6..829855776d9afa 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1719,7 +1719,6 @@ ar: delete: حذف الحسابات development: التطوير edit_profile: تعديل الصفحة التعريفية - export: تصدير البيانات featured_tags: الوسوم الشائعة import: استيراد import_and_export: استيراد وتصدير diff --git a/config/locales/ast.yml b/config/locales/ast.yml index a7d4a9917eebdb..72c5d9d75254ce 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -774,7 +774,6 @@ ast: back: Volver a Mastodon development: Desendolcu edit_profile: Edición del perfil - export: Esportación de datos featured_tags: Etiquetes destacaes import: Importación import_and_export: Importación y esportación diff --git a/config/locales/be.yml b/config/locales/be.yml index d45f443b75f06c..d1d3e17679f2d6 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -1722,7 +1722,6 @@ be: delete: Выдаленне ўліковага запісу development: Распрацоўка edit_profile: Рэдагаваць профіль - export: Экспарт даных featured_tags: Выбраныя хэштэгі import: Імпарт import_and_export: Імпарт і экспарт diff --git a/config/locales/bg.yml b/config/locales/bg.yml index e2c246827afb4b..00b3a41167cec1 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1617,7 +1617,6 @@ bg: delete: Изтриване на акаунта development: Разработка edit_profile: Редактирай профила си - export: Експортиране на данни featured_tags: Актуални хаштагове import: Импортиране import_and_export: Импортиране и експортиране diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 33a1d4e88f7bfe..965f354a35f82c 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -873,6 +873,9 @@ ca: message_html: No has definit cap norma del servidor. sidekiq_process_check: message_html: No hi ha cap procés de Sidekiq executant-se per a la cua (o cues) de %{value}. Reviseu la configuració de Sidekiq + software_version_check: + action: Veure les actualitzacions disponibles + message_html: Hi ha disponible una actualització de Mastodon. software_version_critical_check: action: Veure actualitzacions disponibles message_html: Hi ha disponible una actualització crítica de Mastodon, si us plau, actualitza-la el més abans possible. @@ -1686,7 +1689,7 @@ ca: delete: Eliminació del compte development: Desenvolupament edit_profile: Edita el perfil - export: Exportació de dades + export: Exporta featured_tags: Etiquetes destacades import: Importació import_and_export: Importació i exportació diff --git a/config/locales/ckb.yml b/config/locales/ckb.yml index bc668d2ce4c7e4..88dadff0146769 100644 --- a/config/locales/ckb.yml +++ b/config/locales/ckb.yml @@ -907,7 +907,6 @@ ckb: delete: سڕینەوەی هەژمارە development: گەشەپێدان edit_profile: دەستکاری پرۆفایل - export: ناردن زانیاری featured_tags: هاشتاگی تایبەت import: هاوردن import_and_export: هاوردەکردن و ناردن diff --git a/config/locales/co.yml b/config/locales/co.yml index 58ddd7d01b593f..dad3e08ffd23d0 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -891,7 +891,6 @@ co: delete: Suppressione di u contu development: Sviluppu edit_profile: Mudificà u prufile - export: Spurtazione d’infurmazione featured_tags: Hashtag in vista import: Impurtazione import_and_export: Impurtazione è spurtazione diff --git a/config/locales/cs.yml b/config/locales/cs.yml index b7fc8ab1b0bc26..91fa517944d17c 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1666,7 +1666,6 @@ cs: delete: Smazání účtu development: Vývoj edit_profile: Upravit profil - export: Export dat featured_tags: Zvýrazněné hashtagy import: Import import_and_export: Import a export diff --git a/config/locales/cy.yml b/config/locales/cy.yml index c2c193d9434292..1ae6aa08fff93a 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -1796,7 +1796,6 @@ cy: delete: Dileu cyfrif development: Datblygu edit_profile: Golygu proffil - export: Allforio data featured_tags: Prif hashnodau import: Mewnforio import_and_export: Mewnforio ac allforio diff --git a/config/locales/da.yml b/config/locales/da.yml index a177b97de76fd2..0da901d4a8c48c 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -875,6 +875,9 @@ da: message_html: Ingen serverregler defineret. sidekiq_process_check: message_html: Ingen Sidekiq-proces kører for %{value}-kø(er). Gennemgå Sidekiq-opsætningen + software_version_check: + action: Se tilgængelige opdateringer + message_html: En Mastodon-opdatering er tilgængelig. software_version_critical_check: action: Se tilgængelige opdateringer message_html: En kritisk Mastodon-opdatering er tilgængelig. Opdatér hurtigst muligt. @@ -1692,7 +1695,7 @@ da: delete: Kontosletning development: Udvikling edit_profile: Redigér profil - export: Dataeksport + export: Eksport featured_tags: Udvalgte hashtags import: Import import_and_export: Import og eksport diff --git a/config/locales/de.yml b/config/locales/de.yml index 85e24c230ec339..c82e65282ffe3e 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -875,6 +875,9 @@ de: message_html: Du hast keine Serverregeln festgelegt. sidekiq_process_check: message_html: Kein Sidekiq-Prozess läuft für die %{value} Warteschlange(n). Bitte überprüfe deine Sidekiq-Konfiguration + software_version_check: + action: Verfügbare Updates ansehen + message_html: Ein Mastodon-Update ist verfügbar. software_version_critical_check: action: Verfügbare Updates ansehen message_html: Ein kritisches Mastodon-Update ist verfügbar – bitte aktualisiere so schnell wie möglich. @@ -1422,7 +1425,7 @@ de: max_uses: one: Eine Verwendung other: "%{count} Verwendungen" - max_uses_prompt: Keine Einschränkung + max_uses_prompt: Unbegrenzt prompt: Erstelle Einladungen und teile die dazugehörigen Links, um anderen einen Zugang zu diesem Server zu gewähren table: expires_at: Läuft ab @@ -1900,7 +1903,7 @@ de: feature_action: Mehr erfahren feature_audience: Mastodon bietet dir eine einzigartige Möglichkeit, deine Reichweite ohne Mittelsperson zu verwalten. Auf deiner eigenen Infrastruktur bereitgestellt, ermöglicht Mastodon es dir, jedem anderen Mastodon-Server zu folgen und von jedem anderen Server aus gefolgt zu werden. Ebenso steht Mastodon unter deiner Kontrolle. feature_audience_title: Baue deine Reichweite mit Vertrauen auf - feature_control: Du weißt am besten, was du auf deiner Startseite sehen möchtest. Keine Algorithmen oder Werbung, die deine Zeit verschwenden. Folge Nutzer*innen von jedem Mastodon-Server von einem einzelnen Konto aus und empfange deren Beiträge in chronologischer Reihenfolge. Mache Mastodon zu deinem ganz persönlichen Fleckchen im Internet. + feature_control: Du weißt am besten, was du auf deiner Startseite sehen möchtest. Keine Algorithmen oder Werbung, die deine Zeit verschwenden. Folge Nutzer*innen auf allen Mastodon-Servern von einem einzelnen Konto aus und empfange deren Beiträge in chronologischer Reihenfolge. Mache Mastodon zu deinem ganz persönlichen Fleckchen im Internet. feature_control_title: Behalte die Kontrolle über deine eigene Timeline feature_creativity: Mastodon unterstützt Audio-, Video- und Bildbeiträge, Beschreibungen, Umfragen, Inhaltswarnungen, animierte Avatare, benutzerdefinierte Emojis, das Zuschneiden von Vorschaubildern und vieles mehr, um dir zu helfen, dich online zu entfalten. Egal, ob du deine Kunst, deine Musik oder deinen Podcast veröffentlichst – Mastodon ist für dich da. feature_creativity_title: Einzigartige Kreativität diff --git a/config/locales/devise.eo.yml b/config/locales/devise.eo.yml index 193fecc757201a..9d946967e9cba9 100644 --- a/config/locales/devise.eo.yml +++ b/config/locales/devise.eo.yml @@ -48,10 +48,13 @@ eo: subject: 'Mastodon: Instrukcioj por ŝanĝi pasvorton' title: Pasvorto restarigita two_factor_disabled: + explanation: Ensalutu nun eblas uzante nur retadreson kaj pasvorton. subject: 'Mastodon: dufaktora aŭtentigo malebligita' + subtitle: Dupaŝa aŭtentigo por via konto estas malŝaltita. title: 2FA estas malŝaltita two_factor_enabled: subject: 'Mastodon: Dufaktora aŭtentigo ebligita' + subtitle: Dupaŝa aŭtentigo por via konto estas ŝaltita. title: 2FA aktivigita two_factor_recovery_codes_changed: explanation: La antaŭaj reakiraj kodoj estis nuligitaj kaj novaj estis generitaj. @@ -69,9 +72,11 @@ eo: subject: 'Mastodon: sekureca ŝlosilo forigita' title: Unu el viaj sekurecaj ŝlosiloj estis forigita webauthn_disabled: + explanation: Aŭtentigo per sekurecaj ŝlosiloj estas malŝaltita por via konto. subject: 'Mastodon: sekureca-ŝlosila aŭtentigo malebligita' title: Sekurecaj ŝlosiloj malaktivigitaj webauthn_enabled: + extra: Via sekureca ŝlosilo nun povas esti uzata por ensaluto. subject: 'Mastodon: sekureca-ŝlosila aŭtentigo ebligita' title: Sekurecaj ŝlosiloj aktivigitaj omniauth_callbacks: diff --git a/config/locales/devise.io.yml b/config/locales/devise.io.yml index 6bf0b52cef18b0..49637579e4dfe8 100644 --- a/config/locales/devise.io.yml +++ b/config/locales/devise.io.yml @@ -12,6 +12,7 @@ io: last_attempt: Tu ankore povas probar unfoye ante ke tua konto esos extingita. locked: Tua konto esas extingita. not_found_in_database: Nejusta %{authentication_keys}. + omniauth_user_creation_failure: Eroro dum ke kreas konto por ca identeso. pending: Vua konti ankore kontrolesas. timeout: Vua kunsido expiris. Voluntez rienirar por avancar. unauthenticated: Tu devas enirar o membreskar por durar. @@ -47,14 +48,19 @@ io: subject: Instrucioni por chanjar la pasvorto title: Richanjo di pasvorto two_factor_disabled: + explanation: Eniro esas nun posibla per nur retpostoadreso e pasvorto. subject: 'Mastodon: 2-faktorverifiko deaktivigesis' + subtitle: 2-faktora verifiko por vua konto desaktivigesis. title: 2FA deaktivigesis two_factor_enabled: + explanation: Ficho facesis da parigita softwaro TOTP bezonesos por eniro. subject: 'Mastodon: 2-faktorverifiko aktivigesis' + subtitle: 2-faktora verifiko aktivigesis por vua konto. title: 2FA aktivigesis two_factor_recovery_codes_changed: explanation: Antea rigankodexi devalidesis e novo facesis. subject: 'Mastodon: 2-faktorrigankodexi rifacesis' + subtitle: Antea rigankodexi desvalidesis e novo facesis. title: 2FA-rigankodexi chanjesis unlock_instructions: subject: Instructioni por riacendar la konto @@ -68,9 +74,13 @@ io: subject: 'Mastodon: Sekurklefo efacesis' title: 1 de vua sekurklefi efacesis webauthn_disabled: + explanation: Verifiko per sekuresklefi desaktivigesis por vua konto. + extra: Eniro esas nun posibla per nur ficho qua facesis da parigita softwaro TOTP. subject: 'Mastodon: Verifiko per sekurklefi deaktivigesis' title: Sekurklefi deaktivigesis webauthn_enabled: + explanation: Sekuresklefoa verifiko aktivigesis por vua konto. + extra: Vua sekuresklefo povas nun uzesar por eniro. subject: 'Mastodon: Sekurklefverifiko aktivigesis' title: Sekurklefi aktivigesis omniauth_callbacks: diff --git a/config/locales/devise.kab.yml b/config/locales/devise.kab.yml index 20249aae9431ce..32a98a37c3be0e 100644 --- a/config/locales/devise.kab.yml +++ b/config/locales/devise.kab.yml @@ -11,9 +11,9 @@ kab: invalid: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir. last_attempt: Γur-k yiwen n uɛraḍ-nniḍen kan send ad yettucekkel umiḍan-ik. locked: Amiḍan-ik yettwargel. - not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir. + not_found_in_database: Tella tuccḍa deg %{authentication_keys} neɣ deg wawal uffir. omniauth_user_creation_failure: Tuccḍa lawan n tmerna n umiḍan i timagit-a. - pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli. + pending: Amiḍan-inek·inem mazal-it deg ɛiwed n tmuɣli. timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ. unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ send ad tkemmelḍ. unconfirmed: Ilaq ad wekdeḍ tansa-inek·inem imayl send ad tkemmelḍ. diff --git a/config/locales/doorkeeper.af.yml b/config/locales/doorkeeper.af.yml index 9e05f403f6c920..d32730468a7c4d 100644 --- a/config/locales/doorkeeper.af.yml +++ b/config/locales/doorkeeper.af.yml @@ -60,7 +60,6 @@ af: error: title: "’n Fout het ingesluip" new: - prompt_html: "%{client_name} wil toegang hê tot jou rekening. Dit is ’n derdepartytoepassing. Moet dit nie toelaat as jy dit nie vertrou nie." review_permissions: Hersien toestemmings title: Benodig magtiging show: diff --git a/config/locales/doorkeeper.an.yml b/config/locales/doorkeeper.an.yml index 1096d8c8dc7667..bee55771de734e 100644 --- a/config/locales/doorkeeper.an.yml +++ b/config/locales/doorkeeper.an.yml @@ -60,7 +60,6 @@ an: error: title: Ha ocurriu una error new: - prompt_html: "%{client_name} deseya permiso pa acceder ta la tuya cuenta. Ye una aplicación de tercers. Si no confías en ella, no habrías d'autorizar-la." review_permissions: Revisar permisos title: Se requiere autorización show: diff --git a/config/locales/doorkeeper.ar.yml b/config/locales/doorkeeper.ar.yml index 79e6c60152235b..8dea8b4894cedc 100644 --- a/config/locales/doorkeeper.ar.yml +++ b/config/locales/doorkeeper.ar.yml @@ -60,7 +60,6 @@ ar: error: title: حدث هناك خطأ new: - prompt_html: يريد %{client_name} الإذن للوصول إلى حسابك. إنه تطبيق طرف ثالث. إذا كنت لا تثق فيه، فلا ينبغي أن تأذن له بذلك. review_permissions: مراجعة الصلاحيات title: إذن بالتصريح show: diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml index 0df15a07b62330..c9c831f7f5bf77 100644 --- a/config/locales/doorkeeper.ast.yml +++ b/config/locales/doorkeeper.ast.yml @@ -41,7 +41,6 @@ ast: error: title: Prodúxose un error new: - prompt_html: "%{client_name}, que ye una aplicación de terceros, quier tener accesu a la cuenta. Si nun t'enfotes nella, nun habríes autorizala." review_permissions: Revisión de los permisos show: title: Copia esti códigu d'autorización y apiégalu na aplicación. diff --git a/config/locales/doorkeeper.be.yml b/config/locales/doorkeeper.be.yml index 75f9930e1a6b3a..defe0ddf0dbafc 100644 --- a/config/locales/doorkeeper.be.yml +++ b/config/locales/doorkeeper.be.yml @@ -60,7 +60,6 @@ be: error: title: Узнікла памылка new: - prompt_html: "%{client_name} хацеў бы атрымаць дазвол для доступу да вашага акаунта. Гэта вонкавае прыкладанне. Не давайце дазволу на гэта, калі вы не давяраеце гэтаму прыкладанню. " review_permissions: Прагледзець дазволы title: Патрабуецца аўтарызацыя show: diff --git a/config/locales/doorkeeper.bg.yml b/config/locales/doorkeeper.bg.yml index a1ef1778547c02..c3977e58441e22 100644 --- a/config/locales/doorkeeper.bg.yml +++ b/config/locales/doorkeeper.bg.yml @@ -60,7 +60,7 @@ bg: error: title: Възникна грешка new: - prompt_html: "%{client_name} иска разрешение да има достъп до акаунта ви. Приложение от трета страна е.Ако не му се доверявате, то може да не го упълномощявате." + prompt_html: "%{client_name} желае да има достъп до акаунта ви. Одобрявайте само тази заявка, ако я разпознавате и ако имате доворерие на източника." review_permissions: Преглед на разрешенията title: Изисква се упълномощаване show: diff --git a/config/locales/doorkeeper.ca.yml b/config/locales/doorkeeper.ca.yml index 85a09b5b433571..590339fe887949 100644 --- a/config/locales/doorkeeper.ca.yml +++ b/config/locales/doorkeeper.ca.yml @@ -60,7 +60,7 @@ ca: error: title: S'ha produït un error new: - prompt_html: "%{client_name} vol permís per accedir el teu compte. És una aplicació de tercers. Si no hi confies, no hauries d'autoritzar-la." + prompt_html: "%{client_name} demana accés al vostre compte. Només aproveu aquesta petició si reconeixeu i confieu en aquest origen." review_permissions: Revisa els permisos title: Cal autorizació show: diff --git a/config/locales/doorkeeper.ckb.yml b/config/locales/doorkeeper.ckb.yml index f952b6eca9ea87..b318bce859b06d 100644 --- a/config/locales/doorkeeper.ckb.yml +++ b/config/locales/doorkeeper.ckb.yml @@ -60,7 +60,6 @@ ckb: error: title: هەڵەیەک ڕوویدا new: - prompt_html: "%{client_name} حەز دەکات مۆڵەت بدرێت بۆ چوونە ناو ئەکاونتەکەت. ئەپڵیکەیشنێکی لایەنی سێیەمە. ئەگەر متمانەت پێی نییە، ئەوا نابێت ڕێگەی پێبدەیت." review_permissions: پێداچوونەوە بە مۆڵەتەکاندا بکە title: ڕێپێدان پێویستە show: diff --git a/config/locales/doorkeeper.cs.yml b/config/locales/doorkeeper.cs.yml index 1b98d0f88b3e9c..882be66ee0c3d6 100644 --- a/config/locales/doorkeeper.cs.yml +++ b/config/locales/doorkeeper.cs.yml @@ -60,7 +60,6 @@ cs: error: title: Vyskytla se chyba new: - prompt_html: "%{client_name} si přeje oprávnění pro přístup k vašemu účtu. Je to aplikace třetí strany. Pokud jí nedůvěřujete, pak byste ji neměli autorizovat." review_permissions: Zkontrolujte oprávnění title: Je vyžadována autorizace show: diff --git a/config/locales/doorkeeper.cy.yml b/config/locales/doorkeeper.cy.yml index f15d74d72146a8..32f5055b6c0665 100644 --- a/config/locales/doorkeeper.cy.yml +++ b/config/locales/doorkeeper.cy.yml @@ -60,7 +60,7 @@ cy: error: title: Mae rhywbeth wedi mynd o'i le new: - prompt_html: Hoffai %{client_name} gael caniatâd i gael mynediad i'ch cyfrif. Mae'n gais trydydd parti. Os nad ydych yn ymddiried ynddo, yna peidiwch a'i awdurdodi. + prompt_html: Hoffai %{client_name} gael caniatâd i gael mynediad i'ch cyfrif. Dim ond os ydych chi'n adnabod ac yn ymddiried yn y ffynhonnell hon y dylech gymeradwyo'r cais hwn. review_permissions: Adolygu caniatâd title: Angen awdurdodi show: diff --git a/config/locales/doorkeeper.da.yml b/config/locales/doorkeeper.da.yml index cd11dcf4e391ff..7ac16e0012b36e 100644 --- a/config/locales/doorkeeper.da.yml +++ b/config/locales/doorkeeper.da.yml @@ -60,7 +60,7 @@ da: error: title: En fejl opstod new: - prompt_html: "%{client_name} ønsker tilladelse til at tilgå din konto. Den er en tredjepartsapplikation. Har du ikke tillid til den, bør den ikke godkendes." + prompt_html: "%{client_name} vil ønsker tilladelse til at tilgå din konto. Godkend kun denne anmodning, hvis kilden genkendes, og man stoler på den." review_permissions: Gennemgå tilladelser title: Godkendelse kræves show: diff --git a/config/locales/doorkeeper.de.yml b/config/locales/doorkeeper.de.yml index b29d668b2ed2ef..6d0e3010af7523 100644 --- a/config/locales/doorkeeper.de.yml +++ b/config/locales/doorkeeper.de.yml @@ -60,7 +60,7 @@ de: error: title: Ein Fehler ist aufgetreten new: - prompt_html: "%{client_name} möchte auf dein Konto zugreifen. Es handelt sich um eine Software von Dritten. Wenn du der Anwendung nicht vertraust, solltest du ihr keinen Zugriff auf dein Konto geben." + prompt_html: "%{client_name} möchte auf dein Konto zugreifen. Du solltest diese Anfrage nur genehmigen, wenn du diese Quelle kennst und ihr vertraust." review_permissions: Berechtigungen überprüfen title: Autorisierung erforderlich show: diff --git a/config/locales/doorkeeper.el.yml b/config/locales/doorkeeper.el.yml index 7fcd69c2384b53..59877b6bd06766 100644 --- a/config/locales/doorkeeper.el.yml +++ b/config/locales/doorkeeper.el.yml @@ -60,7 +60,6 @@ el: error: title: Εμφανίστηκε σφάλμα new: - prompt_html: Το %{client_name} θα ήθελε άδεια πρόσβασης στο λογαριασμό σου. Είναι μια εφαρμογή τρίτων. Αν δεν το εμπιστεύεσαι, τότε δεν πρέπει να το εγκρίνεις. review_permissions: Ανασκόπηση δικαιωμάτων title: Απαιτείται έγκριση show: diff --git a/config/locales/doorkeeper.en-GB.yml b/config/locales/doorkeeper.en-GB.yml index 999284e85ff38e..63a4575e83ce51 100644 --- a/config/locales/doorkeeper.en-GB.yml +++ b/config/locales/doorkeeper.en-GB.yml @@ -60,7 +60,7 @@ en-GB: error: title: An error has occurred new: - prompt_html: "%{client_name} would like permission to access your account. It is a third-party application. If you do not trust it, then you should not authorise it." + prompt_html: "%{client_name} would like permission to access your account. Only approve this request if you recognise and trust this source." review_permissions: Review permissions title: Authorisation required show: diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml index e28f6a79664be1..3b3b141afa7889 100644 --- a/config/locales/doorkeeper.en.yml +++ b/config/locales/doorkeeper.en.yml @@ -60,7 +60,7 @@ en: error: title: An error has occurred new: - prompt_html: "%{client_name} would like permission to access your account. It is a third-party application. If you do not trust it, then you should not authorize it." + prompt_html: "%{client_name} would like permission to access your account. Only approve this request if you recognize and trust this source." review_permissions: Review permissions title: Authorization required show: diff --git a/config/locales/doorkeeper.eo.yml b/config/locales/doorkeeper.eo.yml index 8bb61c7a49cfc3..12e120f8befa67 100644 --- a/config/locales/doorkeeper.eo.yml +++ b/config/locales/doorkeeper.eo.yml @@ -60,7 +60,6 @@ eo: error: title: Eraro okazis new: - prompt_html: "%{client_name} petas permeson por aliri vian konton. Se vi ne fidas ĝin, ne rajtigu ĝin." review_permissions: Revizu permesojn title: Rajtigo bezonata show: diff --git a/config/locales/doorkeeper.es-AR.yml b/config/locales/doorkeeper.es-AR.yml index 91f41912477480..a6e1a46b80718c 100644 --- a/config/locales/doorkeeper.es-AR.yml +++ b/config/locales/doorkeeper.es-AR.yml @@ -60,7 +60,7 @@ es-AR: error: title: Ocurrió un error new: - prompt_html: "%{client_name} solicita permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confiás en ella, no deberías autorizarla." + prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Aprobá esta solicitud solo si reconocés y confiás en esta fuente. review_permissions: Revisar permisos title: Autorización requerida show: diff --git a/config/locales/doorkeeper.es-MX.yml b/config/locales/doorkeeper.es-MX.yml index 49ff9a1e43d15d..e119d71f4e7028 100644 --- a/config/locales/doorkeeper.es-MX.yml +++ b/config/locales/doorkeeper.es-MX.yml @@ -60,7 +60,7 @@ es-MX: error: title: Ha ocurrido un error new: - prompt_html: "%{client_name} requiere permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confías en esta, no deberías autorizarla." + prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Aprueba esta solicitud solo si reconoces y confías en esta fuente. review_permissions: Revisar permisos title: Se requiere autorización show: diff --git a/config/locales/doorkeeper.es.yml b/config/locales/doorkeeper.es.yml index b3c7ccddd46d89..d582460d3fe7a9 100644 --- a/config/locales/doorkeeper.es.yml +++ b/config/locales/doorkeeper.es.yml @@ -60,7 +60,7 @@ es: error: title: Ha ocurrido un error new: - prompt_html: "%{client_name} desea permiso para acceder a tu cuenta. Es una aplicación de terceros. Si no confías en ella, no deberías autorizarla." + prompt_html: A %{client_name} le gustaría obtener permiso para acceder a tu cuenta. Aprueba esta solicitud solo si reconoces y confías en esta fuente. review_permissions: Revisar permisos title: Se requiere autorización show: diff --git a/config/locales/doorkeeper.et.yml b/config/locales/doorkeeper.et.yml index ffc42239a90296..ebfaf5c710d509 100644 --- a/config/locales/doorkeeper.et.yml +++ b/config/locales/doorkeeper.et.yml @@ -60,7 +60,6 @@ et: error: title: Ilmnes viga new: - prompt_html: "%{client_name} soovib luba kontole juurdepääsuks. See on kolmanda osapoole rakendus. Kui see pole usaldusväärne, siis ei tohiks seda lubada." review_permissions: Lubade ülevaade title: Autoriseerimine vajalik show: diff --git a/config/locales/doorkeeper.eu.yml b/config/locales/doorkeeper.eu.yml index e7963672fae5d3..a09fe42f40a4dc 100644 --- a/config/locales/doorkeeper.eu.yml +++ b/config/locales/doorkeeper.eu.yml @@ -60,7 +60,6 @@ eu: error: title: Errore bat gertatu da new: - prompt_html: "%{client_name} bezeroak zure kontura sartzeko baimena nahi du. Hirugarrengoen aplikazio bat da. Ez bazara fidatzen, ez zenuke baimendu behar." review_permissions: Berrikusi baimenak title: Baimena behar da show: diff --git a/config/locales/doorkeeper.fa.yml b/config/locales/doorkeeper.fa.yml index 0ce7a9591dc21b..4ff03950b55f80 100644 --- a/config/locales/doorkeeper.fa.yml +++ b/config/locales/doorkeeper.fa.yml @@ -60,7 +60,6 @@ fa: error: title: خطایی رخ داد new: - prompt_html: "%{client_name} خواهان اجازه دسترسی به حساب کاربری شماست. اگر به آن اعتماد ندارید، نباید تاییدش کنید." review_permissions: بازبینی اجازه‌ها title: نیاز به اجازه دادن show: diff --git a/config/locales/doorkeeper.fi.yml b/config/locales/doorkeeper.fi.yml index ce8aef4a9fc6cb..7d44a6a6b92528 100644 --- a/config/locales/doorkeeper.fi.yml +++ b/config/locales/doorkeeper.fi.yml @@ -60,7 +60,7 @@ fi: error: title: Tapahtui virhe new: - prompt_html: "%{client_name} pyytää oikeutta käyttää tiliäsi. Se on kolmannen osapuolen sovellus. Jos et luota siihen, älä valtuuta sitä." + prompt_html: "%{client_name} haluaisi käyttöoikeuden tiliisi. Hyväksy tämä pyyntö vain, jos tunnistat lähteen ja luotat siihen." review_permissions: Tarkista käyttöoikeudet title: Valtuutus vaaditaan show: diff --git a/config/locales/doorkeeper.fo.yml b/config/locales/doorkeeper.fo.yml index 29f8cd3387ee49..b6c1998b3a109a 100644 --- a/config/locales/doorkeeper.fo.yml +++ b/config/locales/doorkeeper.fo.yml @@ -60,7 +60,7 @@ fo: error: title: Ein feilur er íkomin new: - prompt_html: "%{client_name} kundi hugsa sær atgongd til tína kontu. Tað er ein triðjaparts-nýtsluskipan. Tú skal ikki geva henni hesa heimld, um tú ikki hevur álit á henni." + prompt_html: "%{client_name} kundi hugsað sær atgongd til tína kontu. Góðtak einans hesa umbøn, um tú kennir hesa keldu aftur og hevur álit á henni." review_permissions: Eftirkanna rættindi title: Váttan kravd show: diff --git a/config/locales/doorkeeper.fr-CA.yml b/config/locales/doorkeeper.fr-CA.yml index f06cc7804df4aa..9279a8a26ace25 100644 --- a/config/locales/doorkeeper.fr-CA.yml +++ b/config/locales/doorkeeper.fr-CA.yml @@ -60,7 +60,7 @@ fr-CA: error: title: Une erreur est survenue new: - prompt_html: "%{client_name} souhaite accéder à votre compte. Il s'agit d'une application tierce. Si vous ne lui faites pas confiance, vous ne devriez pas l'y autoriser." + prompt_html: "%{client_name} aimerait avoir la permission d'accéder à votre compte. Approuver cette demande uniquement si vous reconnaissez et faites confiance à cette source." review_permissions: Examiner les autorisations title: Autorisation requise show: diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml index cf8d1f08b43e77..71c9605d8a9393 100644 --- a/config/locales/doorkeeper.fr.yml +++ b/config/locales/doorkeeper.fr.yml @@ -60,7 +60,7 @@ fr: error: title: Une erreur est survenue new: - prompt_html: "%{client_name} souhaite accéder à votre compte. Il s'agit d'une application tierce. Vous ne devriez pas l'y autoriser si vous ne lui faites pas confiance." + prompt_html: "%{client_name} aimerait avoir la permission d'accéder à votre compte. Approuver cette demande uniquement si vous reconnaissez et faites confiance à cette source." review_permissions: Examiner les autorisations title: Autorisation requise show: diff --git a/config/locales/doorkeeper.fy.yml b/config/locales/doorkeeper.fy.yml index f15389faf90b42..94e67d17a60763 100644 --- a/config/locales/doorkeeper.fy.yml +++ b/config/locales/doorkeeper.fy.yml @@ -60,7 +60,6 @@ fy: error: title: Der is in flater bard new: - prompt_html: "%{client_name} hat tastimming nedich om tagong te krijen ta jo account. It giet om in tapassing fan in tredde partij.As jo dit net fertrouwe, moatte jo gjin tastimming jaan." review_permissions: Tastimmingen beoardiele title: Autorisaasje fereaske show: diff --git a/config/locales/doorkeeper.ga.yml b/config/locales/doorkeeper.ga.yml index 95c3c4d2237449..b8ee3497b79db1 100644 --- a/config/locales/doorkeeper.ga.yml +++ b/config/locales/doorkeeper.ga.yml @@ -60,7 +60,7 @@ ga: error: title: Tharla earráid new: - prompt_html: Ba mhaith le %{client_name} cead rochtain a fháil ar do chuntas. Is iarratas tríú páirtí é. Mura bhfuil muinín agat as, níor cheart duit é a údarú. + prompt_html: Ba mhaith le %{client_name} cead rochtain a fháil ar do chuntas. Ní cheadaigh an t-iarratas seo ach amháin má aithníonn tú an fhoinse seo agus go bhfuil muinín agat as. review_permissions: Ceadanna a athbhreithniú title: Tá údarú ag teastáil show: diff --git a/config/locales/doorkeeper.gd.yml b/config/locales/doorkeeper.gd.yml index 1db1a90f8014a3..8157a4e5fdabb5 100644 --- a/config/locales/doorkeeper.gd.yml +++ b/config/locales/doorkeeper.gd.yml @@ -60,7 +60,7 @@ gd: error: title: Thachair mearachd new: - prompt_html: Bu mhiann le %{client_name} cead gus an cunntas agad inntrigeadh. Seo aplacaid threas-phàrtaidh. Mur eil earbsa agad ann, na ùghdarraich e. + prompt_html: Bu toigh le %{client_name} cead fhaighinn airson an cunntas agad inntrigeadh. Na gabh ris an iarrtas seo ach mas aithne dhut an tùs seo agus earbsa agad ann. review_permissions: Thoir sùil air na ceadan title: Tha feum air ùghdarrachadh show: diff --git a/config/locales/doorkeeper.gl.yml b/config/locales/doorkeeper.gl.yml index 2103e50ea198d0..adee6bd3d3ccb4 100644 --- a/config/locales/doorkeeper.gl.yml +++ b/config/locales/doorkeeper.gl.yml @@ -60,7 +60,7 @@ gl: error: title: Algo fallou new: - prompt_html: "%{client_name} solicita permiso para acceder á túa conta. É unha aplicación de terceiros. Se non confías nela, non deberías autorizala." + prompt_html: "%{client_name} solicita permiso para acceder á túa conta. Aproba esta solicitude só se recoñeces e confías da súa orixe." review_permissions: Revisar permisos title: Autorización necesaria show: diff --git a/config/locales/doorkeeper.he.yml b/config/locales/doorkeeper.he.yml index 16a8fc94cf54d6..a454c779f18f3f 100644 --- a/config/locales/doorkeeper.he.yml +++ b/config/locales/doorkeeper.he.yml @@ -60,7 +60,7 @@ he: error: title: התרחשה שגיאה new: - prompt_html: "%{client_name} מעוניין בהרשאה לגשת לחשבונך. זוהי אפליקציית צד-שלישי. אם יש סיבה לא לבטוח בה, נא לא לאשר." + prompt_html: היישום %{client_name} מבקש גישה לחשבונך. אשרו רק אם אתם מזהים את הבקשה וסומכים על מקור הבקשה. review_permissions: עיון בהרשאות title: נדרשת הרשאה show: diff --git a/config/locales/doorkeeper.hu.yml b/config/locales/doorkeeper.hu.yml index b3cd00f4beeec4..a13c362173df2a 100644 --- a/config/locales/doorkeeper.hu.yml +++ b/config/locales/doorkeeper.hu.yml @@ -60,7 +60,7 @@ hu: error: title: Hiba történt new: - prompt_html: "%{client_name} szeretné elérni a fiókodat. Ez egy harmadik féltől származó alkalmazás. Ha nem bízol meg benne, ne addj felhatalmazást neki." + prompt_html: A(z) %{client_name} engedélyt kér hogy hozzáférjen a fiókodhoz. Csak akkor engedélyezd ezt a kérést, ha felismered és megbízol ebben a forrásban. review_permissions: Jogosultságok áttekintése title: Engedélyezés szükséges show: diff --git a/config/locales/doorkeeper.ia.yml b/config/locales/doorkeeper.ia.yml index 985d073ab80ae6..6bf5e3850670e4 100644 --- a/config/locales/doorkeeper.ia.yml +++ b/config/locales/doorkeeper.ia.yml @@ -60,7 +60,6 @@ ia: error: title: Un error ha occurrite new: - prompt_html: "%{client_name} vole haber le permission de acceder a tu conto. Illo es un application tertie. Si tu non confide in illo, alora tu non deberea autorisar lo." review_permissions: Revider permissiones title: Autorisation necessari show: diff --git a/config/locales/doorkeeper.id.yml b/config/locales/doorkeeper.id.yml index 3f9a409c21c087..cccabc07012dc5 100644 --- a/config/locales/doorkeeper.id.yml +++ b/config/locales/doorkeeper.id.yml @@ -60,7 +60,6 @@ id: error: title: Ada yang error new: - prompt_html: "%{client_name} meminta izin untuk mengakses akun Anda. Ini adalah aplikasi pihak ketiga. Jika Anda tidak mempercayainya, Anda boleh tidak mengizinkannya." review_permissions: Tinjau izin title: Izin diperlukan show: diff --git a/config/locales/doorkeeper.ie.yml b/config/locales/doorkeeper.ie.yml index 0119f3573f13b3..6d8951b326e843 100644 --- a/config/locales/doorkeeper.ie.yml +++ b/config/locales/doorkeeper.ie.yml @@ -60,7 +60,6 @@ ie: error: title: Alquo ha errat new: - prompt_html: "%{client_name}, un aplication de triesim partise, vole permission por accesser tui conto. Si tu ne fide it, ne autorisa it." review_permissions: Inspecter permissiones title: Autorisation besonat show: diff --git a/config/locales/doorkeeper.io.yml b/config/locales/doorkeeper.io.yml index a71fa95841378e..0384d968beb3d6 100644 --- a/config/locales/doorkeeper.io.yml +++ b/config/locales/doorkeeper.io.yml @@ -60,7 +60,6 @@ io: error: title: Eroro eventis new: - prompt_html: "%{client_name} volas permiso por acesar vua konti. Ol esas externa softwaro. Se vu ne fidas, lore vu debas ne yurizar." review_permissions: Kontrolez permisi title: Yurizo bezonesas show: diff --git a/config/locales/doorkeeper.is.yml b/config/locales/doorkeeper.is.yml index 01093f44298a42..05f2415eea537a 100644 --- a/config/locales/doorkeeper.is.yml +++ b/config/locales/doorkeeper.is.yml @@ -60,7 +60,6 @@ is: error: title: Villa kom upp new: - prompt_html: "%{client_name} biður um heimild til að fara inn á notandaaðganginn þinn. Þetta er utanaðkomandi hugbúnaður. Ef þú treystir ekki viðkomandi, þá ættir þú ekki að heimila þetta." review_permissions: Yfirfara heimildir title: Auðkenning er nauðsynleg show: diff --git a/config/locales/doorkeeper.it.yml b/config/locales/doorkeeper.it.yml index 9654cb2a20b1a3..3a24465cdc2c43 100644 --- a/config/locales/doorkeeper.it.yml +++ b/config/locales/doorkeeper.it.yml @@ -60,7 +60,7 @@ it: error: title: Si è verificato un errore new: - prompt_html: "%{client_name} vorrebbe l'autorizzazione ad accedere al tuo profilo. È un'applicazione di terze parti. Se non ti fidi, non dovresti autorizzarla." + prompt_html: "%{client_name} vorrebbe il permesso di accedere al tuo account. Approva questa richiesta solo se riconosci e ti fidi di questa fonte." review_permissions: Revisiona le autorizzazioni title: Autorizzazione necessaria show: diff --git a/config/locales/doorkeeper.ja.yml b/config/locales/doorkeeper.ja.yml index 38c4d2c1aa9ad4..7cfddf50a16c65 100644 --- a/config/locales/doorkeeper.ja.yml +++ b/config/locales/doorkeeper.ja.yml @@ -60,7 +60,6 @@ ja: error: title: エラーが発生しました new: - prompt_html: "%{client_name}があなたのアカウントにアクセスする許可を求めています。心当たりが無い場合はアクセス許可しないでください。" review_permissions: アクセス許可を確認 title: 認証が必要です show: diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml index 13d8d93258dc35..fa9e1c540ad236 100644 --- a/config/locales/doorkeeper.kab.yml +++ b/config/locales/doorkeeper.kab.yml @@ -125,10 +125,10 @@ kab: title: Tlaq tsiregt n OAuth scopes: admin:read: ad iɣeṛ akk isefka ɣef uqeddac - admin:write: ẓreg akk isefka γef uqeddac - follow: beddel assaγen n umiḍan - push: ṭṭef-d alɣuten-ik·im yettwademren - read: γeṛ akk isefka n umiḍan-ik + admin:write: ad iẓreg akk isefka ɣef uqeddac + follow: ad ibeddel assaɣen n umiḍan + push: ad iṭṭef-d alɣuten-ik·im yettwademren + read: ad iɣeṛ akk isefka n umiḍan-ik·im read:accounts: ẓer isallen n yimiḍanen read:blocks: ẓer imiḍanen i tesḥebseḍ read:bookmarks: ẓer ticraḍ-ik @@ -139,10 +139,10 @@ kab: read:notifications: ad iẓer alɣuten-inek·inem read:reports: ẓer ineqqisen-ik·im read:search: anadi deg umkan-ik·im - read:statuses: ẓer meṛṛa tisuffaɣ + read:statuses: ad iẓer meṛṛa tisuffaɣ write: beddel meṛṛa isefka n umiḍan-ik write:accounts: ad iẓreg amaɣnu-ik·im - write:blocks: seḥbes imiḍanen d tγula + write:blocks: ad iseḥbes imiḍanen akked tɣula write:bookmarks: ad yernu tisuffaɣ ɣer ticraḍ write:filters: ad isnulfu imsizedgen write:follows: ḍfeṛ imdanen diff --git a/config/locales/doorkeeper.ko.yml b/config/locales/doorkeeper.ko.yml index f35333f1df3859..dc1b8c08b1baa5 100644 --- a/config/locales/doorkeeper.ko.yml +++ b/config/locales/doorkeeper.ko.yml @@ -60,7 +60,7 @@ ko: error: title: 오류가 발생하였습니다 new: - prompt_html: "%{client_name} 제3자 애플리케이션이 귀하의 계정에 접근하기 위한 권한을 요청하고 있습니다. 이 애플리케이션을 신뢰할 수 없다면 이 요청을 승인하지 마십시오." + prompt_html: "%{client_name}이 계정에 접근할 권한을 요청합니다. 내가 알아볼 수 있고 신뢰할 수 있는 출처의 요청인 경우에만 승인하세요." review_permissions: 권한 검토 title: 승인 필요 show: diff --git a/config/locales/doorkeeper.ku.yml b/config/locales/doorkeeper.ku.yml index e3438eb5de0c5b..be6f0587c982a5 100644 --- a/config/locales/doorkeeper.ku.yml +++ b/config/locales/doorkeeper.ku.yml @@ -60,7 +60,6 @@ ku: error: title: Xeletîyek çêbû new: - prompt_html: "%{client_name} mafê dixwaze ku bigihîje ajimêrê te. Ew sepanek aliyê sêyemîn e. Ku tu pê bawer nakî, wê demê divê tu mafê gihiştinê nedî. " review_permissions: Gihiştinan binirxînin title: Destûr kirin pêwîst e show: diff --git a/config/locales/doorkeeper.lad.yml b/config/locales/doorkeeper.lad.yml index c335d67fd6ee09..678a53c91d3b00 100644 --- a/config/locales/doorkeeper.lad.yml +++ b/config/locales/doorkeeper.lad.yml @@ -60,7 +60,6 @@ lad: error: title: Un yerro tiene afitado new: - prompt_html: "%{client_name} kere permiso para akseder tu kuento. Es una aplikasyon de terseros. Si no konfias en eya, no deverias autorizarla." review_permissions: Reviza permisos title: Autorizasyon rekerida show: diff --git a/config/locales/doorkeeper.lt.yml b/config/locales/doorkeeper.lt.yml index 9b3b6558a42b1c..f957e4157ce95b 100644 --- a/config/locales/doorkeeper.lt.yml +++ b/config/locales/doorkeeper.lt.yml @@ -60,7 +60,7 @@ lt: error: title: Įvyko klaida. new: - prompt_html: "%{client_name} norėtų gauti leidimą pasiekti tavo paskyrą. Tai – trečiosios šalies programa. Jei ja nepasitiki, tada neturėtum leisti." + prompt_html: "%{client_name} norėtų gauti leidimą pasiekti tavo paskyrą. Patvirtink šį prašymą tik tada, jei atpažįsti šį šaltinį ir juo pasitiki." review_permissions: Peržiūrėti leidimus title: Privalomas leidimas show: diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml index 0f05adf1486c1b..55e288a9d67aa4 100644 --- a/config/locales/doorkeeper.lv.yml +++ b/config/locales/doorkeeper.lv.yml @@ -60,7 +60,6 @@ lv: error: title: Radās kļūda new: - prompt_html: "%{client_name} vēlas saņemt atļauju piekļūt tavam kontam. Tā ir trešās puses lietojumprogramma. Ja tu tam neuzticies, tad nevajadzētu to autorizēt." review_permissions: Pārskatīt atļaujas title: Nepieciešama autorizācija show: diff --git a/config/locales/doorkeeper.ms.yml b/config/locales/doorkeeper.ms.yml index 32fb0044bb4793..b52824e8c3d465 100644 --- a/config/locales/doorkeeper.ms.yml +++ b/config/locales/doorkeeper.ms.yml @@ -60,7 +60,6 @@ ms: error: title: Ralat telah berlaku new: - prompt_html: "%{client_name} ingin mendapatkan kebenaran untuk mengakses akaun anda. Ia adalah aplikasi pihak ketiga. Jika anda tidak mempercayainya, maka anda tidak seharusnya membenarkannya." review_permissions: Semak kebenaran title: Kebenaran diperlukan show: diff --git a/config/locales/doorkeeper.my.yml b/config/locales/doorkeeper.my.yml index bce6039eae14f7..0cfe50598233df 100644 --- a/config/locales/doorkeeper.my.yml +++ b/config/locales/doorkeeper.my.yml @@ -60,7 +60,6 @@ my: error: title: အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည် new: - prompt_html: "%{client_name} က သင့်အကောင့်သို့ ဝင်ရောက်ရန် ခွင့်ပြုချက်ရယူလိုပါသည်။ ၎င်းမှာ ပြင်ပကြားခံအက်ပလီကေးရှင်းတစ်ခုဖြစ်သည်။ သင် မယုံကြည်ပါက ၎င်းကိုခွင့်မပြုသင့်ပါ။" review_permissions: ခွင့်ပြုချက်များကို ပြန်လည်သုံးသပ်ပါ title: ခွင့်ပြုချက် လိုအပ်သည် show: diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml index 65ef826d387d8f..c6453761f144c6 100644 --- a/config/locales/doorkeeper.nl.yml +++ b/config/locales/doorkeeper.nl.yml @@ -60,7 +60,7 @@ nl: error: title: Er is een fout opgetreden new: - prompt_html: "%{client_name} heeft toestemming nodig om toegang te krijgen tot jouw account. Het betreft een third-party-toepassing.Als je dit niet vertrouwt, moet je geen toestemming verlenen." + prompt_html: "%{client_name} vraagt om toegang tot je account. Keur dit verzoek alleen goed als je deze bron herkent en vertrouwt." review_permissions: Toestemmingen beoordelen title: Autorisatie vereist show: diff --git a/config/locales/doorkeeper.nn.yml b/config/locales/doorkeeper.nn.yml index 975ceb43c712be..9b9ddba08d68db 100644 --- a/config/locales/doorkeeper.nn.yml +++ b/config/locales/doorkeeper.nn.yml @@ -60,7 +60,7 @@ nn: error: title: Ein feil har oppstått new: - prompt_html: "%{client_name} ønsker tilgang til kontoen din. Det er ein tredjepartsapplikasjon. Dersom du ikkje stolar på den, bør du ikkje autorisere det." + prompt_html: "%{client_name} ynskjer tilgang til kontoen din. Godkjenn dette berre dersom du kjenner att og stolar på %{client_name}." review_permissions: Sjå gjennom løyve title: Autorisasjon nødvendig show: diff --git a/config/locales/doorkeeper.no.yml b/config/locales/doorkeeper.no.yml index c432f6645cf98b..7b7b9d65342689 100644 --- a/config/locales/doorkeeper.no.yml +++ b/config/locales/doorkeeper.no.yml @@ -60,7 +60,6 @@ error: title: En feil oppstod new: - prompt_html: "%{client_name} ønsker tilgang til kontoen din. Det er en tredjeparts applikasjon. Hvis du ikke stoler på den, bør du ikke autorisere den." review_permissions: Gå gjennom tillatelser title: Autorisasjon påkrevd show: diff --git a/config/locales/doorkeeper.oc.yml b/config/locales/doorkeeper.oc.yml index 64bc3a43e2fb95..7f1155a839ea21 100644 --- a/config/locales/doorkeeper.oc.yml +++ b/config/locales/doorkeeper.oc.yml @@ -60,7 +60,6 @@ oc: error: title: I a agut un error new: - prompt_html: "%{client_name} volria l’autorizacion d’accedir a vòstre compte. Es una aplicacion tèrça.Se vos fisatz pas a ela, alara deuriatz pas l’autorizacion." review_permissions: Repassar las autorizacions title: Cal l’autorizacion show: diff --git a/config/locales/doorkeeper.pl.yml b/config/locales/doorkeeper.pl.yml index bf2da6f8083d76..2ff1bb5f4509c5 100644 --- a/config/locales/doorkeeper.pl.yml +++ b/config/locales/doorkeeper.pl.yml @@ -60,7 +60,7 @@ pl: error: title: Wystapił błąd new: - prompt_html: "%{client_name} chciałby uzyskać pozwolenie na dostęp do Twojego konta. Jest to aplikacja zewnętrzna. Jeśli jej nie ufasz, nie powinno się jej autoryzować." + prompt_html: "%{client_name} prosi o dostęp do twojego konta. Tylko zatwierdź tę prośbę, jeżeli ją rozpoznajesz i ufasz." review_permissions: Sprawdź uprawnienia title: Wymagana jest autoryzacja show: diff --git a/config/locales/doorkeeper.pt-BR.yml b/config/locales/doorkeeper.pt-BR.yml index c991850c68cc7a..85bf5d60c02a05 100644 --- a/config/locales/doorkeeper.pt-BR.yml +++ b/config/locales/doorkeeper.pt-BR.yml @@ -60,7 +60,7 @@ pt-BR: error: title: Ocorreu um erro new: - prompt_html: O %{client_name} gostaria de ter permissão para acessar sua conta. Trata-se de uma aplicação de terceiros. Se você não confia nesta aplicação, então você não deve autorizá-la. + prompt_html: "%{client_name} gostaria de permissão para acessar sua conta. Aprove esta solicitação apenas se você reconhecer e confiar nesta fonte." review_permissions: Rever permissões title: Autorização necessária show: diff --git a/config/locales/doorkeeper.pt-PT.yml b/config/locales/doorkeeper.pt-PT.yml index 3b4439584b01c1..e2ac275335fd59 100644 --- a/config/locales/doorkeeper.pt-PT.yml +++ b/config/locales/doorkeeper.pt-PT.yml @@ -60,7 +60,6 @@ pt-PT: error: title: Ocorreu um erro new: - prompt_html: "%{client_name} pretende ter permissão para aceder à sua conta. É uma aplicação de terceiros. Se não confia nesta aplicação, então não deve autorizá-la." review_permissions: Rever permissões title: Autorização necessária show: diff --git a/config/locales/doorkeeper.ro.yml b/config/locales/doorkeeper.ro.yml index 7091bcaf7b565e..9c02501eff7ca7 100644 --- a/config/locales/doorkeeper.ro.yml +++ b/config/locales/doorkeeper.ro.yml @@ -60,7 +60,6 @@ ro: error: title: A apărut o eroare new: - prompt_html: "%{client_name} dorește să îți acceseze contul. Este o aplicație terță. Dacă nu aveți încredere în ea, atunci nu ar trebui să o autorizați." review_permissions: Revizuiți permisiunile title: Autorizare necesară show: diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml index 12b7e7e87e0b45..1dcb2093d517d2 100644 --- a/config/locales/doorkeeper.ru.yml +++ b/config/locales/doorkeeper.ru.yml @@ -60,7 +60,6 @@ ru: error: title: Произошла ошибка new: - prompt_html: "%{client_name} хочет получить доступ к вашему аккаунту. Это стороннее приложение. Если вы ему не доверяете, не разрешайте доступ." review_permissions: Просмотр разрешений title: Требуется авторизация show: diff --git a/config/locales/doorkeeper.sco.yml b/config/locales/doorkeeper.sco.yml index 70341c3c691123..6e54c53ca508ca 100644 --- a/config/locales/doorkeeper.sco.yml +++ b/config/locales/doorkeeper.sco.yml @@ -60,7 +60,6 @@ sco: error: title: A error haes occurrt new: - prompt_html: "%{client_name} wad like permission fir tae access yer accoont. It is a third-party application. Gin ye dinnae trust it, then ye shuidnae authorize it." review_permissions: Luik ower permissions title: Authorization requirt show: diff --git a/config/locales/doorkeeper.si.yml b/config/locales/doorkeeper.si.yml index d3550cf5989b78..43a109b194cb77 100644 --- a/config/locales/doorkeeper.si.yml +++ b/config/locales/doorkeeper.si.yml @@ -60,7 +60,6 @@ si: error: title: දෝෂයක් සිදු වී ඇත new: - prompt_html: "%{client_name} ඔබගේ ගිණුමට ප්‍රවේශ වීමට අවසර ලබා ගැනීමට කැමති වේ. එය තෙවන පාර්ශවීය යෙදුමකි. ඔබ එය විශ්වාස නොකරන්නේ නම්, ඔබ එයට අවසර නොදිය යුතුය." review_permissions: අවසර සමාලෝචනය title: බලය පැවරීමේ අවශ්ය show: diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml index face9db96668f5..774a2648f9807c 100644 --- a/config/locales/doorkeeper.sk.yml +++ b/config/locales/doorkeeper.sk.yml @@ -60,7 +60,6 @@ sk: error: title: Nastala chyba new: - prompt_html: "%{client_name} žiada o povolenie na prístup k vášmu účtu. Ide o aplikáciu tretej strany. Ak jej nedôverujete, nemali by ste ju povoliť." review_permissions: Preskúmať povolenia title: Je potrebné schválenie show: diff --git a/config/locales/doorkeeper.sl.yml b/config/locales/doorkeeper.sl.yml index f6f64fc87fa0f2..3f36c7375643e3 100644 --- a/config/locales/doorkeeper.sl.yml +++ b/config/locales/doorkeeper.sl.yml @@ -60,7 +60,6 @@ sl: error: title: Prišlo je do napake new: - prompt_html: "%{client_name} želi dovoljenje za dostop do vašega računa. Gre za zunanji program. Če mu ne zaupate, mu ne dodelite teh pravic." review_permissions: Preglej dovoljenja title: Potrebna je odobritev show: diff --git a/config/locales/doorkeeper.sq.yml b/config/locales/doorkeeper.sq.yml index 651f90b3b4ce42..f98cf88c630c87 100644 --- a/config/locales/doorkeeper.sq.yml +++ b/config/locales/doorkeeper.sq.yml @@ -60,7 +60,7 @@ sq: error: title: Ndodhi një gabim new: - prompt_html: "%{client_name} do të donte leje të hyjë në llogarinë tuaj. Është një aplikacion palësh të treta. Nëse s’i zini besë, atëherë s’duhet ta autorizoni." + prompt_html: "%{client_name} do të donte leje të hyjë në llogarinë tuaj. Miratojeni këtë kërkesë vetëm nëse e njihni dhe e besoni këtë burim." review_permissions: Shqyrtoni leje title: Lypset autorizim show: diff --git a/config/locales/doorkeeper.sr-Latn.yml b/config/locales/doorkeeper.sr-Latn.yml index 89e84344fd43fa..bce2b1c08371c6 100644 --- a/config/locales/doorkeeper.sr-Latn.yml +++ b/config/locales/doorkeeper.sr-Latn.yml @@ -60,7 +60,6 @@ sr-Latn: error: title: Dogodila se greška new: - prompt_html: "%{client_name} želi dozvolu za pristup tvom nalogu. U pitanju je aplikacija treće strane. Ako smatraš da nije pouzdana, ne bi trebalo da je ovlastiš." review_permissions: Pregledaj dozvole title: Potrebna autorizacija show: diff --git a/config/locales/doorkeeper.sr.yml b/config/locales/doorkeeper.sr.yml index 63b940478495d2..b6ab6e61c0914a 100644 --- a/config/locales/doorkeeper.sr.yml +++ b/config/locales/doorkeeper.sr.yml @@ -60,7 +60,6 @@ sr: error: title: Догодила се грешка new: - prompt_html: "%{client_name} жели дозволу за приступ твом налогу. У питању је апликација треће стране. Ако сматраш да није поуздана, не би требало да је овластиш." review_permissions: Прегледај дозволе title: Потребна ауторизација show: diff --git a/config/locales/doorkeeper.sv.yml b/config/locales/doorkeeper.sv.yml index 83927d10977bd8..9f646fd3e4b454 100644 --- a/config/locales/doorkeeper.sv.yml +++ b/config/locales/doorkeeper.sv.yml @@ -60,7 +60,6 @@ sv: error: title: Ett fel har uppstått new: - prompt_html: "%{client_name} vill ha behörighet att komma åt ditt konto. Det är en applikation från tredje part. Du bör endast godkänna den om du litar på den." review_permissions: Granska behörigheter title: Godkännande krävs show: diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml index 3735386ba3831f..e7ed0ba8a3bdb5 100644 --- a/config/locales/doorkeeper.th.yml +++ b/config/locales/doorkeeper.th.yml @@ -60,7 +60,6 @@ th: error: title: เกิดข้อผิดพลาด new: - prompt_html: "%{client_name} ต้องการสิทธิอนุญาตเพื่อเข้าถึงบัญชีของคุณ แอปพลิเคชันเป็นแอปพลิเคชันจากบุคคลที่สาม หากคุณไม่เชื่อถือแอปพลิเคชัน คุณไม่ควรอนุญาตแอปพลิเคชัน" review_permissions: ตรวจทานสิทธิอนุญาต title: ต้องการการอนุญาต show: diff --git a/config/locales/doorkeeper.tr.yml b/config/locales/doorkeeper.tr.yml index 41996d96035b32..f7f67564d20949 100644 --- a/config/locales/doorkeeper.tr.yml +++ b/config/locales/doorkeeper.tr.yml @@ -60,7 +60,7 @@ tr: error: title: Bir hata oluştu new: - prompt_html: "%{client_name} hesabınıza erişme izni istiyor. Bu üçüncü taraf bir uygulamadır. Eğer güvenmiyorsanız, izin vermemelisiniz." + prompt_html: "%{client_name} hesabınıze erişmek için izin istiyor. Bu isteği sadece bu kaynağı tanıyor ve güveniyorsanız onaylayın." review_permissions: İzinleri incele title: İzin gerekli show: diff --git a/config/locales/doorkeeper.uk.yml b/config/locales/doorkeeper.uk.yml index 55b91fd69dabdc..1e18eaef9a1918 100644 --- a/config/locales/doorkeeper.uk.yml +++ b/config/locales/doorkeeper.uk.yml @@ -60,7 +60,7 @@ uk: error: title: Сталася помилка new: - prompt_html: "%{client_name} хоче отримати доступ до вашого облікового запису. Це сторонній застосунок. Якщо ви йому не довіряєте, не варто авторизувати його." + prompt_html: "%{client_name} хоче отримати дозвіл на доступ до вашого облікового запису. Схвалюйте цей запит, якщо ви впізнаєте це джерело і довіряєте йому." review_permissions: Переглянути дозволи title: Необхідна авторизація show: diff --git a/config/locales/doorkeeper.vi.yml b/config/locales/doorkeeper.vi.yml index 5837961737aa63..6687c0339d3388 100644 --- a/config/locales/doorkeeper.vi.yml +++ b/config/locales/doorkeeper.vi.yml @@ -60,7 +60,7 @@ vi: error: title: Một lỗi đã xảy ra new: - prompt_html: "%{client_name} yêu cầu truy cập tài khoản của bạn. Đây là ứng dụng của bên thứ ba. Nếu không tin tưởng, đừng cho phép nó." + prompt_html: "%{client_name} cần được bạn cho phép truy cập vào tài khoản. Cho phép nếu bạn tin tưởng ứng dụng này." review_permissions: Quyền truy cập title: Yêu cầu truy cập show: @@ -71,7 +71,7 @@ vi: confirmations: revoke: Bạn có chắc không? index: - authorized_at: Cho phép %{date} + authorized_at: Cho phép vào %{date} description_html: Đây là những ứng dụng có thể truy cập tài khoản của bạn bằng API. Nếu có ứng dụng bạn không nhận ra ở đây hoặc ứng dụng hoạt động sai, bạn có thể thu hồi quyền truy cập của ứng dụng đó. last_used_at: Dùng lần cuối %{date} never_used: Chưa dùng @@ -151,7 +151,7 @@ vi: scopes: admin:read: đọc mọi dữ liệu trên máy chủ admin:read:accounts: đọc thông tin nhạy cảm của tất cả các tài khoản - admin:read:canonical_email_blocks: đọc thông tin nhạy cảm của tất cả các khối email chuẩn + admin:read:canonical_email_blocks: đọc thông tin nhạy cảm của tất cả khối email chuẩn admin:read:domain_allows: đọc thông tin nhạy cảm của tất cả các tên miền cho phép admin:read:domain_blocks: đọc thông tin nhạy cảm của tất cả các tên miền chặn admin:read:email_domain_blocks: đọc thông tin nhạy cảm của tất cả các miền email chặn diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml index ee8c0cf13aa098..46253d01b3f57c 100644 --- a/config/locales/doorkeeper.zh-CN.yml +++ b/config/locales/doorkeeper.zh-CN.yml @@ -60,7 +60,7 @@ zh-CN: error: title: 发生错误 new: - prompt_html: "%{client_name} 希望得到访问你账号的许可。这是一个第三方应用。如果你不信任它,那么你不应该授权它。" + prompt_html: "%{client_name} 请求获得访问您账户的权限。 请在确保自己了解并信任此来源后再批准该请求。" review_permissions: 检查权限 title: 需要授权 show: diff --git a/config/locales/doorkeeper.zh-HK.yml b/config/locales/doorkeeper.zh-HK.yml index 79629b12febf39..4450cfc1a4b242 100644 --- a/config/locales/doorkeeper.zh-HK.yml +++ b/config/locales/doorkeeper.zh-HK.yml @@ -60,7 +60,6 @@ zh-HK: error: title: 發生錯誤 new: - prompt_html: "%{client_name} 想得到存取你帳號的權限。這是一個第三方應用程式。如果你不信任它,請勿授權。" review_permissions: 檢視權限 title: 需要用戶授權 show: diff --git a/config/locales/doorkeeper.zh-TW.yml b/config/locales/doorkeeper.zh-TW.yml index 2759f0a3d26d02..5af93e1e07b72e 100644 --- a/config/locales/doorkeeper.zh-TW.yml +++ b/config/locales/doorkeeper.zh-TW.yml @@ -60,7 +60,7 @@ zh-TW: error: title: 發生錯誤 new: - prompt_html: "%{client_name} 欲請求存取您帳號之權限。這是一個第三方應用程式。若您不信任該應用程式,請不要授權。" + prompt_html: "%{client_name} 想要請求存取您帳號之權限。請僅於您所識別且信任此來源時允許請求。" review_permissions: 檢視權限 title: 需要授權 show: diff --git a/config/locales/el.yml b/config/locales/el.yml index 0da957cdb28de7..610ae4026512a7 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -24,6 +24,8 @@ el: admin: account_actions: action: Εκτέλεση ενέργειας + already_silenced: Αυτός ο λογαριασμός έχει ήδη περιοριστεί. + already_suspended: Αυτός ο λογαριασμός έχει ήδη ανασταλεί. title: Εκτέλεση ενέργειας συντονισμού στον %{acct} account_moderation_notes: create: Άφησε σημείωση @@ -45,6 +47,7 @@ el: title: Αλλαγή email για %{username} change_role: changed_msg: Ο ρόλος άλλαξε επιτυχώς! + edit_roles: Διαχείριση ρόλων χρήστη label: Αλλαγή ρόλου no_role: Κανένας ρόλος title: Αλλαγή ρόλου για %{username} @@ -1601,7 +1604,6 @@ el: delete: Διαγραφή λογαριασμού development: Ανάπτυξη edit_profile: Επεξεργασία προφίλ - export: Εξαγωγή δεδομένων featured_tags: Παρεχόμενες ετικέτες import: Εισαγωγή import_and_export: Εισαγωγή και εξαγωγή diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 577978ce88d54f..fbd48d1c316097 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1692,7 +1692,7 @@ en-GB: delete: Account deletion development: Development edit_profile: Edit profile - export: Data export + export: Export featured_tags: Featured hashtags import: Import import_and_export: Import and export diff --git a/config/locales/en.yml b/config/locales/en.yml index b92a563f8ea960..f00c3ce1403bd9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -875,6 +875,9 @@ en: message_html: You haven't defined any server rules. sidekiq_process_check: message_html: No Sidekiq process running for the %{value} queue(s). Please review your Sidekiq configuration + software_version_check: + action: See available updates + message_html: A Mastodon update is available. software_version_critical_check: action: See available updates message_html: A critical Mastodon update is available, please update as quickly as possible. @@ -1693,7 +1696,7 @@ en: delete: Account deletion development: Development edit_profile: Edit profile - export: Data export + export: Export featured_tags: Featured hashtags import: Import import_and_export: Import and export diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 7ebf0748194067..a3f968d1396bad 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -24,12 +24,15 @@ eo: admin: account_actions: action: Plenumi agon + already_silenced: Ĉi tiu konto jam estis limigita. + already_suspended: Ĉi tiu konto jam estis suspendita. title: Plenumi kontrolan agon al %{acct} account_moderation_notes: create: Lasi noton created_msg: Noto de moderigado sukcese kreita! destroyed_msg: Noto de moderigado sukcese detruita! accounts: + add_email_domain_block: Bloki retpoŝtan domajnon approve: Aprobi approved_msg: Sukcese aprobis aliĝ-peton de %{username} are_you_sure: Ĉu vi certas? @@ -44,6 +47,7 @@ eo: title: Ŝanĝi retadreson por %{username} change_role: changed_msg: Rolo sukcese ŝanĝita! + edit_roles: Administri uzantrolojn label: Ŝanĝi rolon no_role: Neniu rolo title: Ŝanĝi rolon por %{username} @@ -271,6 +275,7 @@ eo: filter_by_action: Filtri per ago filter_by_user: Filtri per uzanto title: Ĵurnalo de revizo + unavailable_instance: "(domajna nomo nedisponebla)" announcements: destroyed_msg: Anonco sukcese forigita! edit: @@ -408,6 +413,7 @@ eo: attempts_over_week: one: "%{count} provo ekde lasta semajno" other: "%{count} registroprovoj ekde lasta semajno" + created_msg: Sukcese blokita retpoŝta domajno delete: Forigi dns: types: @@ -416,6 +422,7 @@ eo: new: create: Aldoni domajnon resolve: Solvi domajnon + title: Bloki novan retpoŝtan domajnon not_permitted: Ne permesita resolved_through_html: Solvis tra %{domain} export_domain_allows: @@ -568,6 +575,7 @@ eo: silence_description_html: La konto estos videbla al nur personoj kiu jam sekvis ĝin au permane serĉo ĝin, ege limigante ĝian atingon. Malfermi ciujn raportojn kontra ĉi tiun konton. suspend_description_html: La konto kaj ciuj ĝiaj enhavoj estos neatingebla kaj poŝte forigitas, kaj interagi per ĝi estos neebla. Malfermi ciujn raportojn kontra ĉi tiu konto. actions_description_remote_html: Decidu kiun klopodon por solvi ĉi tiun raporton. Ĉi tiu efikas kiel nur via servilo komuniki per ĉi tiu fora konto kaj trakti ĝian enhavon. + actions_no_posts: Ĉi tiu raporto havas neniujn rilatajn afiŝojn por forigi add_to_report: Aldoni pli al raporto are_you_sure: Ĉu vi certas? assign_to_self: Asigni al mi @@ -604,6 +612,7 @@ eo: report: 'Signalo #%{id}' reported_account: Signalita konto reported_by: Signalita de + reported_with_application: Raportita per aplikaĵo resolved: Solvitaj resolved_msg: Signalo sukcese solvita! skip_to_actions: Salti al agoj @@ -800,6 +809,8 @@ eo: message_html: Estas pritraktataj datumbazaj migradoj. Bonvolu ekzekuti ilin por certigi, ke la apliko kondutas kiel atendite elasticsearch_preset: action: Legi dokumentaron + elasticsearch_preset_single_node: + action: Vidi dokumentadon elasticsearch_running_check: message_html: Ne eblas konekti Elasticsearch. Bonvolu kontroli ke ĝi funkcias, aǔ malŝaltu plentekstan serĉon elasticsearch_version_check: @@ -810,6 +821,12 @@ eo: message_html: Vi ne difinis iujn servilajn regulojn. sidekiq_process_check: message_html: Neniu Sidekiq-procezo por la %{value} vico + software_version_check: + message_html: Mastodon-ĝisdatigo disponeblas. + software_version_critical_check: + action: Vidi disponeblajn ĝisdatigojn + software_version_patch_check: + action: Vidi disponeblajn ĝisdatigojn upload_check_privacy_error: action: Klaku ĉi tie por pliaj informoj message_html: "Via retservilo estas misagordita. La privateco de viaj uzantoj estas en risko." @@ -817,16 +834,27 @@ eo: action: Klaku ĉi tie por pliaj informoj message_html: "Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko." tags: + moderation: + title: Stato + name: Nomo + newest: Plej novaj + oldest: Plej malnovaj review: La statuso de la recenzo + search: Serĉi + title: Kradvortoj updated_msg: Kradvorto agordoj ĝisdatigis sukcese title: Administrado trends: allow: Permesi approved: Aprobita + confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn etikedojn? + confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn etikedojn? disallow: Malpermesi links: allow: Permesi ligilon allow_provider: Permesi publikiganto + confirm_allow: Ĉu vi certas, ke vi volas permesi elektitajn ligilojn? + confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn ligilojn? description_html: Ĉioj estas ligiloj kiuj nun diskonitajs multe de kontoj kiujn via servilo vidas. Ligiloj ne montritas publike se vi ne aprobis la publikiganton. disallow: Malpermesi ligilon disallow_provider: Malpermesi publikiganton @@ -850,6 +878,8 @@ eo: statuses: allow: Permesi afiŝon allow_account: Permesi aŭtoron + confirm_allow_account: Ĉu vi certas, ke vi volas permesi elektitajn kontojn? + confirm_disallow_account: Ĉu vi certas, ke vi volas malpermesi elektitajn kontojn? description_html: Oni multe diskonigas kaj stelumas ĉi tiujn mesaĝojn nuntempe laŭ via servilo. Tio povas helpi novajn kaj revenantajn uzantojn trovi pli da homoj por sekvi. Mesaĝo estas montrita publike nur se vi aprobis la aŭtoron kaj se la aŭtoro aprobis ke ties konto estu proponita al aliaj. Vi ankaŭ povas permesi aŭ malakcepti specifajn mesaĝojn. disallow: Malpermesi afiŝon disallow_account: Malpermesi aŭtoron @@ -928,6 +958,8 @@ eo: body: "%{reporter} signalis %{target}" body_remote: Iu de %{domain} signalis %{target} subject: Nova signalo por %{instance} (#%{id}) + new_software_updates: + body: Novaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi! new_trends: body: 'La eroj bezonas kontrolon antau ol ili povas montritas publike:' new_trending_links: @@ -956,7 +988,9 @@ eo: guide_link_text: Ĉiu povas kontribui. sensitive_content: Tikla enhavo application_mailer: + notification_preferences: Ŝanĝi retpoŝtajn preferojn salutation: "%{name}," + settings: 'Ŝanĝi retpoŝtajn preferojn: %{link}' unsubscribe: Malabonu view: 'Vidi:' view_profile: Vidi profilon @@ -975,8 +1009,11 @@ eo: help_html: Se vi havas problemojn solvi la CAPTCHA, vi povas kontakti nin per %{email} kaj ni povas helpi vin. title: Sekureckontrolo confirmations: + clicking_this_link: alklakante ĉi tiun ligilon login_link: ensaluti + registration_complete: Via registriĝo sur %{domain} nun finiĝis! welcome_title: Bonvenon, %{name}! + wrong_email_hint: Se tiu retadreso ne estas ĝusta, vi povas ŝanĝi ĝin en kontagordoj. delete_account: Forigi konton delete_account_html: Se vi deziras forigi vian konton, vi povas fari tion ĉi tie. Vi bezonos konfirmi vian peton. description: @@ -997,6 +1034,7 @@ eo: or_log_in_with: Aŭ saluti per privacy_policy_agreement_html: Mi legis kaj konsentis pri privatpolitiko progress: + confirm: Konfirmi retadreson details: Viaj detaloj review: Niaj recenzoj rules: Akcepti regulojn @@ -1033,6 +1071,11 @@ eo: view_strikes: Vidi antauaj admonoj kontra via konto too_fast: Formularo sendita tro rapide, klopodu denove. use_security_key: Uzi sekurecan ŝlosilon + author_attribution: + example_title: Ekzempla teksto + more_from_html: Pli de %{name} + s_blog: Blogo de %{name} + title: Atribuo de aŭtoro challenge: confirm: Daŭrigi hint_html: "Konsileto: Ni ne demandos pri via pasvorto ĝis 1 horo." @@ -1228,9 +1271,12 @@ eo: overwrite: Anstataŭigi overwrite_long: Anstataŭigi la nunajn registrojn per la novaj preface: Vi povas importi datumojn, kiujn vi eksportis el alia servilo, kiel liston de homoj, kiujn vi sekvas aŭ blokas. + recent_imports: Lastatempaj importoj states: finished: Finita + in_progress: Farata unconfirmed: Nekonfirmita + status: Stato success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite titles: following: Importado de sekvaj kontoj @@ -1518,7 +1564,6 @@ eo: delete: Konta forigo development: Evoluigado edit_profile: Redakti profilon - export: Eksporti datumojn featured_tags: Elstarigitaj kradvortoj import: Enporti import_and_export: Importi kaj eksporti @@ -1530,6 +1575,9 @@ eo: strikes: Kontroladmonoj two_factor_authentication: Dufaktora aŭtentigo webauthn_authentication: Sekurecaj ŝlosiloj + severed_relationships: + lost_followers: Perditaj sekvantoj + type: Evento statuses: attached: audio: @@ -1689,7 +1737,19 @@ eo: silence: Konto limigita suspend: Konto suspendita welcome: + apps_step: Elŝutu niajn oficialajn aplikaĵojn. + apps_title: Aplikaĵoj de Mastodon + edit_profile_action: Agordi + edit_profile_title: Agordi vian profilon explanation: Jen kelkaj konsiloj por helpi vin komenci + feature_action: Lerni pli + follow_action: Sekvi + hashtags_title: Popularaj kradvortoj + hashtags_view_more: Vidi pli da popularaj kradvortoj + post_step: Salutu la mondon per teksto, fotoj, filmetoj aŭ balotenketoj. + post_title: Faru vian unuan afiŝon + share_step: Sciigu viajn amikojn kiel trovi vin sur Mastodon. + sign_in_action: Ensaluti subject: Bonvenon en Mastodon title: Bonvenon, %{name}! users: diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 9f1dc46c9df8ce..49b8f288fa0436 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -875,6 +875,9 @@ es-AR: message_html: No definiste ninguna regla del servidor. sidekiq_process_check: message_html: No hay ningún proceso Sidekiq en ejecución para la/s cola/s %{value}. Por favor, revisá tu configuración de Sidekiq + software_version_check: + action: Ver actualizaciones disponibles + message_html: Hay disponible una actualización de Mastodon. software_version_critical_check: action: Ver actualizaciones disponibles message_html: Una actualización crítica de Mastodon está disponible; por favor, actualizá lo antes posible. @@ -1692,7 +1695,7 @@ es-AR: delete: Eliminación de la cuenta development: Desarrollo edit_profile: Editar perfil - export: Exportación de datos + export: Exportar featured_tags: Etiquetas destacadas import: Importar import_and_export: Importación y exportación diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 8aac7cbb47b2c2..0f4c8452c007dc 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -875,6 +875,9 @@ es-MX: message_html: No ha definido ninguna regla del servidor. sidekiq_process_check: message_html: No hay ningún proceso Sidekiq en ejecución para la(s) cola(s) %{value}. Por favor, revise su configuración de Sidekiq + software_version_check: + action: Ver actualizaciones disponibles + message_html: Hay disponible una actualización de Mastodon. software_version_critical_check: action: Ver actualizaciones disponibles message_html: Una actualización crítica de Mastodon está disponible, por favor actualice lo antes posible. @@ -1203,7 +1206,7 @@ es-MX: caches: El contenido que ha sido almacenado en caché por otros servidores puede persistir data_removal: Tus publicaciones y el resto de datos se eliminarán definitivamente email_change_html: Puedes cambiar tu dirección de correo electrónico sin eliminar tu cuenta - email_contact_html: Si aún no te ha llegado, puedes escribir a %{email} para pedir ayuda + email_contact_html: Si todavía no te ha llegado, puedes escribir a %{email} para pedir ayuda email_reconfirmation_html: Si no te ha llegado el correo de confirmación, puedes volver a solicitarlo irreversible: No podrás restaurar ni reactivar tu cuenta more_details_html: Para más detalles, ver la política de privacidad. @@ -1692,7 +1695,7 @@ es-MX: delete: Borrar cuenta development: Desarrollo edit_profile: Editar perfil - export: Exportar información + export: Exportar featured_tags: Hashtags destacados import: Importar import_and_export: Importar y exportar diff --git a/config/locales/es.yml b/config/locales/es.yml index 2815ada77957ce..aa18e7b52eb916 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -875,6 +875,9 @@ es: message_html: No ha definido ninguna regla del servidor. sidekiq_process_check: message_html: No hay ningún proceso Sidekiq en ejecución para la(s) cola(s) %{value}. Por favor, revise su configuración de Sidekiq + software_version_check: + action: Ver actualizaciones disponibles + message_html: Hay disponible una actualización de Mastodon. software_version_critical_check: action: Ver actualizaciones disponibles message_html: Una actualización crítica de Mastodon está disponible, por favor actualiza lo antes posible. @@ -1692,7 +1695,7 @@ es: delete: Borrar cuenta development: Desarrollo edit_profile: Editar perfil - export: Exportar información + export: Exportar featured_tags: Hashtags destacados import: Importar import_and_export: Importar y exportar diff --git a/config/locales/et.yml b/config/locales/et.yml index 60f98a471e37a2..b71e3ccb6878a9 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1692,7 +1692,6 @@ et: delete: Konto kustutamine development: Arendus edit_profile: Muuda profiili - export: Andmete eksportimine featured_tags: Esile toodud sildid import: Impordi import_and_export: Import / eksport diff --git a/config/locales/eu.yml b/config/locales/eu.yml index 7c7f995a7143b1..e80207d46fc945 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1592,7 +1592,6 @@ eu: delete: Kontuaren ezabaketa development: Garapena edit_profile: Editatu profila - export: Datuen esportazioa featured_tags: Nabarmendutako traolak import: Inportazioa import_and_export: Inportatu eta esportatu diff --git a/config/locales/fa.yml b/config/locales/fa.yml index c2c22af4c46a51..e7d932de113a84 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -1438,7 +1438,6 @@ fa: delete: پاک‌کردن حساب development: فرابری edit_profile: ویرایش نمایه - export: برون‌سپاری داده‌ها featured_tags: برچسب‌های برگزیده import: درون‌ریزی import_and_export: درون‌ریزی و برون‌بری diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 5df82bff9fa440..22ccc711612746 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -875,6 +875,9 @@ fi: message_html: Et ole määritellyt palvelimen sääntöjä lainkaan. sidekiq_process_check: message_html: Ei ole Sidekiq-prosessia käynnissä jonossa %{value}. Tarkista Sidekiq-asetukset + software_version_check: + action: Näytä saatavilla olevat päivitykset + message_html: Saatavilla on Mastodon-päivitys. software_version_critical_check: action: Näytä saatavilla olevat päivitykset message_html: Kriittinen Mastodon-päivitys on saatavilla. Tee päivitys mahdollisimman ripeästi. @@ -1692,7 +1695,7 @@ fi: delete: Tilin poisto development: Kehitys edit_profile: Muokkaa profiilia - export: Vie tietoja + export: Vie featured_tags: Suositellut aihetunnisteet import: Tuo tietoja import_and_export: Tuonti ja vienti diff --git a/config/locales/fo.yml b/config/locales/fo.yml index ce21aa3be7c44f..31eb67b3b099af 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -875,6 +875,9 @@ fo: message_html: Tú hevur ikki ásett nakrar ambætarareglur. sidekiq_process_check: message_html: Eingin Sidekiq gongd koyrir fyri %{value} bíðirøðina(r). Vinarliga eftirkanna Sidekiq uppsetingina + software_version_check: + action: Sí tøkar dagføringar + message_html: Ein Mastodon-dagføring er tøk. software_version_critical_check: action: Sí tøkar dagføringar message_html: Ein kritisk Mastodon-dagføring er tøk, vinarliga dagfør sum skjótast. @@ -1692,7 +1695,7 @@ fo: delete: Striking av kontu development: Menning edit_profile: Rætta vanga - export: Útflyt dátur + export: Flyt út featured_tags: Varpaði frámerki import: Innflyt import_and_export: Innflyt og útflyt diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index 3f9252ffabff7b..16cdb79317cc5b 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -262,8 +262,10 @@ fr-CA: destroy_user_role_html: "%{name} a supprimé le rôle %{target}" disable_2fa_user_html: "%{name} a désactivé l'authentification à deux facteurs pour l'utilisateur·rice %{target}" disable_custom_emoji_html: "%{name} a désactivé l'émoji %{target}" + disable_sign_in_token_auth_user_html: "%{name} a désactivé l'authentification par jeton de courriel pour %{target}" disable_user_html: "%{name} a désactivé la connexion de l'utilisateur·rice %{target}" enable_custom_emoji_html: "%{name} a activé l'émoji %{target}" + enable_sign_in_token_auth_user_html: "%{name} a activé l'authentification par jeton de courriel pour %{target}" enable_user_html: "%{name} a activé la connexion de l'utilisateur·rice %{target}" memorialize_account_html: "%{name} a converti le compte de %{target} en un mémorial" promote_user_html: "%{name} a promu l'utilisateur·rice %{target}" @@ -876,6 +878,9 @@ fr-CA: message_html: Vous n'avez pas défini de règles pour le serveur. sidekiq_process_check: message_html: Aucun processus Sidekiq en cours d'exécution pour la/les file(s) d'attente %{value}. Veuillez vérifier votre configuration de Sidekiq + software_version_check: + action: Voir les mises à jour disponibles + message_html: Une mise à jour de Mastodon est disponible. software_version_critical_check: action: Voir les mises à jour disponibles message_html: Une mise à jour critique de Mastodon est disponible, veuillez mettre à jour le plus rapidement possible. @@ -1447,6 +1452,7 @@ fr-CA: unsubscribe: action: Oui, me désabonner complete: Désabonné·e + confirmation_html: Êtes-vous sûr de vouloir vous désabonner de la réception de %{type} pour Mastodon sur %{domain} à votre adresse e-mail %{email} ? Vous pouvez toujours vous réabonner à partir de vos paramètres de notification par messagerie. emails: notification_emails: favourite: e-mails de notifications de favoris @@ -1692,7 +1698,7 @@ fr-CA: delete: Suppression du compte development: Développement edit_profile: Modifier le profil - export: Export de données + export: Exportation featured_tags: Hashtags mis en avant import: Import de données import_and_export: Import et export diff --git a/config/locales/fr.yml b/config/locales/fr.yml index cb76ae2243c33d..bc57d00e658f37 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -262,8 +262,10 @@ fr: destroy_user_role_html: "%{name} a supprimé le rôle %{target}" disable_2fa_user_html: "%{name} a désactivé l'authentification à deux facteurs pour l'utilisateur·rice %{target}" disable_custom_emoji_html: "%{name} a désactivé l'émoji %{target}" + disable_sign_in_token_auth_user_html: "%{name} a désactivé l'authentification par jeton de courriel pour %{target}" disable_user_html: "%{name} a désactivé la connexion de l'utilisateur·rice %{target}" enable_custom_emoji_html: "%{name} a activé l'émoji %{target}" + enable_sign_in_token_auth_user_html: "%{name} a activé l'authentification par jeton de courriel pour %{target}" enable_user_html: "%{name} a activé la connexion de l'utilisateur·rice %{target}" memorialize_account_html: "%{name} a converti le compte de %{target} en un mémorial" promote_user_html: "%{name} a promu l'utilisateur·rice %{target}" @@ -427,7 +429,7 @@ fr: undo: Annuler le blocage de domaine view: Afficher les blocages de domaines email_domain_blocks: - add_new: Ajouter + add_new: Ajouter un nouveau allow_registrations_with_approval: Autoriser les inscriptions avec approbation attempts_over_week: one: "%{count} tentative au cours de la dernière semaine" @@ -876,6 +878,9 @@ fr: message_html: Vous n'avez pas défini de règles pour le serveur. sidekiq_process_check: message_html: Aucun processus Sidekiq en cours d'exécution pour la/les file(s) d'attente %{value}. Veuillez vérifier votre configuration de Sidekiq + software_version_check: + action: Voir les mises à jour disponibles + message_html: Une mise à jour de Mastodon est disponible. software_version_critical_check: action: Voir les mises à jour disponibles message_html: Une mise à jour critique de Mastodon est disponible, veuillez mettre à jour le plus rapidement possible. @@ -1447,6 +1452,7 @@ fr: unsubscribe: action: Oui, se désinscrire complete: Désinscrit + confirmation_html: Êtes-vous sûr de vouloir vous désabonner de la réception de %{type} pour Mastodon sur %{domain} à votre adresse e-mail %{email} ? Vous pouvez toujours vous réabonner à partir de vos paramètres de notification par messagerie. emails: notification_emails: favourite: e-mails de notifications de favoris @@ -1692,7 +1698,7 @@ fr: delete: Suppression du compte development: Développement edit_profile: Modifier le profil - export: Export de données + export: Exportation featured_tags: Hashtags mis en avant import: Import de données import_and_export: Import et export diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 8b854494d4b555..0379af34e9afc9 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -1682,7 +1682,6 @@ fy: delete: Account fuortsmite development: Untwikkelers edit_profile: Profyl bewurkje - export: Eksportearje featured_tags: Utljochte hashtags import: Ymportearje import_and_export: Ymportearje en eksportearje diff --git a/config/locales/ga.yml b/config/locales/ga.yml index a6369354cd8a56..e25865903ea365 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -917,6 +917,9 @@ ga: message_html: Níl aon rialacha freastalaí sainmhínithe agat. sidekiq_process_check: message_html: Níl próiseas Sidekiq ag rith don scuaine/(scuainí) %{value}. Déan athbhreithniú ar do chumraíocht Sidekiq + software_version_check: + action: Féach nuashonruithe atá ar fáil + message_html: Tá nuashonrú Mastodon ar fáil. software_version_critical_check: action: Féach nuashonruithe atá ar fáil message_html: Tá nuashonrú ríthábhachtach Mastodon ar fáil, nuashonraigh chomh tapa agus is féidir le do thoil. @@ -1770,7 +1773,7 @@ ga: delete: Scriosadh cuntais development: Forbairt edit_profile: Cuir an phróifíl in eagar - export: Easpórtáil sonraí + export: Easpórtáil featured_tags: Haischlib faoi thrácht import: Iompórtáil import_and_export: Iompórtáil agus easpórtáil diff --git a/config/locales/gd.yml b/config/locales/gd.yml index b5cbc4a73ed372..90d03c74e15fdb 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -1744,7 +1744,6 @@ gd: delete: Sguabadh às cunntais development: Leasachadh edit_profile: Deasaich a’ phròifil - export: Às-phortadh dàta featured_tags: Tagaichean hais brosnaichte import: Ion-phortadh import_and_export: Ion-phortadh ⁊ às-phortadh diff --git a/config/locales/gl.yml b/config/locales/gl.yml index 9813514a7bf6cf..e396761f7eb5d5 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -543,7 +543,7 @@ gl: total_reported: Denuncias sobre eles total_storage: Adxuntos multimedia totals_time_period_hint_html: Os totais aquí mostrados inclúen todo o historial de datos. - unknown_instance: Actualmente non temos constancia deste rexistro no servidor. + unknown_instance: Actualmente non hai rexistro deste dominio no servidor. invites: deactivate_all: Desactivar todo filter: @@ -602,7 +602,7 @@ gl: resolve_description_html: Non se van tomar accións contra a conta denunciada, nin se gardarán avisos, e pecharase a denuncia. silence_description_html: A conta será visible só para quen xa a está a seguir ou quen a buscou manualmente, limitando moito o seu alcance. Pódese cambiar. Isto pecha tódalas denuncias acerca desta conta. suspend_description_html: A conta e todo o seu contido non serán accesible e finalmente eliminaranse, será imposible interactuar con ela. A decisión é reversible durante 30 días. Isto pecha tódalas denuncias sobre esta conta. - actions_description_html: Decide a acción a tomar para resolver esta denuncia. Se tomas accións punitivas contra a conta denunciada enviaraselle un correo, excepto se está indicada a categoría Spam. + actions_description_html: Decide a acción a tomar para resolver esta denuncia. Se tomas accións punitivas contra a conta denunciada enviaráselle un correo, excepto se está indicada a categoría Spam. actions_description_remote_html: Decide a acción a tomar para resolver a denuncia. Isto só lle afecta ao xeito en que o teu servidor se comunica con esta conta remota e xestiona o seu contido. actions_no_posts: Esta denuncia non ten publicacións asociadas para eliminar add_to_report: Engadir máis á denuncia @@ -875,6 +875,9 @@ gl: message_html: Non tes definidas regras para o servidor. sidekiq_process_check: message_html: Non hai procesos Sidekiq a funcionar para a cola(s) %{value}. Revisa a túa configuración para Sidekiq + software_version_check: + action: Ver as actualizacións dispoñibles + message_html: Hai dispoñible unha actualización para Mastodon. software_version_critical_check: action: Mira as actualizacións dispoñibles message_html: Hai unha actualización crítica de Mastodon dispoñible, actualiza axiña. @@ -1692,7 +1695,7 @@ gl: delete: Eliminación da conta development: Desenvolvemento edit_profile: Editar perfil - export: Exportar datos + export: Exportar featured_tags: Cancelos destacados import: Importar import_and_export: Importar e exportar diff --git a/config/locales/he.yml b/config/locales/he.yml index 13a1f6f05d30d3..c7af22660f7b16 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1744,7 +1744,6 @@ he: delete: מחיקת חשבון development: פיתוח edit_profile: עריכת פרופיל - export: יצוא מידע featured_tags: תגיות נבחרות import: יבוא import_and_export: יבוא ויצוא diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 7dacf2007790f1..908cbf51c4328e 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -205,7 +205,6 @@ hr: delete: Brisanje računa development: Razvijanje edit_profile: Uredi profil - export: Izvoz podataka featured_tags: Istaknuti hashtagovi import: Uvezi import_and_export: Uvezi i izvezi diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 9767c488345493..5a00db954813e8 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -875,6 +875,9 @@ hu: message_html: Még nem definiáltál egy szerver szabályt sem. sidekiq_process_check: message_html: Nincs Sidekiq folyamat, mely a %{value} sorhoz van rendelve. Kérlek, nézd át a Sidekiq beállításait + software_version_check: + action: Elérhető frissítések megtekintése + message_html: Egy Mastodon-frissítés elérhető. software_version_critical_check: action: Elérhető frissítések megtekintése message_html: Kritikus Mastodon frissítés érhető el, frissíts a lehető leggyorsabban. @@ -1692,7 +1695,7 @@ hu: delete: Fiók törlése development: Fejlesztőknek edit_profile: Profil szerkesztése - export: Adatok exportálása + export: Exportálás featured_tags: Kiemelt hashtagek import: Importálás import_and_export: Import és export diff --git a/config/locales/hy.yml b/config/locales/hy.yml index 1fda020c0790a4..201922d102c043 100644 --- a/config/locales/hy.yml +++ b/config/locales/hy.yml @@ -757,7 +757,6 @@ hy: delete: Հաշուի ջնջում development: Ծրագրավորում edit_profile: Խմբագրել պրոֆիլը - export: Տվյալների արտահանում featured_tags: Ընտրուած հէշթեգեր import: Ներմուծել import_and_export: Ներմուծել և արտահանել diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 6632af061ec364..a8bc48b306a4b3 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -1675,7 +1675,6 @@ ia: delete: Deletion de conto development: Disveloppamento edit_profile: Modificar profilo - export: Exportation de datos featured_tags: Hashtags in evidentia import: Importar import_and_export: Importar e exportar diff --git a/config/locales/id.yml b/config/locales/id.yml index 96a5022a7c81da..6a005fddaae7dc 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -1347,7 +1347,6 @@ id: delete: Penghapusan akun development: Pengembangan edit_profile: Ubah profil - export: Expor data featured_tags: Tagar unggulan import: Impor import_and_export: Impor dan ekspor diff --git a/config/locales/ie.yml b/config/locales/ie.yml index 513a8eda7eb930..7e8140a374daff 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -1590,7 +1590,6 @@ ie: delete: Deletion de conto development: Developation edit_profile: Modificar profil - export: Exportation de data featured_tags: Recomandat hashtags import: Importar import_and_export: Importation e exportation diff --git a/config/locales/io.yml b/config/locales/io.yml index 97cc417df0f82e..dfb583450a6b88 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -1555,7 +1555,6 @@ io: delete: Kontoefaco development: Developo edit_profile: Redaktar la profilo - export: Exportacar datumi featured_tags: Estelata hashtagi import: Importacar import_and_export: Importaco e exportaco diff --git a/config/locales/is.yml b/config/locales/is.yml index 590805ad3027b0..4af26eea0b0cf6 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -1696,7 +1696,6 @@ is: delete: Eyðing notandaaðgangs development: Þróun edit_profile: Breyta notandasniði - export: Útflutningur gagna featured_tags: Myllumerki með aukið vægi import: Flytja inn import_and_export: Inn- og útflutningur diff --git a/config/locales/it.yml b/config/locales/it.yml index fe6fec17d778aa..a89fa0a53e444e 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -875,6 +875,9 @@ it: message_html: Non hai definito alcuna regola del server. sidekiq_process_check: message_html: Nessun processo di Sidekiq in esecuzione per le code di %{value}. Sei pregato di revisionare la tua configurazione di Sidekiq + software_version_check: + action: Visualizza gli aggiornamenti disponibili + message_html: È disponibile un aggiornamento per Mastodon. software_version_critical_check: action: Visualizza gli aggiornamenti disponibili message_html: Un aggiornamento critico di Mastodon è disponibile, ti preghiamo di aggiornare il più rapidamente possibile. @@ -1694,7 +1697,7 @@ it: delete: Cancellazione account development: Sviluppo edit_profile: Modifica profilo - export: Esportazione dati + export: Esporta featured_tags: Hashtag in evidenza import: Importa import_and_export: Importa ed esporta diff --git a/config/locales/ja.yml b/config/locales/ja.yml index ed6293e1cabaa9..41f93397da990f 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -22,6 +22,8 @@ ja: admin: account_actions: action: アクションを実行 + already_silenced: すでに制限されているアカウントです。 + already_suspended: すでに停止されているアカウントです。 title: "%{acct}さんに対してアクションを実行" account_moderation_notes: create: 書き込む @@ -589,6 +591,7 @@ ja: suspend_description_html: アカウントとそのすべての内容にアクセスできなくなり、最終的に削除され、やり取りは不可能になります。 30日以内であれば元に戻すことができます。このアカウントに対するすべての通報をクローズします。 actions_description_html: このレポートへのアクションを決定してください。アカウントへ懲罰的な措置を取った場合、Spanカテゴリが選択されている場合を除き、メール通知が送信されます。 actions_description_remote_html: この通報を解決するためのアクションを選択してください。これはあなたのサーバーがこのリモートアカウントと通信し、そのコンテンツを処理する時のみ影響します。 + actions_no_posts: 削除対象となる投稿がレポートに含まれていません add_to_report: 通報にさらに追加 already_suspended_badges: local: このサーバーで停止済み @@ -1656,7 +1659,6 @@ ja: delete: アカウントの削除 development: 開発 edit_profile: プロフィールを編集 - export: データのエクスポート featured_tags: 注目のハッシュタグ import: データのインポート import_and_export: インポート・エクスポート diff --git a/config/locales/ka.yml b/config/locales/ka.yml index 576937507886d2..2a0365fbf52644 100644 --- a/config/locales/ka.yml +++ b/config/locales/ka.yml @@ -410,7 +410,6 @@ ka: delete: ანგარიშის გაუქმება development: დეველოპმენტი edit_profile: პროფილის ცვლილება - export: მონაცემის ექსპორტი import: იმპორტი migrate: ანგარიშის მიგრაცია preferences: პრეფერენციები diff --git a/config/locales/kab.yml b/config/locales/kab.yml index 7044983ac9fe90..12bda84d463d2a 100644 --- a/config/locales/kab.yml +++ b/config/locales/kab.yml @@ -222,8 +222,8 @@ kab: shortcode: Tangalt tawezlant title: Imujiten udmawanen uncategorized: War-taggayt - unlist: Kkes seg wumuγ - unlisted: Yettwakkes seg wumuγ + unlist: Kkes seg wumuɣ + unlisted: Yettwakkes seg wumuɣ update_failed_msg: Ur izmir ara ad-issali umuji-a upload: Sali dashboard: @@ -710,8 +710,8 @@ kab: privacy_policy: title: Tasertit tabaḍnit redirects: - prompt: Ma tumneḍ aseɣwen-a, sit fell-as akken ad tkemmleḍ. - title: Aql-ik·em ad teffɣeḍ seg %{instance}. + prompt: Ma tumneḍ asaɣ-a, sit fell-as akken ad tkemmleḍ. + title: Ad teffɣeḍ seg %{instance}. relationships: activity: Armud n umiḍan followers: Imeḍfaṛen @@ -776,7 +776,6 @@ kab: delete: Tukksa n umiḍan development: Taneflit edit_profile: Ẓreg amaɣnu - export: Taktert n yisefka import: Kter import_and_export: Taktert d usifeḍ migrate: Tunigin n umiḍan diff --git a/config/locales/kk.yml b/config/locales/kk.yml index 67969d4d69eadf..537104ba51a90d 100644 --- a/config/locales/kk.yml +++ b/config/locales/kk.yml @@ -623,7 +623,6 @@ kk: delete: Аккаунт өшіру development: Жасаушы топ edit_profile: Профиль өңдеу - export: Экспорт уақыты featured_tags: Таңдаулы хэштегтер import: Импорт import_and_export: Импорт/экспорт diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 216e4687620368..3f6c4b39b8b646 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -863,6 +863,9 @@ ko: message_html: 아직 서버 규칙을 정하지 않았습니다. sidekiq_process_check: message_html: "%{value} 큐에 대한 사이드킥 프로세스가 발견되지 않았습니다. 사이드킥 설정을 검토해주세요" + software_version_check: + action: 사용 가능한 업데이트 보기 + message_html: 마스토돈 업데이트가 있습니다. software_version_critical_check: action: 사용 가능한 업데이트 보기 message_html: 긴급 마스토돈 업데이트가 있으니, 가능한 서둘러 업데이트 해주세요. @@ -1668,7 +1671,7 @@ ko: delete: 계정 삭제 development: 개발 edit_profile: 프로필 편집 - export: 데이터 내보내기 + export: 내보내기 featured_tags: 추천 해시태그 import: 데이터 가져오기 import_and_export: 가져오기 & 내보내기 diff --git a/config/locales/ku.yml b/config/locales/ku.yml index 08843f645e2078..ddd214441c352b 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -1369,7 +1369,6 @@ ku: delete: Jêbirina ajimêr development: Pêşdebir edit_profile: Profîlê serrast bike - export: Derxistinê daneyan featured_tags: Hashtagên bijarte import: Têxistin import_and_export: Têxistin û derxistin diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 3d1f1a61e2447d..275bdab86100c7 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -874,8 +874,12 @@ lad: message_html: "Tu magazinaje de objektos es mal konfigurado. La privasita de tus utilizadores esta en riziko." tags: moderation: + pending_review: Revizion esta asperando title: Estado + usable: Uzavle name: Nombre + newest: Mas muevos + oldest: Mas viejos reset: Reinisya review: Estado de revizion search: Bushka @@ -1027,7 +1031,9 @@ lad: guide_link_text: Todos pueden kontribuir. sensitive_content: Kontenido sensivle application_mailer: + notification_preferences: Troka preferensyas de posta salutation: "%{name}," + settings: 'Troka preferensyas de posta: %{link}' unsubscribe: Dezabona view: 'Mira:' view_profile: Ve profil @@ -1047,6 +1053,7 @@ lad: hint_html: Una koza mas! Tenemos ke konfirmar ke eres umano (para evitar spam!). Rezolve el CAPTCHA abasho i klika "Kontinua". title: Kontrolo de sigurita confirmations: + awaiting_review: Tu adreso de posta tiene sido konfirmado! La taifa de %{domain} esta revizando tu enrejistrasyon. Risiviras un meil si acheten tu kuento! awaiting_review_title: Estamos revizando tu enrejistramiento clicking_this_link: klikando en este atadijo login_link: konektate kon kuento @@ -1054,6 +1061,7 @@ lad: redirect_to_app_html: Seras readresado a la aplikasyon %{app_name}. Si esto no afita, aprova %{clicking_this_link} o regresa manualmente a la aplikasyon. registration_complete: Tu enrejistrasyon en %{domain} ya esta kompletada! welcome_title: Bienvenido, %{name}! + wrong_email_hint: Si este adreso de posta es inkorekto, puedes trokarlo en las preferensyas del kuento. delete_account: Efasa kuento delete_account_html: Si keres supremir tu kuento, puedes ir aki. Seras pedido de una konfirmasyon. description: @@ -1096,8 +1104,10 @@ lad: security: Sigurita set_new_password: Establese muevo kod setup: + email_below_hint_html: Mira en tu kuti de spam o solisita de muevo. Si el adreso de posta elektronika ke aparese aki es yerrado, puedes trokarlo aki. email_settings_hint_html: Klika el atadjiko ke te embimos para verifikar %{email}. Asperaremos aki. link_not_received: No risivites un atadijo? + new_confirmation_instructions_sent: Resiviras un muevo mesaj de posta elektronika kon el atadjio de konfirmasyon en unos minutos! title: Reviza tu kuti de arivo sign_in: preamble_html: Konektate kon tus kredensiales de %{domain}. Si tu kuento esta balabayado en otruno servidor, no puedras konektarte aki. @@ -1109,11 +1119,14 @@ lad: status: account_status: Estado del kuento functional: Tu kuento esta kompletamente funksyonal. + pending: Tu solisitasyon esta asperando la revizion por muestros administradores. Esto puede tadrar algun tiempo. Arisiviras una posta elektronika si la solisitasyon sea achetada. redirecting_to: Tu kuento se topa inaktivo porke esta siendo readresado a %{acct}. self_destruct: Deke %{domain} va a serrarse, solo tendras akseso limitado a tu kuento. view_strikes: Ve amonestamientos pasados kontra tu kuento too_fast: Formulario enviado demaziado rapido, aprovalo de muevo. use_security_key: Uza la yave de sigurita + author_attribution: + more_from_html: Mas de %{name} challenge: confirm: Kontinua hint_html: "Konsejo: No retornaremos a demandarte por el kod durante la sigiente ora." @@ -1150,6 +1163,9 @@ lad: before: 'Antes de kontinuar, por favor melda kon atensyon las sigientes notas:' caches: El kontenido ke tiene sido magazinado en kashe por otros sirvidores puede persistir data_removal: Tus publikasyones i el resto de datos se supremiran definitivamente + email_change_html: Puedes trokar tu adreso de posta elektronika sin supremir tu kuento + email_contact_html: Si ainda no te tiene parvenido, puedes eskrivir a %{email} para pider ayuda + email_reconfirmation_html: Si no te tiene parvenido la posta de konfirmasyon, puedes retornar a solisitarlo irreversible: No podras restaurar ni reaktivar tu kuento more_details_html: Para mas detalyos, ver la politika de privasita. username_available: Tu nombre de utilizador retornara a estar desponivle @@ -1380,6 +1396,7 @@ lad: authentication_methods: otp: aplikasyon de autentifikasyon en dos pasos password: kod + sign_in_token: kodiche de sigurita por posta elektronika webauthn: yaves de sigurita description_html: Si ves una aktivita ke no rekoneses, konsidera trokar tu kod i kapasitar la autentifikasyon en dos pasos. empty: No ay estoria de autentifikasyon desponivle @@ -1390,6 +1407,7 @@ lad: unsubscribe: action: Si, dezabona complete: Dezabonado + confirmation_html: Estas siguro de ke ya no keres risivir %{type} de Mastodon en %{domain} a tu posta elektronika %{email}? Syempre podras reabonarte dizde las opsyones de avizos por posta.. emails: notification_emails: favourite: avizos de favoritos por posta @@ -1634,7 +1652,6 @@ lad: delete: Efasa kuento development: Dezvelopamiento edit_profile: Edita profil - export: Eksporta enformasyon featured_tags: Etiketas avaliadas import: Importo import_and_export: Importo i eksporto @@ -1864,6 +1881,7 @@ lad: invalid_otp_token: Kodiche de dos pasos no valido otp_lost_help_html: Si pedriste akseso a los dos, puedes kontaktarte kon %{email} rate_limited: Demaziadas provas de autentifikasyon, aprova de muevo dempues. + seamless_external_login: Estas konektado por un servisyo eksterno i estonses la konfigurasyon de kod i konto de posta no estan disponivles. signed_in_as: 'Konektado komo:' verification: extra_instructions_html: Konsejo: El atadijo en tu web puede ser invizivle. La parte importante es rel="me", ke evita la suplantasyon de identita en sitios kon kontenido jenerado por el utilizador. Puedes inkluzo uzar una etiketa atadijo en la kavesera de la pajina en vez de a, ama el HTML deve ser aksesivle sin exekutar JavaScript. diff --git a/config/locales/lt.yml b/config/locales/lt.yml index fa07eb6f59dfc0..3b63ba6dcf9fc8 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -608,6 +608,9 @@ lt: message_html: Tavo Elasticsearch klasteris turi tik vieną mazgą, ES_PRESET turėtų būti nustatyta į single_node_cluster. elasticsearch_running_check: message_html: Nepavyko prijungti prie Elasticsearch. Patikrink, ar ji veikia, arba išjunk viso teksto paiešką. + software_version_check: + action: Žiūrėti galimus naujinimus + message_html: Yra „Mastodon“ naujinimas. tags: moderation: not_trendable: Netendencinga @@ -1090,7 +1093,7 @@ lt: delete: Paskyros trynimas development: Kūrimas edit_profile: Redaguoti profilį - export: Duomenų eksportas + export: Eksportuoti featured_tags: Rodomi saitažodžiai import: Importuoti import_and_export: Importas ir eksportas diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 4aeec5ceca73dc..16844a95c2bd4c 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -1130,6 +1130,8 @@ lv: too_fast: Veidlapa ir iesniegta pārāk ātri, mēģini vēlreiz. use_security_key: Lietot drošības atslēgu author_attribution: + example_title: Parauga teksts + more_from_html: Vairāk no %{name} s_blog: "%{name} emuāri" title: Autora attiecinājums challenge: @@ -1650,20 +1652,23 @@ lv: delete: Konta dzēšana development: Izstrāde edit_profile: Labot profilu - export: Datu eksports featured_tags: Piedāvātie tēmturi import: Imports import_and_export: Imports un eksports migrate: Konta migrācija + notifications: E-pasta paziņojumi preferences: Iestatījumi profile: Profils relationships: Sekojamie un sekotāji + severed_relationships: Pārtrauktās attiecības statuses_cleanup: Automātiska ziņu dzēšana strikes: Moderācijas aizrādījumi two_factor_authentication: Divpakāpju autentifikācija webauthn_authentication: Drošības atslēgas severed_relationships: download: Lejupielādēt (%{count}) + lost_followers: Zaudētie sekotāji + lost_follows: Zaudētie sekojumi type: Notikums statuses: attached: @@ -1829,6 +1834,8 @@ lv: suspend: Konts apturēts welcome: apps_android_action: Iegūt to Google Play + apps_ios_action: Lejupielādēt no App Store + apps_step: Lejupielādēt mūsu oficiālās lietotnes. apps_title: Mastodon lietotnes edit_profile_action: Pielāgot edit_profile_title: Pielāgo savu profilu diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 0c0ffb69bfc849..9994a34bb5eac5 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -1529,7 +1529,6 @@ ms: delete: Pemadaman akaun development: Pembangunan edit_profile: Sunting profil - export: Eksport data featured_tags: Tanda pagar terpilih import: Import import_and_export: Import dan eksport diff --git a/config/locales/my.yml b/config/locales/my.yml index 6acaa34cdc5c74..598915fad9019b 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -1529,7 +1529,6 @@ my: delete: အကောင့်ဖျက်သိမ်းခြင်း development: Development edit_profile: ပရိုဖိုင်ပြင်ဆင်ရန် - export: အချက်အလက်ထုတ်ယူခြင်း featured_tags: အသားပေးဖော်ပြထားသည့် ဟက်ရှ်တဂျ်များ import: ထည့်သွင်းခြင်း import_and_export: ထည့်သွင်းခြင်းနှင့် ထုတ်ယူခြင်း diff --git a/config/locales/nl.yml b/config/locales/nl.yml index afc4652bf600cc..7681a04eaecdfa 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -875,6 +875,9 @@ nl: message_html: Je hebt voor deze server geen regels opgesteld. sidekiq_process_check: message_html: Er draait geen Sidekiqproces voor de wachtrij(en) %{value}. Controleer je Sidekiqconfiguratie + software_version_check: + action: Beschikbare updates bekijken + message_html: Er is een Mastodon-update beschikbaar. software_version_critical_check: action: Bekijk de beschikbare updates message_html: Er is een kritieke update voor Mastodon beschikbaar. Update zo snel mogelijk. diff --git a/config/locales/nn.yml b/config/locales/nn.yml index dcf571a7923c46..8f6afc2426bb9b 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -875,6 +875,9 @@ nn: message_html: Du har ikke definert noen serverregler. sidekiq_process_check: message_html: Ingen Sidekiq-prosess kjører for %{value} køen(e). Vennligst se gjennom Sidekiq-konfigurasjonen din + software_version_check: + action: Sjå tilgjengelege oppdateringar + message_html: Ei Mastodon-oppdatering er tilgjengeleg. software_version_critical_check: action: Sjå tilgjengelege oppdateringar message_html: Ei kritisk oppdatering til Mastodon er tilgjengeleg. Oppdater så snart som mogleg. @@ -1692,7 +1695,7 @@ nn: delete: Kontosletting development: Utvikling edit_profile: Endr profil - export: Dataeksport + export: Eksporter featured_tags: Utvalgte emneknagger import: Hent inn import_and_export: Importer og eksporter diff --git a/config/locales/no.yml b/config/locales/no.yml index 1f0b6baccecfd8..ec0b14d5a3bfff 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1584,7 +1584,6 @@ delete: Kontosletting development: Utvikling edit_profile: Endre profil - export: Dataeksport featured_tags: Utvalgte emneknagger import: Importér import_and_export: Importer og eksporter diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 5cdd9240b01d97..a30126c44ba936 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -813,7 +813,6 @@ oc: delete: Supression de compte development: Desvolopament edit_profile: Modificar lo perfil - export: Exportar de donadas featured_tags: Etiquetas en avant import: Importar de donadas import_and_export: Import e export diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 314adf885f8dc6..3aaf7a5a57a2a4 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -903,6 +903,9 @@ pl: message_html: Nie zdefiniowano żadnych reguł serwera. sidekiq_process_check: message_html: Brak uruchomionego procesu Sidekiq dla kolejki(-ek) %{value}. Sprawdź konfigurację Sidekiq + software_version_check: + action: Pokaż dostępne aktualizacje + message_html: Dostępna aktualizacja Mastodona. software_version_critical_check: action: Pokaż dostępne aktualizacje message_html: Dostępna krytyczna aktualizacja Mastodona, zaktualizuj jak tylko będzie to możliwe. diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 7742a80569c1c8..5e7317c5fbb730 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -875,6 +875,9 @@ pt-BR: message_html: Você não definiu nenhuma regra de servidor. sidekiq_process_check: message_html: Nenhum processo Sidekiq rodando para a(s) fila(s) %{value}. Por favor, revise a sua configuração para Sidekiq + software_version_check: + action: Ver atualizações disponíveis + message_html: Uma atualização do Mastodon está disponível. software_version_critical_check: action: Ver atualizações disponíveis message_html: Uma atualização crítica do Mastodon está disponível. Por favor, atualize o mais rápido possível. @@ -1692,7 +1695,7 @@ pt-BR: delete: Exclusão de conta development: Desenvolvimento edit_profile: Editar perfil - export: Exportar dados + export: Exportar featured_tags: Hashtags em destaque import: Importar import_and_export: Importar e exportar diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index d6c5c4a6ff01f7..6b48e8de26b48e 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -1679,7 +1679,6 @@ pt-PT: delete: Eliminação da conta development: Desenvolvimento edit_profile: Editar perfil - export: Exportar dados featured_tags: Etiquetas destacadas import: Importar import_and_export: Importar e exportar diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 387772749006e1..c61c7f459fcf3e 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -1741,7 +1741,6 @@ ru: delete: Удаление учётной записи development: Разработчикам edit_profile: Изменить профиль - export: Экспорт данных featured_tags: Избранные хэштеги import: Импорт import_and_export: Импорт и экспорт diff --git a/config/locales/sc.yml b/config/locales/sc.yml index 780270ddf17b2e..306e670b7182ca 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -1080,7 +1080,6 @@ sc: delete: Eliminatzione de su contu development: Isvilupu edit_profile: Modìfica profilu - export: Esportatzione de datos featured_tags: Etichetas in evidèntzia import: Importatzione import_and_export: Importatzione e esportatzione diff --git a/config/locales/sco.yml b/config/locales/sco.yml index 97eaa21ed6d0d6..8cc733a4acc2a2 100644 --- a/config/locales/sco.yml +++ b/config/locales/sco.yml @@ -1359,7 +1359,6 @@ sco: delete: Accoont deletion development: Development edit_profile: Edit profile - export: Data export featured_tags: Featured hashtags import: Import import_and_export: Import an export diff --git a/config/locales/si.yml b/config/locales/si.yml index 8460de01da9f6a..270e0ae3fc4e31 100644 --- a/config/locales/si.yml +++ b/config/locales/si.yml @@ -1234,7 +1234,6 @@ si: delete: ගිණුම මැකීම development: සංවර්ධනය edit_profile: පැතිකඩ සංස්කරණය - export: දත්ත නිර්යාතය featured_tags: විශේෂාංගගත හැෂ් ටැග් import: ආයාතය import_and_export: ආයාත හා නිර්යාත diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index a2cf8e4222543a..7b7d92995b04e8 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -3,6 +3,7 @@ bg: simple_form: hints: account: + attribution_domains_as_text: Защитава от фалшиви атрибути. discoverable: Вашите публични публикации и профил може да се представят или препоръчват в различни области на Mastodon и вашия профил може да се предлага на други потребители. display_name: Вашето пълно име или псевдоним. fields: Вашата начална страница, местоимения, години, всичко що искате. @@ -130,6 +131,7 @@ bg: name: Можете да смените само употребата на големи/малки букви, например, за да е по-четимо user: chosen_languages: Само публикации на отметнатите езици ще се показват в публичните часови оси + role: Ролята управлява какви позволения има потребителят. user_role: color: Цветът, използван за ролите в потребителския интерфейс, като RGB в шестнадесетичен формат highlighted: Това прави ролята обществено видима @@ -142,6 +144,7 @@ bg: url: До къде ще се изпращат събитията labels: account: + attribution_domains_as_text: Позволяване само на особени уебсайтове discoverable: Включване на профил и публикации в алгоритмите за откриване fields: name: Етикет diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 88c1c0e184312d..d46e764a44fdaf 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -2,6 +2,15 @@ el: simple_form: hints: + account: + attribution_domains_as_text: Προστατεύει από ψευδείς ιδιότητες. + discoverable: Οι δημόσιες δημοσιεύσεις και το προφίλ σου μπορεί να εμφανίζονται ή να συνιστώνται σε διάφορους τομείς του Mastodon και το προφίλ σου μπορεί να προτείνεται σε άλλους χρήστες. + display_name: Το πλήρες ή το αστείο σου όνομα. + fields: Η αρχική σου σελίδα, αντωνυμίες, ηλικία, ό,τι θες. + indexable: Οι δημόσιες δημοσιεύσεις σου μπορεί να εμφανιστούν στα αποτελέσματα αναζήτησης στο Mastodon. Άτομα που έχουν αλληλεπιδράσει με τις δημοσιεύσεις σου μπορεί να είναι σε θέση να τις αναζητήσουν όπως και να 'χει. + note: 'Μπορείς να @επισημάνεις άλλα άτομα ή #ετικέτες.' + show_collections: Οι χρήστες θα είναι σε θέση να περιηγηθούν στα άτομα που ακολουθείς και στους ακόλουθούς σου. Άτομα που ακολουθείς θα βλέπουν ότι τους ακολουθείς όπως και να 'χει. + unlocked: Οι χρήστες θα είναι σε θέση να σε ακολουθήσουν χωρίς να ζητούν έγκριση. Κατάργησε την επιλογή αν θες να αξιολογείς τα αιτήματα ακολούθησης και να επιλέξεις αν θα αποδεχθείς ή απορρίψεις νέους ακόλουθους. account_alias: acct: Όρισε το username@domain του λογαριασμού από τον οποίο θέλεις να μετακινηθείς account_migration: @@ -31,12 +40,14 @@ el: text: Μπορείς να κάνετε έφεση σε ένα παράπτωμα μόνο μία φορά defaults: autofollow: Όσοι εγγραφούν μέσω της πρόσκλησης θα σε ακολουθούν αυτόματα + avatar: WEBP, PNG, GIF ή JPG. Το πολύ %{size}. Θα υποβαθμιστεί σε %{dimensions}px bot: Ο λογαριασμός αυτός εκτελεί κυρίως αυτοματοποιημένες ενέργειες και ίσως να μην παρακολουθείται context: Ένα ή περισσότερα πλαίσια στα οποία μπορεί να εφαρμόζεται αυτό το φίλτρο current_password: Για λόγους ασφαλείας παρακαλώ γράψε τον κωδικό του τρέχοντος λογαριασμού current_username: Για επιβεβαίωση, παρακαλώ γράψε το όνομα χρήστη του τρέχοντος λογαριασμού digest: Αποστέλλεται μόνο μετά από μακρά περίοδο αδράνειας και μόνο αν έχεις λάβει προσωπικά μηνύματα κατά την απουσία σου email: Θα σου σταλεί email επιβεβαίωσης + header: WEBP, PNG, GIF ή JPG. Το πολύ %{size}. Θα υποβαθμιστεί σε %{dimensions}px inbox_url: Αντέγραψε το URL της αρχικής σελίδας του ανταποκριτή που θέλεις να χρησιμοποιήσεις irreversible: Οι φιλτραρισμένες αναρτήσεις θα εξαφανιστούν αμετάκλητα, ακόμα και αν το φίλτρο αργότερα αφαιρεθεί locale: Η γλώσσα χρήσης, των email και των ειδοποιήσεων push @@ -67,10 +78,15 @@ el: warn: Απόκρυψη φιλτραρισμένου περιεχομένου πίσω από μια προειδοποίηση που αναφέρει τον τίτλο του φίλτρου form_admin_settings: activity_api_enabled: Καταμέτρηση τοπικά δημοσιευμένων δημοσιεύσεων, ενεργών χρηστών και νέων εγγραφών σε εβδομαδιαία πακέτα + app_icon: WEBP, PNG, GIF ή JPG. Παρακάμπτει το προεπιλεγμένο εικονίδιο εφαρμογής σε κινητές συσκευές με προσαρμοσμένο εικονίδιο. + backups_retention_period: Οι χρήστες έχουν τη δυνατότητα να δημιουργήσουν αρχεία των αναρτήσεων τους για να κατεβάσουν αργότερα. Όταν οριστεί μια θετική τιμή, αυτά τα αρχεία θα διαγράφονται αυτόματα από τον αποθηκευτικό σου χώρο μετά τον καθορισμένο αριθμό ημερών. bootstrap_timeline_accounts: Αυτοί οι λογαριασμοί θα καρφιτσωθούν στην κορυφή των νέων χρηστών που ακολουθούν τις συστάσεις. closed_registrations_message: Εμφανίζεται όταν κλείνουν οι εγγραφές + content_cache_retention_period: Όλες οι αναρτήσεις από άλλους διακομιστές (συμπεριλαμβανομένων των ενισχύσεων και απαντήσεων) θα διαγραφούν μετά τον καθορισμένο αριθμό ημερών, χωρίς να λαμβάνεται υπόψη οποιαδήποτε αλληλεπίδραση τοπικού χρήστη με αυτές τις αναρτήσεις. Αυτό περιλαμβάνει αναρτήσεις όπου ένας τοπικός χρήστης την έχει χαρακτηρίσει ως σελιδοδείκτη ή αγαπημένη. Θα χαθούν επίσης ιδιωτικές αναφορές μεταξύ χρηστών από διαφορετικές οντότητες και θα είναι αδύνατο να αποκατασταθούν. Η χρήση αυτής της ρύθμισης προορίζεται για οντότητες ειδικού σκοπού και χαλάει πολλές προσδοκίες του χρήστη όταν εφαρμόζεται για χρήση γενική σκοπού. custom_css: Μπορείς να εφαρμόσεις προσαρμοσμένα στυλ στην έκδοση ιστοσελίδας του Mastodon. + favicon: WEBP, PNG, GIF ή JPG. Παρακάμπτει το προεπιλεγμένο favicon του Mastodon με ένα προσαρμοσμένο εικονίδιο. mascot: Παρακάμπτει την εικονογραφία στην προηγμένη διεπαφή ιστού. + media_cache_retention_period: Τα αρχεία πολυμέσων από αναρτήσεις που γίνονται από απομακρυσμένους χρήστες αποθηκεύονται προσωρινά στο διακομιστή σου. Όταν οριστεί μια θετική τιμή, τα μέσα θα διαγραφούν μετά τον καθορισμένο αριθμό ημερών. Αν τα δεδομένα πολυμέσων ζητηθούν μετά τη διαγραφή τους, θα γίνει ε, αν το πηγαίο περιεχόμενο είναι ακόμα διαθέσιμο. Λόγω περιορισμών σχετικά με το πόσο συχνά οι κάρτες προεπισκόπησης συνδέσμων συνδέονται σε ιστοσελίδες τρίτων, συνιστάται να ορίσεις αυτή την τιμή σε τουλάχιστον 14 ημέρες ή οι κάρτες προεπισκόπησης συνδέσμων δεν θα ενημερώνονται κατ' απάιτηση πριν από εκείνη την ώρα. peers_api_enabled: Μια λίστα με ονόματα τομέα που συνάντησε αυτός ο διακομιστής στο fediverse. Δεν περιλαμβάνονται δεδομένα εδώ για το αν συναλλάσσετε με ένα συγκεκριμένο διακομιστή, μόνο ότι ο διακομιστής σας το ξέρει. Χρησιμοποιείται από υπηρεσίες που συλλέγουν στατιστικά στοιχεία για την συναλλαγή με γενική έννοια. profile_directory: Ο κατάλογος προφίλ παραθέτει όλους τους χρήστες που έχουν επιλέξει να είναι ανακαλύψιμοι. require_invite_text: 'Όταν η εγγραφή απαιτεί χειροκίνητη έγκριση, κάνε το πεδίο κειμένου: «Γιατί θέλετε να συμμετάσχετε;» υποχρεωτικό αντί για προαιρετικό' @@ -103,14 +119,19 @@ el: sign_up_requires_approval: Νέες εγγραφές θα απαιτούν την έγκριση σας severity: Επιλέξτε τι θα γίνεται με αιτήσεις από αυτήν την διεύθυνση IP rule: + hint: Προαιρετικό. Δώσε περισσότερες λεπτομέρειες σχετικά με τον κανόνα text: Περιγράψτε έναν κανόνα ή μια απαίτηση για τους χρήστες σε αυτόν τον διακομιστή. Προσπαθήστε να τον κρατήσετε σύντομο και απλό sessions: otp: 'Βάλε τον κωδικό δυο παραγόντων (2FA) από την εφαρμογή του τηλεφώνου σου ή χρησιμοποίησε κάποιον από τους κωδικούς ανάκτησης σου:' webauthn: Αν πρόκειται για ένα κλειδί USB βεβαιωθείτε ότι είναι συνδεδεμένο και αν απαιτείται πατήστε το ελαφρά. + settings: + indexable: Η σελίδα του προφίλ σου μπορεί να εμφανιστεί στα αποτελέσματα αναζήτησης στο Google, Bing και άλλες. + show_application: Θα είσαι πάντα σε θέση να δεις ποια εφαρμογή δημοσίευσε την ανάρτησή σου όπως και να 'χει. tag: name: Μπορείς να αλλάξεις μόνο το πλαίσιο των χαρακτήρων, για παράδειγμα για να γίνει περισσότερο ευανάγνωστο user: chosen_languages: Όταν ενεργοποιηθεί, στη δημόσια ροή θα εμφανίζονται τουτ μόνο από τις επιλεγμένες γλώσσες + role: Ο ρόλος ελέγχει ποια δικαιώματα έχει ο χρήστης. user_role: color: Το χρώμα που θα χρησιμοποιηθεί για το ρόλο σε ολόκληρη τη διεπαφή, ως RGB σε δεκαεξαδική μορφή highlighted: Αυτό καθιστά το ρόλο δημόσια ορατό @@ -119,12 +140,18 @@ el: position: Ανώτεροι ρόλοι αποφασίζει την επίλυση συγκρούσεων σε ορισμένες περιπτώσεις. Ορισμένες ενέργειες μπορούν να εκτελεστούν μόνο σε ρόλους με χαμηλότερη προτεραιότητα webhook: events: Επιλέξτε συμβάντα για αποστολή + template: Σύνθεσε το δικό σου JSON payload χρησιμοποιώντας μεταβλητή παρεμβολή. Άφησε κενό για προεπιλογή JSON. url: Πού θα σταλούν τα γεγονότα labels: account: + attribution_domains_as_text: Να επιτρέπονται μόνο συγκεκριμένες ιστοσελίδες + discoverable: Παροχή προφίλ και αναρτήσεων σε αλγορίθμους ανακάλυψης fields: name: Περιγραφή value: Περιεχόμενο + indexable: Συμπερίληψη δημόσιων αναρτήσεων στα αποτελέσματα αναζήτησης + show_collections: Εμφάνιση ακολούθων και ακολουθουμένων στο προφίλ + unlocked: Αυτόματη αποδοχή νέων ακολούθων account_alias: acct: Διακριτικό του παλιού λογαριασμού account_migration: @@ -186,6 +213,7 @@ el: setting_default_privacy: Ιδιωτικότητα δημοσιεύσεων setting_default_sensitive: Σημείωση όλων των πολυμέσων ως ευαίσθητου περιεχομένου setting_delete_modal: Επιβεβαίωση πριν τη διαγραφή ενός τουτ + setting_disable_hover_cards: Απενεργοποίηση προεπισκόπησης προφίλ κατά την αιώρηση setting_disable_swiping: Απενεργοποίηση κινήσεων συρσίματος setting_display_media: Εμφάνιση πολυμέσων setting_display_media_default: Προκαθορισμένο @@ -217,10 +245,13 @@ el: warn: Απόκρυψη με προειδοποίηση form_admin_settings: activity_api_enabled: Δημοσίευση συγκεντρωτικών στατιστικών σχετικά με τη δραστηριότητα του χρήστη στο API + app_icon: Εικονίδιο εφαρμογής backups_retention_period: Περίοδος αρχειοθέτησης του χρήστη bootstrap_timeline_accounts: Πρότεινε πάντα αυτούς τους λογαριασμούς σε νέους χρήστες closed_registrations_message: Προσαρμοσμένο μήνυμα όταν οι εγγραφές δεν είναι διαθέσιμες + content_cache_retention_period: Περίοδος διατήρησης απομακρυσμένου περιεχομένου custom_css: Προσαρμοσμένο CSS + favicon: Favicon mascot: Προσαρμοσμένη μασκότ (απαρχαιωμένο) media_cache_retention_period: Περίοδος διατήρησης προσωρινής μνήμης πολυμέσων peers_api_enabled: Δημοσίευση λίστας των εντοπισμένων διακομιστών στο API @@ -268,15 +299,27 @@ el: pending_account: Αποστολή email όταν υπάρχει νέος λογαριασμός για επιθεώρηση reblog: Αποστολή email όταν κάποιος προωθεί τη δημοσίευση σου report: Υποβλήθηκε νέα αναφορά + software_updates: + all: Ειδοποίηση για όλες τις ενημερώσεις + critical: Ειδοποίηση μόνο για κρίσιμες ενημερώσεις + label: Μια νέα έκδοση του Mastodon είναι διαθέσιμη + none: Να μην ειδοποιούμαι ποτέ για ενημερώσεις (δεν συνιστάται) + patch: Ειδοποίηση για ενημερώσεις σφαλμάτων trending_tag: Νέο περιεχόμενο προς τάση απαιτεί αξιολόγηση rule: + hint: Επιπρόσθετες πληροφορίες text: Κανόνας + settings: + indexable: Συμπερίληψη σελίδας προφίλ στις μηχανές αναζήτησης + show_application: Εμφάνιση από ποια εφαρμογή έστειλες μία ανάρτηση tag: listable: Εμφάνιση αυτής της ετικέτας στο δημόσιο κατάλογο name: Ετικέτα trendable: Εμφάνιση της ετικέτας στις τάσεις + usable: Να επιτρέπεται η τοπική χρήση αυτής της ετικέτας από αναρτήσεις user: role: Ρόλος + time_zone: Ζώνη ώρας user_role: color: Χρώμα εμβλήματος highlighted: Εμφάνιση ρόλου ως σήμα στα προφίλ χρηστών @@ -285,9 +328,11 @@ el: position: Προτεραιότητα webhook: events: Ενεργοποιημένα συμβάντα + template: Πρότυπο payload url: Endpoint URL 'no': Όχι not_recommended: Δεν προτείνεται + overridden: Αντικαταστάθηκε recommended: Προτείνεται required: mark: "*" diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index 053816ef881c06..cb4a9041e81eb6 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -3,6 +3,7 @@ eo: simple_form: hints: account: + attribution_domains_as_text: Protektas kontraŭ falsaj atribuoj. discoverable: Viaj publikaj afiŝoj kaj profilo povas esti prezentitaj aŭ rekomenditaj en diversaj lokoj de Mastodon kaj via profilo povas esti proponita al aliaj uzantoj. display_name: Via plena nomo aŭ via kromnomo. fields: Via retpaĝo, pronomoj, aĝo, ĉio, kion vi volas. @@ -78,6 +79,7 @@ eo: bootstrap_timeline_accounts: Ĉi tiuj kontoj pinglitas al la supro de sekvorekomendoj de novaj uzantoj. closed_registrations_message: Montrita kiam registroj fermitas custom_css: Vi povas meti propajn stilojn en la retversio de Mastodon. + favicon: WEBP, PNG, GIF aŭ JPG. Anstataŭigas la defaŭltan Mastodon-favikono kun propra bildsimbolo. mascot: Anstatauigi la ilustraĵon en la altnivela retinterfaco. peers_api_enabled: Listo de domajnaj nomoj kiujn ĉi tiu servilo renkontis en la fediverso. Neniuj datumoj estas inkluditaj ĉi tie pri ĉu vi federacias kun donita servilo, nur ke via servilo scias pri ĝi. Ĉi tio estas uzata de servoj kiuj kolektas statistikojn pri federacio en ĝenerala signifo. profile_directory: La profilujo listigas ĉiujn uzantojn kiu volonte malkovrebli. @@ -111,6 +113,7 @@ eo: sign_up_requires_approval: Novaj registriĝoj bezonos vian aprobon severity: Elektu, kio okazos pri petoj de ĉi tiu IP-adreso rule: + hint: Laŭvola. Provizu pliajn detalojn pri la regulo text: Priskribu regulon aŭ neceson por uzantoj en ĉi tiu servilo. Provu fari ĝin mallonga kaj simpla sessions: otp: 'Enmetu la kodon de dufaktora aŭtentigo el via telefono aŭ uzu unu el viaj realiraj kodoj:' @@ -122,6 +125,7 @@ eo: name: Vi povas ŝanĝi nur la majuskladon de la literoj, ekzemple, por igi ĝin pli legebla user: chosen_languages: Kun tio markita nur mesaĝoj en elektitaj lingvoj aperos en publikaj tempolinioj + role: La rolo kontrolas kiujn permesojn la uzanto havas. user_role: color: Koloro uzita por la rolo sur la UI, kun RGB-formato highlighted: Ĉi tio igi la rolon publike videbla @@ -134,6 +138,7 @@ eo: url: Kien eventoj sendotas labels: account: + attribution_domains_as_text: Permesi nur specifajn retejojn discoverable: Elstarigi profilon kaj afiŝojn en eltrovantaj algoritmoj fields: name: Etikedo @@ -239,6 +244,7 @@ eo: bootstrap_timeline_accounts: Ĉiam rekomendi ĉi tiujn kontojn al novaj uzantoj closed_registrations_message: Kutima mesaĝo kiam registroj ne estas disponeblaj custom_css: Propa CSS + favicon: Favorikono mascot: Propa maskoto media_cache_retention_period: Audovidaĵkaŝaĵretendauro peers_api_enabled: Eldonu liston de malkovritaj serviloj en la API @@ -294,6 +300,7 @@ eo: patch: Sciigi pri cimoriparaj ĝisdatigoj trending_tag: Nova furoro bezonas kontrolon rule: + hint: Pliaj informoj text: Regulo settings: indexable: Inkludi profilan paĝon en serĉiloj @@ -302,6 +309,7 @@ eo: listable: Permesi ĉi tiun kradvorton aperi en serĉoj kaj sugestoj name: Kradvorto trendable: Permesi al ĉi tiu kradvorto aperi en furoraĵoj + usable: Permesi afiŝojn uzi ĉi tiun kradvorton loke user: role: Rolo time_zone: Horzono diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index f2108828d5643b..8c84e35a4d1880 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -79,14 +79,14 @@ es-MX: form_admin_settings: activity_api_enabled: Conteo de publicaciones publicadas localmente, usuarios activos, y nuevos registros en periodos semanales app_icon: WEBP, PNG, GIF o JPG. Reemplaza el icono de aplicación predeterminado en dispositivos móviles con un icono personalizado. - backups_retention_period: Los usuarios tienen la capacidad de generar archivos de sus mensajes para descargar más adelante. Cuando se establece un valor positivo, estos archivos se eliminarán automáticamente del almacenamiento después del número de días especificado. + backups_retention_period: Los usuarios tienen la posibilidad de generar archivos de sus mensajes para descargarlos más adelante. Cuando se establece en un valor positivo, estos archivos se eliminarán automáticamente del almacenamiento después del número especificado de días. bootstrap_timeline_accounts: Estas cuentas aparecerán en la parte superior de las recomendaciones de los nuevos usuarios. closed_registrations_message: Mostrado cuando los registros están cerrados - content_cache_retention_period: Todas las publicaciones de otros servidores (incluso impulsos y respuestas) se eliminarán después del número de días especificado, sin tener en cuenta la interacción del usuario local con esos mensajes. Esto incluye mensajes donde un usuario local los ha marcado como marcadores o favoritos. Las menciones privadas entre usuarios de diferentes instancias también se perderán sin posibilidad de recuperación. El uso de esta configuración está destinado a instancias de propósito especial, y rompe muchas expectativas de los usuarios cuando se implementa para un uso de propósito general. + content_cache_retention_period: Todas las publicaciones de otros servidores (incluyendo impuestos y respuestas) serán borrados después del número de días especificado, sin tener en cuenta cualquier interacción del usuario local con esas publicaciones. Esto incluye los mensajes que un usuario local haya marcado como favoritos. Las menciones privadas entre usuarios de diferentes instancias también se perderán y será imposible restaurarlas. El uso de esta configuración está pensado para instancias de propósito especial y rompe muchas expectativas de los usuarios cuando se implementa para uso general. custom_css: Puedes aplicar estilos personalizados a la versión web de Mastodon. favicon: WEBP, PNG, GIF o JPG. Reemplaza el icono predeterminado de Mastodon con un icono personalizado. mascot: Reemplaza la ilustración en la interfaz web avanzada. - media_cache_retention_period: Los archivos multimedia de las publicaciones creadas por usuarios remotos se almacenan en caché en tu servidor. Cuando se establece un valor positivo, estos archivos se eliminarán después del número especificado de días. Si los datos multimedia se solicitan después de eliminarse, se volverán a descargar, si el contenido fuente todavía está disponible. Debido a restricciones en la frecuencia con la que las tarjetas de previsualización de enlaces realizan peticiones a sitios de terceros, se recomienda establecer este valor a al menos 14 días, o las tarjetas de previsualización de enlaces no se actualizarán bajo demanda antes de ese momento. + media_cache_retention_period: Los archivos multimedia de las publicaciones realizadas por usuarios remotos se almacenan en caché en su servidor. Si se establece en un valor positivo, los archivos multimedia se eliminarán tras el número de días especificado. Si los datos multimedia se solicitan después de haber sido eliminados, se volverán a descargar, si el contenido de origen sigue estando disponible. Debido a las restricciones sobre la frecuencia con la que las tarjetas de previsualización de enlaces sondean sitios de terceros, se recomienda establecer este valor en al menos 14 días, o las tarjetas de previsualización de enlaces no se actualizarán bajo demanda antes de ese tiempo. peers_api_enabled: Una lista de nombres de dominio que este servidor ha encontrado en el fediverso. Aquí no se incluye ningún dato sobre si usted federa con un servidor determinado, sólo que su servidor lo sabe. Esto es utilizado por los servicios que recopilan estadísticas sobre la federación en un sentido general. profile_directory: El directorio de perfiles lista a todos los usuarios que han optado por que su cuenta pueda ser descubierta. require_invite_text: Cuando los registros requieren aprobación manual, hace obligatoria la entrada de texto "¿Por qué quieres unirte?" en lugar de opcional @@ -249,7 +249,7 @@ es-MX: backups_retention_period: Período de retención del archivo de usuario bootstrap_timeline_accounts: Recomendar siempre estas cuentas a nuevos usuarios closed_registrations_message: Mensaje personalizado cuando los registros no están disponibles - content_cache_retention_period: Período de retención de contenido remoto + content_cache_retention_period: Periodo de conservación de contenidos remotos custom_css: CSS personalizado favicon: Favicon mascot: Mascota personalizada (legado) diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml index fe8243b0e9fb57..5cbbd9d06e90e3 100644 --- a/config/locales/simple_form.io.yml +++ b/config/locales/simple_form.io.yml @@ -3,6 +3,7 @@ io: simple_form: hints: account: + attribution_domains_as_text: Protektas de falsa akreditaji. discoverable: Vua publika posti e profilo povas remarkesar o rekomendesar en diferanta parti di Mastodon e vua profilo povas sugestesar ad altra uzanti. display_name: Vua tota nomo o vua gaya nomo. fields: Vua retsituo, pronomi, evo, irgo quan vu volas. @@ -39,12 +40,14 @@ io: text: Vu povas nur apelar striko unafoye defaults: autofollow: Personi quo registresesas tra invito automatika sequos vu + avatar: WEBP, PNG, GIF o JPG. Maxime %{size}. Esos mikrigita a %{dimensions}px bot: Signalez a altra personi ke la konto precipue havas automatikigita agi e forsan ne surveyesas context: Situeso kande filtrilo debas aplikesar current_password: Por sekuresorezoni, pozez pasvorto di ca konto current_username: Por konfirmar, pozez uzantonomo di ca konto digest: Nur sendesas pos longa neaktiveso e nur se vu ganis irga mesaji dum ke vu esas neprezenta email: Vu sendesos konfirmretposto + header: WEBP, PNG, GIF o JPG. Maxime %{size}. Esos mikrigita a %{dimensions}px inbox_url: Kopiez URL de frontpagino de relayo quon vu volas uzar irreversible: Filtrita posti neinversigeble desaparos, mem se filtro efacesas pose locale: Linguo di uzantointervizajo, retposti e pulsavizi @@ -75,10 +78,15 @@ io: warn: Celez filtrita kontenajo dop avert quo montras titulo di filtrilo form_admin_settings: activity_api_enabled: Quanto de lokale publikigita posti, aktiva uzanti e nova registri, donita semanope + app_icon: WEBP, PNG, GIF o JPG. Ol remplas la originala imajeto di softwaro sur poshaparati kun personaligita imajeto. + backups_retention_period: Uzanto povas facar arkivi di sua posti por deskargar pose. Se ol esas positiva nombro, ca arkivi automate efacesis de vua konserveyo pos la decidita quanto di dii. bootstrap_timeline_accounts: Ca konti pinglagesos a super sequorekomendi di nova uzanti. closed_registrations_message: Montresas kande registradi klozesas + content_cache_retention_period: Omna posti de altra servili efacesos (anke repeti e respondi) pos decidita quanto di dii, sen ye irga lokala uzantointerago kun ti posti. Privata mencioni inter uzanto de dessanta servili anke desganos e neposible riganesos. custom_css: Vu povas pozar kustumizita staili en retverso di Mastodon. + favicon: WEBP, PNG, GIF o JPG. Ol remplas la originala imajeto di Mastodon kun personaligita imajeto. mascot: Remplas montreso en avanca retintervizajo. + media_cache_retention_period: Medidoseri de posti quan posti da deslokala uzanti retummemoresis sur vua servilo. Se medidatumo demandesas pos ol efacesas, ol rideskargesos. peers_api_enabled: Listo di domeni quin ca servilo trovis en la fediverso. Nula informo inkluzesas hike pri ka vu federas kun partikulara servilo, nur ke vua servilo savas pri lo. Co es uzata da enti qui kolektas statistiki pri federeso generale. profile_directory: La profilcheflisto montras omna uzanti quo voluntale volas esar deskovrebla. require_invite_text: Kande registradi bezonas manuala aprobo, ol kauzigas "Por quo vu volas juntas?" textoenpozo esar obliganta @@ -111,6 +119,7 @@ io: sign_up_requires_approval: Nova registro bezonos vua aprobo severity: Selektez quo eventos kun demandi de ca IP rule: + hint: Nemusta. Ol donas plu multa detali pri la regulo text: Deskriptez regulo o bezonaj por uzanti en ca servilo. Vu debas lasar lu esar korta e simpla sessions: otp: Enter the Two-factor code from your phone or use one of your recovery codes. @@ -122,6 +131,7 @@ io: name: Vu povas nur chanjar literkaso, por exemplo, por kauzigar lu divenar plu lektebla user: chosen_languages: Kande marketigesis, nur posti en selektesis lingui montresos en publika tempolinei + role: La rolo donas certena permisi a la uzanto. user_role: color: Koloro quo uzesas por rolo en tota UI, quale RGB kun hexformato highlighted: Co kauzigas rolo divenar publike videbla @@ -130,9 +140,11 @@ io: position: Plu alta rolo decidas problemsolvo en kelka situeso. Kelka agi povas nur eventar a roli kun plu basa prioreso webhook: events: Selektigez eventi por sendar + template: Facez vua sua JSON per variebla interpolo. Lasez quale nulo por originala JSON. url: Ibe eventi sendesos labels: account: + attribution_domains_as_text: Nur permisas specifika retsitui discoverable: Inkluzar profilo e posti en trovado-algoritmi fields: name: Etiketo @@ -201,6 +213,7 @@ io: setting_default_privacy: Videbleso di la mesaji setting_default_sensitive: Sempre markizez medii quale sentoza setting_delete_modal: Montrez konfirmdialogo ante efacar posto + setting_disable_hover_cards: Desaktivigez profilprevido dum klikpaso setting_disable_swiping: Desaktivigez fingromovi setting_display_media: Mediomontrajo setting_display_media_default: Originalo @@ -232,10 +245,13 @@ io: warn: Celez kun averto form_admin_settings: activity_api_enabled: Publikigez rezumstatistiko pri uzantoaktiveso en API + app_icon: Softwarimajeto backups_retention_period: Uzantoarkivretendurtempo bootstrap_timeline_accounts: Sempre rekomendez ca konti a nova uzanti closed_registrations_message: Kustumizita mesajo kande registradi ne esas disponebla + content_cache_retention_period: Fora kontenajretenperiodo custom_css: Kustumizita CSS + favicon: Imajeto mascot: Kustumizita reprezentimajo (oldo) media_cache_retention_period: Mediimemorajretendurtempo peers_api_enabled: Publikigez listo di deskovrita servili en API @@ -291,6 +307,7 @@ io: patch: Notifikar pri problemosolvanta aktualigi trending_tag: Nova tendenco bezonas kontrolo rule: + hint: Plusa informo text: Regulo settings: indexable: Inkluzar profilopagino en serchili @@ -299,6 +316,7 @@ io: listable: Permisez ca hashtago aparar en trovaji e sugestaji name: Hashtago trendable: Permisez ca hashtago aparar che tendenci + usable: Permisez posti uzar ca gretiketo lokale user: role: Rolo time_zone: Klokozono @@ -310,9 +328,11 @@ io: position: Prioreso webhook: events: Aktivigita eventi + template: Pagkargshablono url: URL di finpunto 'no': Ne not_recommended: Ne rekomendesas + overridden: Remplesis recommended: Rekomendito required: mark: "*" diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index 203b02371539a8..f390d42132c615 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -92,7 +92,7 @@ kab: setting_display_media_default: Akk-a kan setting_display_media_hide_all: Ffer-iten akk setting_display_media_show_all: Sken-iten-id akk - setting_hide_network: Ffer azetta-k·m + setting_hide_network: Ffer azetta-k·m inmetti setting_theme: Asental n wesmel setting_use_pending_items: Askar aleɣwayan sign_in_token_attempt: Tangalt n tɣellist diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index 2a381534ba5c2a..94e387107abb59 100644 --- a/config/locales/simple_form.lad.yml +++ b/config/locales/simple_form.lad.yml @@ -237,6 +237,7 @@ lad: warn: Eskonde kon una avertensya form_admin_settings: activity_api_enabled: Publika estatistikas adjustadas sovre la aktivita del utilizador kon la API + app_icon: Ikono de aplikasyon backups_retention_period: Periodo de retensyon de la dosya de utilizador bootstrap_timeline_accounts: Rekomenda siempre estos kuentos a muevos utilizadores closed_registrations_message: Mesaj personalizado kuando las enrejistrasyones no estan desponivles diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index ed27e08bc33466..9cc32457f7465f 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -82,6 +82,7 @@ lv: backups_retention_period: Lietotājiem ir iespēja izveidot savu ierakstu arhīvu lejupielādēšanai vēlāk. Kad iestatīta pozitīva vērtība, šie arhīvi tiks automātiski izdzēsti no krātuves pēc norādītā dienu skaita. bootstrap_timeline_accounts: Šie konti tiks piesprausti jauno lietotāju ieteikumu augšdaļā. closed_registrations_message: Tiek rādīts, kad reģistrēšanās ir slēgta + content_cache_retention_period: Visi ieraksti no citiem serveriem (tajā skaitā pastiprinājumi un atbildes) tiks izdzēsti pēc norādītā dienu skaita, neņemot vērā vietēja lietotāja mijiedarbību ar šādiem ierakstiem. Tas ietver ierakstus, kurus vietējs lietotājs ir atzīmējis kā grāmatzīmi vai pievienojis izlasē. Tiks zaudēti arī privāti pieminējumi starp lietotājiem no dažādiem serveriem, un tos nebūs iespējams atgūt. Šī iestatījuma izmantošana ir paredzēta īpašam nolūkam paredzētiem serveriem un neatbilst tam, ko sagaida vairums lietotāju, kad pielietots vispārējas izmantošanas serveros. custom_css: Vari lietot pielāgotus stilus Mastodon tīmekļa versijā. favicon: WEBP, PNG, GIF vai JPG. Aizstāj noklusējuma Mastodon favikonu ar pielāgotu. mascot: Ignorē ilustrāciju uzlabotajā tīmekļa saskarnē. diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml index 9d3845e7a752a6..aa8dbe76936020 100644 --- a/config/locales/simple_form.sk.yml +++ b/config/locales/simple_form.sk.yml @@ -126,7 +126,7 @@ sk: setting_system_font_ui: Použi základné systémové písmo setting_theme: Vzhľad webu setting_trends: Ukáž dnešné trendy - setting_unfollow_modal: Vyžaduj potvrdenie pred skončením sledovania iného užívateľa + setting_unfollow_modal: Vyžaduj potvrdenie pred tým, než niekoho prestaneš sledovať setting_use_blurhash: Ukáž farebné prechody pre skryté médiá setting_use_pending_items: Pomalý režim severity: Závažnosť diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index eab025c6655466..010bb262adcd27 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -4,12 +4,12 @@ vi: hints: account: attribution_domains_as_text: Bảo vệ khỏi những sự gán ghép sai. - discoverable: Các tút và hồ sơ công khai của bạn có thể được giới thiệu hoặc đề xuất ở nhiều khu vực khác nhau của Mastodon và hồ sơ của bạn có thể được đề xuất cho những người dùng khác. + discoverable: Hồ sơ và tút công khai của bạn được đề xuất cho những người dùng Mastodon khác. display_name: Tên đầy đủ hoặc biệt danh đều được. fields: Trang blog của bạn, nghề nghiệp, tuổi hoặc bất cứ thứ gì. - indexable: Tút công khai của bạn sẽ xuất hiện khi tìm kiếm trên Mastodon. Những người đã tương tác với tút của bạn có thể tìm kiếm chúng. - note: 'Bạn có thể @nhắnriêng ai đó hoặc #hashtags.' - show_collections: Mọi người sẽ biết những bạn theo dõi và người theo dõi bạn. Những người bạn theo dõi sẽ vẫn thấy rằng bạn theo dõi họ. + indexable: Mọi người có thể tìm kiếm và tương tác với những tút công khai của bạn trên Mastodon. + note: 'Bạn có thể @aiđó hoặc #hashtags.' + show_collections: Mọi người sẽ biết những bạn theo dõi và người theo dõi bạn. unlocked: Mọi người sẽ theo dõi bạn mà không cần bạn cho phép. account_alias: acct: Nhập tên_người_dùng@máy chủ của tài khoản cũ @@ -42,7 +42,7 @@ vi: autofollow: Những người đăng ký sẽ tự động theo dõi bạn avatar: WEBP, PNG, GIF hoặc JPG, tối đa %{size}. Sẽ bị nén xuống %{dimensions}px bot: Tài khoản này tự động thực hiện các hành động và không được quản lý bởi người thật - context: Chọn một hoặc nhiều nơi mà bộ lọc sẽ áp dụng + context: Chọn những nơi mà bộ lọc sẽ áp dụng current_password: Vì mục đích bảo mật, vui lòng nhập mật khẩu của tài khoản hiện tại current_username: Để xác nhận, vui lòng nhập tên người dùng của tài khoản hiện tại digest: Chỉ gửi sau một thời gian dài không hoạt động hoặc khi bạn nhận được tin nhắn (trong thời gian vắng mặt) @@ -51,7 +51,7 @@ vi: inbox_url: Sao chép URL của máy chủ mà bạn muốn dùng irreversible: Các tút đã lọc sẽ không thể phục hồi, kể cả sau khi xóa bộ lọc locale: Ngôn ngữ của giao diện, email và thông báo đẩy - password: Dùng ít nhất 8 ký tự + password: Tối thiểu 8 ký tự phrase: Sẽ được hiện thị trong văn bản hoặc cảnh báo nội dung của một tút scopes: Ứng dụng sẽ được phép truy cập những API nào. Nếu bạn chọn quyền cấp cao nhất, không cần chọn quyền nhỏ. setting_aggregate_reblogs: Nếu một tút đã được đăng lại thì những lượt đăng lại sau sẽ không hiện trên bảng tin nữa @@ -74,8 +74,8 @@ vi: filters: action: Chọn hành động sẽ thực hiện khi một tút khớp với bộ lọc actions: - hide: Ẩn hoàn toàn nội dung đã lọc, như thể nó không tồn tại - warn: Ẩn nội dung đã lọc đằng sau một cảnh báo đề cập đến tiêu đề của bộ lọc + hide: Ẩn hoàn toàn, như thể nó không tồn tại + warn: Hiện cảnh báo và bộ lọc form_admin_settings: activity_api_enabled: Số lượng tút được đăng trong máy chủ, người dùng đang hoạt động và đăng ký mới hàng tuần app_icon: WEBP, PNG, GIF hoặc JPG. Dùng biểu tượng tùy chỉnh trên thiết bị di động. @@ -214,7 +214,7 @@ vi: setting_default_sensitive: Đánh dấu media nhạy cảm setting_delete_modal: Hỏi trước khi xóa tút setting_disable_hover_cards: Tắt thẻ xem trước hồ sơ - setting_disable_swiping: Không dùng chuyển động vuốt + setting_disable_swiping: Tắt thao tác vuốt setting_display_media: Media nhạy cảm setting_display_media_default: Mặc định setting_display_media_hide_all: Ẩn toàn bộ @@ -226,7 +226,7 @@ vi: setting_theme: Giao diện setting_trends: Hiển thị xu hướng trong ngày setting_unfollow_modal: Hỏi trước khi bỏ theo dõi ai đó - setting_use_blurhash: Phủ màu media nhạy cảm + setting_use_blurhash: Làm mờ media nhạy cảm setting_use_pending_items: Không tự động cập nhật bảng tin severity: Mức độ nghiêm trọng sign_in_token_attempt: Mã an toàn @@ -305,13 +305,13 @@ vi: label: Đã có phiên bản Mastodon mới none: Không bao giờ thông báo (không đề xuất) patch: Thông báo bản cập sửa lỗi - trending_tag: Phê duyệt nội dung nổi bật mới + trending_tag: Phê duyệt xu hướng mới rule: hint: Thông tin thêm text: Nội quy settings: indexable: Cho phép hiện hồ sơ trong công cụ tìm kiếm - show_application: Cho phép hiện ứng dụng dùng để đăng tút + show_application: Hiện ứng dụng dùng để đăng tút tag: listable: Cho phép xuất hiện trong tìm kiếm và đề xuất name: Hashtag diff --git a/config/locales/sk.yml b/config/locales/sk.yml index d7eacb68509796..8076682ed46e12 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -394,6 +394,7 @@ sk: resolve: Preveď doménu not_permitted: Nepovolená resolved_through_html: Prevedená cez %{domain} + title: Blokované e-mailové domény export_domain_allows: new: title: Nahraj povolené domény @@ -401,6 +402,7 @@ sk: export_domain_blocks: import: existing_relationships_warning: Existujúce vzťahy nasledovania + private_comment_template: 'Importované z: %{source} dňa %{date}' title: Nahraj zákazy domén new: title: Nahraj zákazy domén @@ -1097,7 +1099,7 @@ sk: subject: "%{name} si obľúbil/a tvoj príspevok" title: Novo obľúbené follow: - body: "%{name} ťa teraz následuje!" + body: "%{name} ťa teraz nasleduje!" subject: "%{name} ťa teraz nasleduje" title: Nový sledovateľ follow_request: @@ -1166,7 +1168,7 @@ sk: follow_failure: Nemožno nasledovať niektoré z vybraných účtov. follow_selected_followers: Následuj označených sledovatelov followers: Následovatelia - following: Následovaní + following: Nasledovaní invited: Pozvaný/á last_active: Naposledy aktívny most_recent: Najnovšie @@ -1226,7 +1228,6 @@ sk: delete: Vymazanie účtu development: Vývoj edit_profile: Uprav profil - export: Exportuj dáta featured_tags: Zvýraznené haštagy import: Importuj import_and_export: Import a export diff --git a/config/locales/sl.yml b/config/locales/sl.yml index c8e806bf35efa9..286bece8778bd1 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1729,7 +1729,6 @@ sl: delete: Brisanje računa development: Razvoj edit_profile: Uredi profil - export: Izvoz podatkov featured_tags: Vključeni ključniki import: Uvozi import_and_export: Uvoz in izvoz diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 294c8a888f043f..2f05d7860cb3cd 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -296,6 +296,7 @@ sq: filter_by_action: Filtroji sipas veprimit filter_by_user: Filtroji sipas përdoruesit title: Regjistër auditimesh + unavailable_instance: "(emër përkatësie jo i passhëm)" announcements: destroyed_msg: Lajmërimi u fshi me sukses! edit: @@ -870,6 +871,9 @@ sq: message_html: S’keni përcaktuar ndonjë rregull shërbyesi. sidekiq_process_check: message_html: S’ka proces Sidekiq në punë për %{value} radhë. Ju lutemi, shqyrtoni formësimin tuaj për Sidekiq-un + software_version_check: + action: Shihni përditësimet e gatshme + message_html: Ka gati një përditësim Mastodon-i. software_version_critical_check: action: Shihni përditësimet e gatshme message_html: Ka të gatshëm një përditësim kritik të Mastodon-it, ju lutemi, përditësojeni sa më shpejt të jetë e mundur. @@ -1684,7 +1688,7 @@ sq: delete: Fshirje llogarie development: Zhvillim edit_profile: Përpunoni profilin - export: Eksportim të dhënash + export: Eksportim featured_tags: Hashtag-ë të zgjedhur import: Importo import_and_export: Importim dhe eksportim diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index bfb52c275b66b1..ad14d9d131f57f 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -1619,7 +1619,6 @@ sr-Latn: delete: Brisanje naloga development: Razvoj edit_profile: Uređivanje profila - export: Izvoz podataka featured_tags: Istaknute heš oznake import: Uvoz import_and_export: Uvoz i izvoz diff --git a/config/locales/sr.yml b/config/locales/sr.yml index af7e7ab8d6945e..fc92b98176186e 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1649,7 +1649,6 @@ sr: delete: Брисање налога development: Развој edit_profile: Уређивање профила - export: Извоз података featured_tags: Истакнуте хеш ознаке import: Увоз import_and_export: Увоз и извоз diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 6146cfc8d7feeb..dadd5f160030dd 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -860,6 +860,8 @@ sv: message_html: Du har inte definierat några serverregler. sidekiq_process_check: message_html: Ingen Sidekiq-process körs för kön/köerna %{value}. Vänligen kontrollera din Sidekiq-konfiguration + software_version_check: + message_html: En Mastodon-uppdatering är tillgänglig. software_version_critical_check: action: Se tillgängliga uppdateringar message_html: En kritisk uppdatering för Mastodon är tillgänglig. Uppdatera så snart som möjligt. @@ -1645,7 +1647,7 @@ sv: delete: Konto radering development: Utveckling edit_profile: Redigera profil - export: Exportera data + export: Export featured_tags: Utvalda hashtaggar import: Importera import_and_export: Import och export diff --git a/config/locales/th.yml b/config/locales/th.yml index d56385f2611add..3cb802afe3e981 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -861,12 +861,15 @@ th: message_html: คุณไม่ได้กำหนดกฎของเซิร์ฟเวอร์ใด ๆ sidekiq_process_check: message_html: ไม่มีกระบวนการ Sidekiq ที่กำลังทำงานสำหรับคิว %{value} โปรดตรวจทานการกำหนดค่า Sidekiq ของคุณ + software_version_check: + action: ดูการอัปเดตที่พร้อมใช้งาน + message_html: มีการอัปเดต Mastodon ที่พร้อมใช้งาน software_version_critical_check: action: ดูการอัปเดตที่พร้อมใช้งาน message_html: มีการอัปเดต Mastodon สำคัญพร้อมใช้งาน โปรดอัปเดตโดยเร็วที่สุดเท่าที่จะเป็นไปได้ software_version_patch_check: action: ดูการอัปเดตที่พร้อมใช้งาน - message_html: มีการอัปเดต Mastodon ที่แก้ไขข้อบกพร่องพร้อมใช้งาน + message_html: มีการอัปเดต Mastodon ที่แก้ไขข้อบกพร่องที่พร้อมใช้งาน upload_check_privacy_error: action: ตรวจสอบที่นี่สำหรับข้อมูลเพิ่มเติม message_html: "เว็บเซิร์ฟเวอร์ของคุณกำหนดค่าไม่ถูกต้อง ความเป็นส่วนตัวของผู้ใช้ของคุณตกอยู่ในความเสี่ยง" @@ -1666,7 +1669,7 @@ th: delete: การลบบัญชี development: การพัฒนา edit_profile: แก้ไขโปรไฟล์ - export: การส่งออกข้อมูล + export: ส่งออก featured_tags: แฮชแท็กที่น่าสนใจ import: การนำเข้า import_and_export: การนำเข้าและการส่งออก diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 16dd4c899ded7c..738263191150de 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -875,6 +875,9 @@ tr: message_html: Herhangi bir sunucu kuralı belirlemediniz. sidekiq_process_check: message_html: "%{value} kuyruk(lar)ı için herhangi bir Sidekiq süreci çalışmıyor. Lütfen Sidekiq yapılandırmanızı gözden geçirin" + software_version_check: + action: Mevcut güncellemeleri görün + message_html: Mastodon güncellemesi mevcut. software_version_critical_check: action: Mevcut güncellemeleri göster message_html: Kritik bir Mastodon güncellemesi var, lütfen en kısa sürede güncelleyin. @@ -1692,7 +1695,7 @@ tr: delete: Hesap silme development: Geliştirme edit_profile: Profili düzenle - export: Veriyi dışa aktar + export: Dışa Aktar featured_tags: Öne çıkan etiketler import: İçe aktar import_and_export: İçe ve dışa aktar diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 0ef08a15555659..de1847a745aa05 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -903,6 +903,9 @@ uk: message_html: Ви не визначили будь-які правила сервера. sidekiq_process_check: message_html: Не працює процес Sidekiq для %{value} черги. Перегляньте конфігурації вашого Sidekiq + software_version_check: + action: Переглянути доступні оновлення + message_html: Доступне оновлення Mastodon. software_version_critical_check: action: Переглянути доступні оновлення message_html: Виявлено критичне оновлення Mastodon. Оновіться якнайшвидше. @@ -1744,7 +1747,7 @@ uk: delete: Видалення облікового запису development: Розробка edit_profile: Редагувати профіль - export: Експорт даних + export: Експорт featured_tags: Рекомендовані хештеґи import: Імпорт import_and_export: Імпорт та експорт diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 98696aef7c8b63..7e44e76e44e762 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -44,7 +44,7 @@ vi: submit: Thay đổi email title: Thay đổi email cho %{username} change_role: - changed_msg: Vai trò đã thay đổi thành công! + changed_msg: Đã cập nhật vai trò! edit_roles: Quản lý vai trò người dùng label: Đổi vai trò no_role: Chưa có vai trò @@ -55,7 +55,7 @@ vi: custom: Tùy chỉnh delete: Xóa dữ liệu deleted: Đã xóa - demote: Xóa vai trò + demote: Hạ vai trò destroyed_msg: Dữ liệu %{username} sẽ được lên lịch xóa ngay bây giờ disable: Khóa disable_sign_in_token_auth: Tắt xác minh bằng email @@ -91,7 +91,7 @@ vi: moderation: active: Hoạt động all: Tất cả - disabled: Đã tắt + disabled: Khóa đăng nhập pending: Chờ silenced: Hạn chế suspended: Vô hiệu hóa @@ -108,7 +108,7 @@ vi: previous_strikes: Lịch sử kiểm duyệt previous_strikes_description_html: other: Người này bị cảnh cáo %{count} lần. - promote: Chỉ định vai trò + promote: Nâng vai trò protocol: Giao thức public: Công khai push_subscription_expires: Đăng ký PuSH hết hạn @@ -153,8 +153,8 @@ vi: suspension_irreversible: Toàn bộ dữ liệu của người này sẽ bị xóa hết. Bạn vẫn có thể ngừng vô hiệu hóa nhưng dữ liệu sẽ không thể phục hồi. suspension_reversible_hint_html: Mọi dữ liệu của người này sẽ bị xóa sạch vào %{date}. Trước thời hạn này, dữ liệu vẫn có thể phục hồi. Nếu bạn muốn xóa dữ liệu của người này ngay lập tức, hãy tiếp tục. title: Tài khoản - unblock_email: Mở khóa địa chỉ email - unblocked_email_msg: Mở khóa thành công địa chỉ email của %{username} + unblock_email: Bỏ chặn địa chỉ email + unblocked_email_msg: Đã bỏ chặn địa chỉ email của %{username} unconfirmed_email: Email chưa được xác minh undo_sensitized: Đánh dấu bình thường undo_silenced: Bỏ hạn chế @@ -170,42 +170,42 @@ vi: action_logs: action_types: approve_appeal: Chấp nhận kháng cáo - approve_user: Chấp nhận đăng ký + approve_user: Duyệt đăng ký assigned_to_self_report: Tự xử lý báo cáo change_email_user: Đổi email người dùng change_role_user: Đổi vai trò confirm_user: Xác minh create_account_warning: Cảnh cáo create_announcement: Tạo thông báo mới - create_canonical_email_block: Tạo chặn email + create_canonical_email_block: Chặn địa chỉ email create_custom_emoji: Tạo emoji create_domain_allow: Cho phép máy chủ create_domain_block: Chặn máy chủ create_email_domain_block: Tạo chặn tên miền email - create_ip_block: Tạo chặn IP mới - create_unavailable_domain: Máy chủ không khả dụng + create_ip_block: Chặn IP + create_unavailable_domain: Ngừng liên hợp create_user_role: Tạo vai trò - demote_user: Xóa vai trò + demote_user: Hạ vai trò destroy_announcement: Xóa thông báo - destroy_canonical_email_block: Bỏ chặn email + destroy_canonical_email_block: Bỏ chặn địa chỉ email destroy_custom_emoji: Xóa emoji destroy_domain_allow: Bỏ thanh trừng máy chủ destroy_domain_block: Bỏ chặn máy chủ destroy_email_domain_block: Bỏ chặn tên miền email destroy_instance: Thanh trừng máy chủ - destroy_ip_block: Xóa IP đã chặn + destroy_ip_block: Bỏ chặn IP destroy_status: Xóa tút - destroy_unavailable_domain: Xóa máy chủ không khả dụng + destroy_unavailable_domain: Tái liên hợp destroy_user_role: Xóa vai trò disable_2fa_user: Vô hiệu hóa 2FA disable_custom_emoji: Vô hiệu hóa emoji disable_sign_in_token_auth_user: Tắt xác minh bằng email cho người dùng disable_user: Vô hiệu hóa đăng nhập - enable_custom_emoji: Cho phép emoji + enable_custom_emoji: Duyệt emoji enable_sign_in_token_auth_user: Bật xác minh bằng email cho người dùng - enable_user: Bỏ vô hiệu hóa đăng nhập + enable_user: Cho phép đăng nhập memorialize_account: Đánh dấu tưởng niệm - promote_user: Chỉ định vai trò + promote_user: Nâng vai trò reject_appeal: Từ chối kháng cáo reject_user: Từ chối đăng ký remove_avatar_user: Xóa ảnh đại diện @@ -213,11 +213,11 @@ vi: resend_user: Gửi lại email xác minh reset_password_user: Đặt lại mật khẩu resolve_report: Xử lý báo cáo - sensitive_account: Áp đặt nhạy cảm - silence_account: Áp đặt ẩn - suspend_account: Áp đặt vô hiệu hóa + sensitive_account: Gán nhạy cảm + silence_account: Gán ẩn + suspend_account: Gán vô hiệu hóa unassigned_report: Báo cáo chưa xử lý - unblock_email_account: Mở khóa địa chỉ email + unblock_email_account: Bỏ chặn địa chỉ email unsensitive_account: Bỏ nhạy cảm unsilence_account: Bỏ ẩn unsuspend_account: Bỏ vô hiệu hóa @@ -229,7 +229,7 @@ vi: update_status: Cập nhật tút update_user_role: Cập nhật vai trò actions: - approve_appeal_html: "%{name} đã chấp nhận kháng cáo của %{target}" + approve_appeal_html: "%{name} đã duyệt kháng cáo của %{target}" approve_user_html: "%{name} đã chấp nhận đăng ký từ %{target}" assigned_to_self_report_html: "%{name} tự xử lý báo cáo %{target}" change_email_user_html: "%{name} đã thay đổi địa chỉ email của %{target}" @@ -237,7 +237,7 @@ vi: confirm_user_html: "%{name} đã xác minh địa chỉ email của %{target}" create_account_warning_html: "%{name} đã cảnh cáo %{target}" create_announcement_html: "%{name} tạo thông báo mới %{target}" - create_canonical_email_block_html: "%{name} đã chặn email với hash %{target}" + create_canonical_email_block_html: "%{name} đã chặn địa chỉ email với hash %{target}" create_custom_emoji_html: "%{name} đã tải lên biểu tượng cảm xúc mới %{target}" create_domain_allow_html: "%{name} kích hoạt liên hợp với %{target}" create_domain_block_html: "%{name} chặn máy chủ %{target}" @@ -245,9 +245,9 @@ vi: create_ip_block_html: "%{name} đã chặn IP %{target}" create_unavailable_domain_html: "%{name} ngưng phân phối với máy chủ %{target}" create_user_role_html: "%{name} đã tạo vai trò %{target}" - demote_user_html: "%{name} đã xóa vai trò của %{target}" + demote_user_html: "%{name} đã hạ vai trò của %{target}" destroy_announcement_html: "%{name} xóa thông báo %{target}" - destroy_canonical_email_block_html: "%{name} đã bỏ chặn email với hash %{target}" + destroy_canonical_email_block_html: "%{name} đã bỏ chặn địa chỉ email với hash %{target}" destroy_custom_emoji_html: "%{name} đã xóa emoji %{target}" destroy_domain_allow_html: "%{name} đã ngừng liên hợp với %{target}" destroy_domain_block_html: "%{name} bỏ chặn máy chủ %{target}" @@ -261,11 +261,11 @@ vi: disable_custom_emoji_html: "%{name} đã ẩn emoji %{target}" disable_sign_in_token_auth_user_html: "%{name} đã tắt xác minh email của %{target}" disable_user_html: "%{name} vô hiệu hóa đăng nhập %{target}" - enable_custom_emoji_html: "%{name} cho phép Emoji %{target}" + enable_custom_emoji_html: "%{name} cho phép emoji %{target}" enable_sign_in_token_auth_user_html: "%{name} đã bật xác minh email của %{target}" enable_user_html: "%{name} bỏ vô hiệu hóa đăng nhập %{target}" memorialize_account_html: "%{name} đã biến tài khoản %{target} thành một trang tưởng niệm" - promote_user_html: "%{name} chỉ định vai trò cho %{target}" + promote_user_html: "%{name} đã nâng vai trò của %{target}" reject_appeal_html: "%{name} đã từ chối kháng cáo của %{target}" reject_user_html: "%{name} đã từ chối đăng ký từ %{target}" remove_avatar_user_html: "%{name} đã xóa ảnh đại diện của %{target}" @@ -277,7 +277,7 @@ vi: silence_account_html: "%{name} đã ẩn %{target}" suspend_account_html: "%{name} đã vô hiệu hóa %{target}" unassigned_report_html: "%{name} đã xử lý báo cáo %{target} chưa xử lí" - unblock_email_account_html: "%{name} mở khóa địa chỉ email của %{target}" + unblock_email_account_html: "%{name} bỏ chặn địa chỉ email của %{target}" unsensitive_account_html: "%{name} đánh dấu nội dung của %{target} là bình thường" unsilence_account_html: "%{name} đã bỏ ẩn %{target}" unsuspend_account_html: "%{name} đã bỏ vô hiệu hóa %{target}" @@ -287,7 +287,7 @@ vi: update_ip_block_html: "%{name} cập nhật chặn IP %{target}" update_report_html: "%{name} cập nhật báo cáo %{target}" update_status_html: "%{name} cập nhật tút của %{target}" - update_user_role_html: "%{name} đã thay đổi vai trò %{target}" + update_user_role_html: "%{name} đã cập nhật vai trò %{target}" deleted_account: tài khoản đã xóa empty: Không tìm thấy bản ghi. filter_by_action: Theo hành động @@ -328,7 +328,7 @@ vi: emoji: Emoji enable: Cho phép enabled: Đã cho phép - enabled_msg: Đã cho phép thành công Emoji này + enabled_msg: Đã cho phép emoji này xong image_hint: PNG hoặc GIF tối đa %{size} list: Danh sách listed: Liệt kê @@ -692,7 +692,7 @@ vi: manage_announcements: Quản lý thông báo manage_announcements_description: Cho phép quản lý thông báo trên máy chủ manage_appeals: Quản lý kháng cáo - manage_appeals_description: Cho phép xem xét kháng cáo đối với các hành động kiểm duyệt + manage_appeals_description: Cho phép thành viên kháng cáo đối với các hành động kiểm duyệt manage_blocks: Quản lý chặn manage_blocks_description: Cho phép người dùng tự chặn các nhà cung cấp email và địa chỉ IP manage_custom_emojis: Quản lý emoji @@ -704,7 +704,7 @@ vi: manage_reports: Quản lý báo cáo manage_reports_description: Cho phép xem xét các báo cáo và thực hiện hành động kiểm duyệt đối với chúng manage_roles: Quản lý vai trò - manage_roles_description: Cho phép quản lý và chỉ định các vai trò nhỏ hơn họ + manage_roles_description: Cho phép quản lý và nâng cấp các vai trò nhỏ hơn họ manage_rules: Quản lý nội quy máy chủ manage_rules_description: Cho phép thay đổi nội quy máy chủ manage_settings: Quản lý thiết lập @@ -798,7 +798,7 @@ vi: patch: Bản vá - sửa lỗi và dễ dàng áp dụng các thay đổi version: Phiên bản statuses: - account: Tác giả + account: Người đăng application: Ứng dụng back_to_account: Quay lại trang tài khoản back_to_report: Quay lại trang báo cáo @@ -817,7 +817,7 @@ vi: open: Mở tút original_status: Tút gốc reblogs: Lượt đăng lại - status_changed: Tút đã thay đổi + status_changed: Tút đã sửa title: Toàn bộ tút trending: Xu hướng visibility: Hiển thị @@ -861,6 +861,9 @@ vi: message_html: Bạn chưa cập nhật nội quy máy chủ. sidekiq_process_check: message_html: Sidekiq không hoạt động khi truy vấn %{value}. Hãy kiểm tra lại cấu hình Sidekiq + software_version_check: + action: Bản cập nhật mới + message_html: Có bản cập nhật Mastodon mới. software_version_critical_check: action: Bản cập nhật mới message_html: Có bản cập nhật quan trọng của Mastodon, vui lòng cập nhật nhanh nhất có thể. @@ -896,7 +899,7 @@ vi: title: Quản trị trends: allow: Cho phép - approved: Đã cho phép + approved: Đã duyệt confirm_allow: Bạn có chắc muốn cho phép những hashtag đã chọn? confirm_disallow: Bạn có chắc muốn cấm những hashtag đã chọn? disallow: Cấm @@ -915,17 +918,17 @@ vi: no_publisher_selected: Không có nguồn đăng nào thay đổi vì không có nguồn đăng nào được chọn shared_by_over_week: other: "%{count} người chia sẻ tuần rồi" - title: Tin tức nổi bật + title: Xu hướng tin tức usage_comparison: Chia sẻ %{today} lần hôm nay, so với %{yesterday} lần hôm qua not_allowed_to_trend: Không được phép thành xu hướng - only_allowed: Chỉ cho phép + only_allowed: Đã cho phép pending_review: Đang chờ preview_card_providers: allowed: Tin tức từ nguồn này có thể lên xu hướng description_html: Đây là những nguồn mà từ đó các liên kết thường được chia sẻ trên máy chủ của bạn. Các liên kết sẽ không thể lên xu hướng trừ khi bạn cho phép nguồn. Sự cho phép (hoặc cấm) của bạn áp dụng luôn cho các tên miền phụ. rejected: Tin tức từ nguồn này không thể lên xu hướng title: Nguồn đăng - rejected: Đã cấm + rejected: Từ chối statuses: allow: Cho phép tút allow_account: Cho phép người đăng @@ -936,11 +939,11 @@ vi: description_html: Đây là những tút đang được chia sẻ và yêu thích rất nhiều trên máy chủ của bạn. Nó có thể giúp người mới và người cũ tìm thấy nhiều người hơn để theo dõi. Không có tút nào được hiển thị công khai cho đến khi bạn cho phép người đăng và người cho phép đề xuất tài khoản của họ cho người khác. Bạn cũng có thể cho phép hoặc từ chối từng tút riêng. disallow: Cấm tút disallow_account: Cấm người đăng - no_status_selected: Không có tút xu hướng nào thay đổi vì không có tút nào được chọn - not_discoverable: Tác giả đã chọn không tham gia mục khám phá + no_status_selected: Bạn chưa chọn mục nào + not_discoverable: Người đăng đã chọn không tham gia mục khám phá shared_by: other: Được thích và đăng lại %{friendly_count} lần - title: Tút xu hướng + title: Xu hướng tút tags: current_score: Chỉ số gần đây %{score} dashboard: @@ -956,9 +959,9 @@ vi: not_trendable: Không cho lên xu hướng not_usable: Không được phép dùng peaked_on_and_decaying: Đỉnh điểm %{date}, giờ đang giảm - title: Hashtag nổi bật + title: Xu hướng hashtag trendable: Cho phép lên xu hướng - trending_rank: 'Nổi bật #%{rank}' + trending_rank: 'Xu hướng #%{rank}' usable: Có thể dùng usage_comparison: Dùng %{today} lần hôm nay, so với %{yesterday} hôm qua used_by_over_week: @@ -1004,7 +1007,7 @@ vi: silence: hạn chế tài khoản của họ suspend: vô hiệu hóa tài khoản của họ body: "%{target} đã khiếu nại vì bị %{action_taken_by} %{type} vào %{date}. Họ cho biết:" - next_steps: Bạn có thể chấp nhận kháng cáo để hủy kiểm duyệt hoặc bỏ qua. + next_steps: Bạn có thể duyệt kháng cáo để hủy kiểm duyệt hoặc bỏ qua. subject: "%{username} đang khiếu nại quyết định kiểm duyệt trên %{instance}" new_critical_software_updates: body: Các phiên bản quan trọng mới của Mastodon đã được phát hành, bạn nên cập nhật càng sớm càng tốt! @@ -1022,12 +1025,12 @@ vi: new_trends: body: 'Các mục sau đây cần được xem xét trước khi chúng hiển thị công khai:' new_trending_links: - title: Tin tức nổi bật + title: Xu hướng tin tức new_trending_statuses: - title: Tút nổi bật + title: Xu hướng tút new_trending_tags: - title: Hashtag nổi bật - subject: Nội dung nổi bật chờ duyệt trên %{instance} + title: Xu hướng hashtag + subject: Xu hướng chờ duyệt trên %{instance} aliases: add_new: Kết nối tài khoản created_msg: Tạo thành công một tên hiển thị mới. Bây giờ bạn có thể bắt đầu di chuyển từ tài khoản cũ. @@ -1037,7 +1040,7 @@ vi: remove: Bỏ liên kết bí danh appearance: advanced_web_interface: Bố cục - advanced_web_interface_hint: Bố cục nhiều cột cho phép bạn chuyển bố cục hiển thị thành nhiều cột khác nhau. Thích hợp với màn hình rộng. + advanced_web_interface_hint: Chia giao diện thành nhiều cột, phù hợp với màn hình rộng. animations_and_accessibility: Hiệu ứng confirmation_dialogs: Hộp thoại xác nhận discovery: Khám phá @@ -1147,7 +1150,7 @@ vi: hint_html: Kiểm soát cách bạn được ghi nhận khi chia sẻ liên kết trên Mastodon. more_from_html: Thêm từ %{name} s_blog: "%{name}'s Blog" - title: Ghi nhận tác giả + title: Ghi nhận người đăng challenge: confirm: Tiếp tục hint_html: "Mẹo: Chúng tôi sẽ không hỏi lại mật khẩu của bạn sau này." @@ -1201,7 +1204,7 @@ vi: appealed_msg: Khiếu nại của bạn đã được gửi đi. Nếu nó được chấp nhận, bạn sẽ nhận được thông báo. appeals: submit: Gửi khiếu nại - approve_appeal: Chấp nhận kháng cáo + approve_appeal: Duyệt kháng cáo associated_report: Báo cáo đính kèm created_at: Ngày description_html: Đây là những cảnh cáo và áp đặt kiểm duyệt đối với bạn bởi đội ngũ %{instance}. @@ -1262,7 +1265,7 @@ vi: add_new: Thêm mới errors: limit: Bạn đã đạt tới số lượng hashtag tối đa - hint_html: "Làm nổi bật những hashtag thường dùng. Một công cụ tuyệt vời để theo dõi các tác phẩm sáng tạo và dự án dài hạn của bạn, các hashtag thường dùng sẽ hiển thị nổi bật trên hồ sơ của bạn và cho phép truy cập nhanh vào các tút." + hint_html: "Làm nổi bật những hashtag thường dùng. Một công cụ tuyệt vời để theo dõi các tác phẩm sáng tạo và dự án dài hạn của bạn, cũng như giúp truy cập nhanh vào các tút." filters: contexts: account: Trang hồ sơ @@ -1280,7 +1283,7 @@ vi: deprecated_api_multiple_keywords: Không thể thay đổi các tham số này từ ứng dụng này vì chúng áp dụng cho nhiều hơn một từ khóa bộ lọc. Sử dụng ứng dụng mới hơn hoặc giao diện web. invalid_context: Bối cảnh không hợp lệ hoặc không có index: - contexts: Bộ lọc %{contexts} + contexts: Lọc ở %{contexts} delete: Xóa bỏ empty: Chưa có bộ lọc nào. expires_in: Hết hạn trong %{distance} @@ -1336,7 +1339,7 @@ vi: merge: Hợp nhất merge_long: Giữ hồ sơ hiện có và thêm hồ sơ mới overwrite: Ghi đè - overwrite_long: Thay thế các bản ghi hiện tại bằng những cái mới + overwrite_long: Thay thế các bản ghi hiện tại bằng các bản ghi mới overwrite_preambles: blocking_html: Bạn sắp thay thế danh sách chặn với %{total_items} tài khoản từ %{filename}. bookmarks_html: Bạn sắp thay thế lượt lưu với %{total_items} tút từ %{filename}. @@ -1414,7 +1417,7 @@ vi: description_html: Nếu có lần đăng nhập đáng ngờ, hãy đổi ngay mật khẩu và bật xác minh 2 bước. empty: Không có lịch sử đăng nhập failed_sign_in_html: Đăng nhập thất bại bằng %{method} từ %{ip} (%{browser}) - successful_sign_in_html: Đăng nhập thành công bằng %{method} từ %{ip} (%{browser}) + successful_sign_in_html: Đăng nhập bằng %{method} từ %{ip} (%{browser}) title: Lịch sử đăng nhập mail_subscriptions: unsubscribe: @@ -1555,13 +1558,13 @@ vi: posting_defaults: Mặc định cho tút public_timelines: Bảng tin privacy: - hint_html: "Tùy chỉnh cách mọi người tìm thấy hồ sơ và các tút của bạn. Nhiều tính năng trong Mastodon có thể giúp bạn tiếp cận nhiều đối tượng hơn khi được bật. Hãy xem lại các cài đặt này để đảm bảo chúng phù hợp với bạn." + hint_html: "Tùy chỉnh cách mọi người tìm thấy hồ sơ và tút của bạn. Hãy đảm bảo các thiết lập sau phù hợp với bạn." privacy: Riêng tư privacy_hint_html: Kiểm soát mức độ chi tiết bạn muốn tiết lộ. Mọi người khám phá các hồ sơ thú vị và các ứng dụng thú vị bằng cách theo dõi những người khác và xem họ đăng từ ứng dụng nào, nhưng có thể bạn muốn ẩn nó đi. reach: Tiếp cận reach_hint_html: Kiểm soát cách bạn được khám phá và theo dõi. Bạn có muốn tút của mình xuất hiện trên màn hình Khám phá không? Bạn có muốn người khác nhìn thấy bạn trong các đề xuất theo dõi của họ không? Bạn muốn tự động chấp nhận tất cả những người theo dõi mới hay tự duyệt từng người theo dõi? search: Tìm kiếm - search_hint_html: Kiểm soát cách tìm thấy bạn. Bạn có muốn mọi người tìm thấy bạn bằng những gì bạn đã đăng công khai không? Bạn có muốn những người bên ngoài Mastodon tìm thấy hồ sơ của bạn khi tìm kiếm trên web không? Xin lưu ý rằng không thể đảm bảo loại trừ hoàn toàn khỏi tất cả các công cụ tìm kiếm đối với thông tin công khai. + search_hint_html: Kiểm soát cách tìm thấy bạn. Bạn có muốn mọi người tìm thấy bạn bằng những gì bạn đã đăng công khai không? Bạn có muốn những người bên ngoài Mastodon tìm thấy hồ sơ của bạn khi tìm kiếm trên web không? Lưu ý là không thể đảm bảo tránh khỏi các công cụ tìm kiếm đối với thông tin công khai. title: Riêng tư và tiếp cận privacy_policy: title: Chính sách bảo mật @@ -1666,7 +1669,7 @@ vi: delete: Xóa tài khoản development: Lập trình edit_profile: Sửa hồ sơ - export: Xuất dữ liệu + export: Xuất featured_tags: Hashtag thường dùng import: Nhập dữ liệu import_and_export: Dữ liệu @@ -1675,7 +1678,7 @@ vi: preferences: Chung profile: Hồ sơ relationships: Quan hệ - severed_relationships: Mối quan hệ bị cắt đứt + severed_relationships: Quan hệ bị cắt đứt statuses_cleanup: Tự động xóa tút cũ strikes: Lần cảnh cáo two_factor_authentication: Xác minh 2 bước @@ -1688,7 +1691,7 @@ vi: user_domain_block: Bạn đã chặn %{target_name} lost_followers: Mất người theo dõi lost_follows: Mất người đang theo dõi - preamble: Bạn có thể mất số lượt theo dõi và người theo dõi khi chặn một máy chủ hoặc khi kiểm duyệt viên của bạn quyết định tạm dừng máy chủ từ xa. Khi điều đó xảy ra, bạn sẽ có thể tải xuống danh sách các mối quan hệ đã bị cắt đứt, để kiểm tra và nhập vào máy chủ khác. + preamble: Khi bạn hoặc kiểm duyệt viên máy chủ của bạn chặn một máy chủ, người bạn đang theo dõi và người theo dõi bạn có thể sẽ bị mất. Khi điều đó xảy ra, hãy vào đây tải xuống danh sách các mối quan hệ đã bị cắt đứt, và nhập thủ công. purged: Thông tin về máy chủ này đã bị quản trị viên máy chủ của bạn xóa sạch. type: Sự kiện statuses: @@ -1769,7 +1772,7 @@ vi: contrast: Mastodon (Tương phản) default: Mastodon (Tối) mastodon-light: Mastodon (Sáng) - system: Tự động (chủ đề hệ thống) + system: Theo hệ thống time: formats: default: "%-d.%m.%Y %H:%M" @@ -1832,14 +1835,14 @@ vi: spam: Spam violation: Nội dung vi phạm quy tắc cộng đồng explanation: - delete_statuses: Vài tút của bạn đã vi phạm nội quy máy chủ và tạm thời bị ẩn bởi kiểm duyệt viên của %{instance}. + delete_statuses: Tút của bạn đã vi phạm nội quy máy chủ và tạm thời bị ẩn bởi kiểm duyệt viên của %{instance}. disable: Bạn không còn có thể sử dụng tài khoản của mình, nhưng hồ sơ của bạn và dữ liệu khác vẫn còn nguyên. Bạn có thể yêu cầu sao lưu dữ liệu của mình, thay đổi cài đặt tài khoản hoặc xóa tài khoản của bạn. mark_statuses_as_sensitive: Vài tút của bạn đã bị kiểm duyệt viên %{instance} đánh dấu nhạy cảm. Mọi người cần nhấn vào media để xem nó. Bạn có thể tự đánh dấu tài khoản của bạn là nhạy cảm. sensitive: Từ giờ trở đi, tất cả các media của bạn bạn tải lên sẽ được đánh dấu là nhạy cảm và ẩn đằng sau cảnh báo nhấp chuột. silence: Bạn vẫn có thể sử dụng tài khoản của mình, nhưng chỉ những người đang theo dõi bạn mới thấy bài đăng của bạn. Bạn cũng bị loại khỏi các tính năng khám phá khác. Tuy nhiên, những người khác vẫn có thể theo dõi bạn. suspend: Bạn không còn có thể sử dụng tài khoản của bạn, hồ sơ và các dữ liệu khác không còn có thể truy cập được. Trong vòng 30 ngày, bạn vẫn có thể đăng nhập để yêu cầu bản sao dữ liệu của mình cho đến khi dữ liệu bị xóa hoàn toàn, nhưng chúng tôi sẽ giữ lại một số dữ liệu cơ bản để ngăn bạn thoát khỏi việc vô hiệu hóa. reason: 'Lý do:' - statuses: 'Tút lưu ý:' + statuses: 'Tút vi phạm:' subject: delete_statuses: Những tút %{acct} của bạn đã bị xóa bỏ disable: Tài khoản %{acct} của bạn đã bị vô hiệu hóa @@ -1905,7 +1908,7 @@ vi: seamless_external_login: Bạn đã đăng nhập thông qua một dịch vụ bên ngoài, vì vậy mật khẩu và email không khả dụng. signed_in_as: 'Đăng nhập bằng:' verification: - extra_instructions_html: Mẹo: Liên kết trên trang web của bạn có thể ẩn. Phần quan trọng là rel="me" ngăn chặn việc mạo danh trên các trang web có nội dung do người dùng tạo. Bạn thậm chí có thể sử dụng một thẻ link trên header của trang thay vì a, nhưng HTML phải có thể truy cập được mà không cần thực thi JavaScript. + extra_instructions_html: Mẹo: Có thể ẩn liên kết trên trang web của bạn. Quan trọng là rel="me" giúp ngăn chặn việc mạo danh trên các trang web có nội dung do người dùng tạo. Bạn cũng có thể sử dụng một thẻ link trên header của trang thay vì a, nhưng HTML phải có thể truy cập được mà không cần thực thi JavaScript. here_is_how: Cách thực hiện hint_html: "Xác minh danh tính trên Mastodon là dành cho tất cả mọi người. Dựa trên các tiêu chuẩn web mở, miễn phí bây giờ và mãi mãi. Tất cả những gì bạn cần là một trang web cá nhân để mọi người nhận ra bạn. Khi bạn liên kết đến trang web này từ hồ sơ của mình, chúng tôi sẽ kiểm tra xem trang web đó có liên kết lại với hồ sơ của bạn hay không và hiển thị một chỉ báo trực quan trên đó." instructions_html: Sao chép và dán mã bên dưới vào mã nguồn trang web của bạn. Sau đó, thêm địa chỉ trang web của bạn vào một trong các trường metadata trên hồ sơ của bạn từ tab "Sửa hồ sơ" và lưu thay đổi. @@ -1918,7 +1921,7 @@ vi: error: Có vấn đề khi thêm khóa bảo mật. Xin thử lại. success: Đã thêm khóa bảo mật mới thành công. delete: Xóa - delete_confirmation: Bạn thật sự muốn xóa khóa bảo mật này? + delete_confirmation: Bạn có chắc muốn xóa khóa bảo mật này? description_html: Nếu bạn kích hoạt khóa bảo mật, bạn sẽ cần dùng một trong những khóa bảo mật đó mỗi khi đăng nhập. destroy: error: Có vấn đề khi xóa khóa bảo mật. Xin thử lại. diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 8b34da076a0162..a73871115b3a72 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -861,6 +861,9 @@ zh-CN: message_html: 你没有定义任何服务器规则。 sidekiq_process_check: message_html: "%{value} 队列未运行任何 Sidekiq 进程。请检查你的 Sidekiq 配置" + software_version_check: + action: 查看可用更新 + message_html: 有一个 Mastodon 更新可用。 software_version_critical_check: action: 查看可用更新 message_html: 有一个紧急Mastodon紧急更新可用,请尽快更新。 diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 598c65d0494ec7..c0726fc2f7d04e 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -1564,7 +1564,6 @@ zh-HK: delete: 刪除帳戶 development: 開發 edit_profile: 修改個人資料 - export: 匯出 featured_tags: 推薦的標籤 import: 匯入 import_and_export: 匯入及匯出 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 41c4c8a534e482..4079f68a50c38e 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -863,6 +863,9 @@ zh-TW: message_html: 您尚未定義任何伺服器規則。 sidekiq_process_check: message_html: 沒有佇列 %{value} 的 Sidekiq 行程,請檢查您的 Sidekiq 設定組態 + software_version_check: + action: 檢視可取得的更新 + message_html: 有可取得的 Mastodon 更新。 software_version_critical_check: action: 檢視可取得的更新 message_html: 有可取得的重要 Mastodon 更新,請立即升級。 diff --git a/config/routes.rb b/config/routes.rb index 86248dda412fc3..79b374e4132602 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -127,6 +127,8 @@ def redirect_with_vary(path) end resources :replies, only: [:index], module: :activitypub + resources :likes, only: [:index], module: :activitypub + resources :shares, only: [:index], module: :activitypub end resources :followers, only: [:index], controller: :follower_accounts diff --git a/config/routes/api.rb b/config/routes/api.rb index 48b35cc154218c..e758c8e5264bfa 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -126,6 +126,10 @@ get :search, to: 'search#index' end + namespace :domain_blocks do + resource :preview, only: [:show] + end + resource :domain_blocks, only: [:show, :create, :destroy] resource :directory, only: [:show] @@ -301,21 +305,6 @@ end end - concern :grouped_notifications do - resources :notifications, param: :group_key, only: [:index, :show] do - collection do - post :clear - get :unread_count - end - - member do - post :dismiss - end - - resources :accounts, only: [:index], module: :notifications - end - end - namespace :v2 do get '/search', to: 'search#index', as: :search @@ -342,11 +331,18 @@ resource :policy, only: [:show, :update] end - concerns :grouped_notifications - end + resources :notifications, param: :group_key, only: [:index, :show] do + collection do + post :clear + get :unread_count + end - namespace :v2_alpha, module: 'v2' do - concerns :grouped_notifications + member do + post :dismiss + end + + resources :accounts, only: [:index], module: :notifications + end end namespace :web do diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index a5471704ad1a83..0cc6ee3f8973d3 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -17,7 +17,7 @@ def patch end def default_prerelease - 'beta.2' + 'rc.1' end def prerelease diff --git a/lib/paperclip/blurhash_transcoder.rb b/lib/paperclip/blurhash_transcoder.rb index 150275bc9e078f..b4ff4a12a0e0f6 100644 --- a/lib/paperclip/blurhash_transcoder.rb +++ b/lib/paperclip/blurhash_transcoder.rb @@ -7,7 +7,7 @@ def make width, height, data = blurhash_params # Guard against segfaults if data has unexpected size - raise RangeError("Invalid image data size (expected #{width * height * 3}, got #{data.size})") if data.size != width * height * 3 # TODO: should probably be another exception type + raise RangeError, "Invalid image data size (expected #{width * height * 3}, got #{data.size})" if data.size != width * height * 3 # TODO: should probably be another exception type attachment.instance.blurhash = Blurhash.encode(width, height, data, **(options[:blurhash] || {})) diff --git a/package.json b/package.json index 1a3c86f728d4de..0465b4d44d8fb1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/mastodon", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.4.1", + "packageManager": "yarn@4.5.0", "engines": { "node": ">=18" }, @@ -42,6 +42,9 @@ "@babel/preset-react": "^7.22.3", "@babel/preset-typescript": "^7.21.5", "@babel/runtime": "^7.22.3", + "@dnd-kit/core": "^6.1.0", + "@dnd-kit/sortable": "^8.0.0", + "@dnd-kit/utilities": "^3.2.2", "@formatjs/intl-pluralrules": "^5.2.2", "@gamestdio/websocket": "^0.3.2", "@github/webauthn-json": "^2.1.1", diff --git a/public/embed.js b/public/embed.js index 3fb57469a96523..53372a38904982 100644 --- a/public/embed.js +++ b/public/embed.js @@ -81,7 +81,7 @@ const allowedPrefixes = (document.currentScript && document.currentScript.tagNam embeds.set(id, iframe); iframe.allow = 'fullscreen'; - iframe.sandbox = 'allow-scripts allow-same-origin'; + iframe.sandbox = 'allow-scripts allow-same-origin allow-popups'; iframe.style.border = 0; iframe.style.overflow = 'hidden'; iframe.style.display = 'block'; @@ -112,7 +112,7 @@ const allowedPrefixes = (document.currentScript && document.currentScript.tagNam iframe.width = container.clientWidth; iframe.height = 0; iframe.allow = 'fullscreen'; - iframe.sandbox = 'allow-scripts allow-same-origin'; + iframe.sandbox = 'allow-scripts allow-same-origin allow-popups'; iframe.style.border = 0; iframe.style.overflow = 'hidden'; iframe.style.display = 'block'; diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb index 7ae28e8e09bf00..ca986dcabbee40 100644 --- a/spec/controllers/activitypub/outboxes_controller_spec.rb +++ b/spec/controllers/activitypub/outboxes_controller_spec.rb @@ -69,9 +69,10 @@ expect(response.parsed_body) .to include( - orderedItems: be_an(Array).and(have_attributes(size: 2)) + orderedItems: be_an(Array) + .and(have_attributes(size: 2)) + .and(all(satisfy { |item| targets_public_collection?(item) })) ) - expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true end context 'when account is permanently suspended' do @@ -113,9 +114,10 @@ expect(response.parsed_body) .to include( - orderedItems: be_an(Array).and(have_attributes(size: 2)) + orderedItems: be_an(Array) + .and(have_attributes(size: 2)) + .and(all(satisfy { |item| targets_public_collection?(item) })) ) - expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) }).to be true end end @@ -132,9 +134,10 @@ expect(response.parsed_body) .to include( - orderedItems: be_an(Array).and(have_attributes(size: 3)) + orderedItems: be_an(Array) + .and(have_attributes(size: 3)) + .and(all(satisfy { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) })) ) - expect(response.parsed_body[:orderedItems].all? { |item| targets_public_collection?(item) || targets_followers_collection?(item, account) }).to be true end end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index 27821b0d4ec415..d7c2c2d3b02cc1 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -66,7 +66,6 @@ context 'when status is public' do let(:parent_visibility) { :public } - let(:page_json) { response.parsed_body[:first] } it 'returns http success and correct media type' do expect(response) @@ -78,16 +77,28 @@ context 'without only_other_accounts' do it "returns items with thread author's replies" do - expect(page_json).to be_a Hash - expect(page_json[:items]).to be_an Array - expect(page_json[:items].size).to eq 1 - expect(page_json[:items].all? { |item| targets_public_collection?(item) }).to be true + expect(response.parsed_body) + .to include( + first: be_a(Hash).and( + include( + items: be_an(Array) + .and(have_attributes(size: 1)) + .and(all(satisfy { |item| targets_public_collection?(item) })) + ) + ) + ) end context 'when there are few self-replies' do it 'points next to replies from other people' do - expect(page_json).to be_a Hash - expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=true', 'page=true') + expect(response.parsed_body) + .to include( + first: be_a(Hash).and( + include( + next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=true page=true)).any? } + ) + ) + ) end end @@ -97,8 +108,14 @@ end it 'points next to other self-replies' do - expect(page_json).to be_a Hash - expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=false', 'page=true') + expect(response.parsed_body) + .to include( + first: be_a(Hash).and( + include( + next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=false page=true)).any? } + ) + ) + ) end end end @@ -107,26 +124,31 @@ let(:only_other_accounts) { 'true' } it 'returns items with other public or unlisted replies' do - expect(page_json).to be_a Hash - expect(page_json[:items]).to be_an Array - expect(page_json[:items].size).to eq 3 + expect(response.parsed_body) + .to include( + first: be_a(Hash).and( + include(items: be_an(Array).and(have_attributes(size: 3))) + ) + ) end it 'only inlines items that are local and public or unlisted replies' do - inlined_replies = page_json[:items].select { |x| x.is_a?(Hash) } - expect(inlined_replies.all? { |item| targets_public_collection?(item) }).to be true - expect(inlined_replies.all? { |item| ActivityPub::TagManager.instance.local_uri?(item[:id]) }).to be true + expect(inlined_replies) + .to all(satisfy { |item| targets_public_collection?(item) }) + .and all(satisfy { |item| ActivityPub::TagManager.instance.local_uri?(item[:id]) }) end it 'uses ids for remote toots' do - remote_replies = page_json[:items].reject { |x| x.is_a?(Hash) } - expect(remote_replies.all? { |item| item.is_a?(String) && !ActivityPub::TagManager.instance.local_uri?(item) }).to be true + expect(remote_replies) + .to all(satisfy { |item| item.is_a?(String) && !ActivityPub::TagManager.instance.local_uri?(item) }) end context 'when there are few replies' do it 'does not have a next page' do - expect(page_json).to be_a Hash - expect(page_json[:next]).to be_nil + expect(response.parsed_body) + .to include( + first: be_a(Hash).and(not_include(next: be_present)) + ) end end @@ -136,8 +158,14 @@ end it 'points next to other replies' do - expect(page_json).to be_a Hash - expect(parsed_uri_query_values(page_json[:next])).to include('only_other_accounts=true', 'page=true') + expect(response.parsed_body) + .to include( + first: be_a(Hash).and( + include( + next: satisfy { |value| (parsed_uri_query_values(value) & %w(only_other_accounts=true page=true)).any? } + ) + ) + ) end end end @@ -193,6 +221,18 @@ private + def inlined_replies + response + .parsed_body[:first][:items] + .select { |x| x.is_a?(Hash) } + end + + def remote_replies + response + .parsed_body[:first][:items] + .reject { |x| x.is_a?(Hash) } + end + def parsed_uri_query_values(uri) Addressable::URI .parse(uri) diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb index 9bb520211c2cfa..cfc80b86503f3d 100644 --- a/spec/controllers/oauth/authorizations_controller_spec.rb +++ b/spec/controllers/oauth/authorizations_controller_spec.rb @@ -10,13 +10,6 @@ get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read' } end - shared_examples 'stores location for user' do - it 'stores location for user' do - subject - expect(controller.stored_location_for(:user)).to eq "/oauth/authorize?client_id=#{app.uid}&redirect_uri=http%3A%2F%2Flocalhost%2F&response_type=code&scope=read" - end - end - context 'when signed in' do let!(:user) { Fabricate(:user) } @@ -24,18 +17,17 @@ sign_in user, scope: :user end - it 'returns http success' do + it 'returns http success and private cache control headers' do subject - expect(response).to have_http_status(200) - end - it 'returns private cache control headers' do - subject - expect(response.headers['Cache-Control']).to include('private, no-store') + expect(response) + .to have_http_status(200) + expect(response.headers['Cache-Control']) + .to include('private, no-store') + expect(controller.stored_location_for(:user)) + .to eq authorize_path_for(app) end - include_examples 'stores location for user' - context 'when app is already authorized' do before do Doorkeeper::AccessToken.find_or_create_for( @@ -52,10 +44,12 @@ expect(response).to redirect_to(/\A#{app.redirect_uri}/) end - it 'does not redirect to callback with force_login=true' do - get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read', force_login: 'true' } + context 'with `force_login` param true' do + subject do + get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read', force_login: 'true' } + end - expect(response).to have_http_status(:success) + it { is_expected.to have_http_status(:success) } end end end @@ -63,10 +57,16 @@ context 'when not signed in' do it 'redirects' do subject - expect(response).to redirect_to '/auth/sign_in' + + expect(response) + .to redirect_to '/auth/sign_in' + expect(controller.stored_location_for(:user)) + .to eq authorize_path_for(app) end + end - include_examples 'stores location for user' + def authorize_path_for(app) + "/oauth/authorize?client_id=#{app.uid}&redirect_uri=http%3A%2F%2Flocalhost%2F&response_type=code&scope=read" end end end diff --git a/spec/controllers/oauth/authorized_applications_controller_spec.rb b/spec/controllers/oauth/authorized_applications_controller_spec.rb index 52d3dbde83e034..1cf0984abea5bc 100644 --- a/spec/controllers/oauth/authorized_applications_controller_spec.rb +++ b/spec/controllers/oauth/authorized_applications_controller_spec.rb @@ -10,38 +10,31 @@ get :index end - shared_examples 'stores location for user' do - it 'stores location for user' do - subject - expect(controller.stored_location_for(:user)).to eq '/oauth/authorized_applications' - end - end - context 'when signed in' do before do sign_in Fabricate(:user), scope: :user end - it 'returns http success' do + it 'returns http success with private cache control headers' do subject - expect(response).to have_http_status(200) + expect(response) + .to have_http_status(200) + expect(response.headers['Cache-Control']) + .to include('private, no-store') + expect(controller.stored_location_for(:user)) + .to eq '/oauth/authorized_applications' end - - it 'returns private cache control headers' do - subject - expect(response.headers['Cache-Control']).to include('private, no-store') - end - - include_examples 'stores location for user' end context 'when not signed in' do it 'redirects' do subject - expect(response).to redirect_to '/auth/sign_in' - end - include_examples 'stores location for user' + expect(response) + .to redirect_to '/auth/sign_in' + expect(controller.stored_location_for(:user)) + .to eq '/oauth/authorized_applications' + end end end @@ -55,23 +48,19 @@ before do sign_in user, scope: :user allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) - post :destroy, params: { id: application.id } - end - - it 'revokes access tokens for the application' do - expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at).to_not be_nil end - it 'removes subscriptions for the application\'s access tokens' do - expect(Web::PushSubscription.where(user: user).count).to eq 0 - end - - it 'removes the web_push_subscription' do - expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) - end + it 'revokes access tokens for the application and removes subscriptions and sends kill payload to streaming' do + post :destroy, params: { id: application.id } - it 'sends a session kill payload to the streaming server' do - expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') + expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at) + .to_not be_nil + expect(Web::PushSubscription.where(user: user).count) + .to eq(0) + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect(redis_pipeline_stub) + .to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') end end end diff --git a/spec/controllers/oauth/tokens_controller_spec.rb b/spec/controllers/oauth/tokens_controller_spec.rb index dd2d8ca70cbcc4..a2eed797e075f2 100644 --- a/spec/controllers/oauth/tokens_controller_spec.rb +++ b/spec/controllers/oauth/tokens_controller_spec.rb @@ -9,20 +9,15 @@ let!(:access_token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: application) } let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) } - before do + it 'revokes the token and removes subscriptions' do post :revoke, params: { client_id: application.uid, token: access_token.token } - end - - it 'revokes the token' do - expect(access_token.reload.revoked_at).to_not be_nil - end - - it 'removes web push subscription for token' do - expect(Web::PushSubscription.where(access_token: access_token).count).to eq 0 - end - it 'removes the web_push_subscription' do - expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect(access_token.reload.revoked_at) + .to_not be_nil + expect(Web::PushSubscription.where(access_token: access_token).count) + .to eq(0) + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) end end end diff --git a/spec/controllers/settings/applications_controller_spec.rb b/spec/controllers/settings/applications_controller_spec.rb deleted file mode 100644 index 721741bacb2272..00000000000000 --- a/spec/controllers/settings/applications_controller_spec.rb +++ /dev/null @@ -1,178 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Settings::ApplicationsController do - render_views - - let!(:user) { Fabricate(:user) } - let!(:app) { Fabricate(:application, owner: user) } - - before do - sign_in user, scope: :user - end - - describe 'GET #index' do - before do - Fabricate(:application) - get :index - end - - it 'returns http success with private cache control headers', :aggregate_failures do - expect(response).to have_http_status(200) - expect(response.headers['Cache-Control']).to include('private, no-store') - end - end - - describe 'GET #show' do - it 'returns http success' do - get :show, params: { id: app.id } - expect(response).to have_http_status(200) - expect(assigns[:application]).to eql(app) - end - - it 'returns 404 if you dont own app' do - app.update!(owner: nil) - - get :show, params: { id: app.id } - expect(response).to have_http_status 404 - end - end - - describe 'GET #new' do - it 'returns http success' do - get :new - expect(response).to have_http_status(200) - end - end - - describe 'POST #create' do - context 'when success (passed scopes as a String)' do - subject do - post :create, params: { - doorkeeper_application: { - name: 'My New App', - redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', - website: 'http://google.com', - scopes: 'read write follow', - }, - } - end - - it 'creates an entry in the database', :aggregate_failures do - expect { subject }.to change(Doorkeeper::Application, :count) - expect(response).to redirect_to(settings_applications_path) - end - end - - context 'when success (passed scopes as an Array)' do - subject do - post :create, params: { - doorkeeper_application: { - name: 'My New App', - redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', - website: 'http://google.com', - scopes: %w(read write follow), - }, - } - end - - it 'creates an entry in the database', :aggregate_failures do - expect { subject }.to change(Doorkeeper::Application, :count) - expect(response).to redirect_to(settings_applications_path) - end - end - - context 'with failure request' do - before do - post :create, params: { - doorkeeper_application: { - name: '', - redirect_uri: '', - website: '', - scopes: [], - }, - } - end - - it 'returns http success and renders form', :aggregate_failures do - expect(response).to have_http_status(200) - expect(response).to render_template(:new) - end - end - end - - describe 'PATCH #update' do - context 'when success' do - subject do - patch :update, params: { - id: app.id, - doorkeeper_application: opts, - } - response - end - - let(:opts) do - { - website: 'https://foo.bar/', - } - end - - it 'updates existing application' do - subject - - expect(app.reload.website).to eql(opts[:website]) - expect(response).to redirect_to(settings_application_path(app)) - end - end - - context 'with failure request' do - before do - patch :update, params: { - id: app.id, - doorkeeper_application: { - name: '', - redirect_uri: '', - website: '', - scopes: [], - }, - } - end - - it 'returns http success and renders form', :aggregate_failures do - expect(response).to have_http_status(200) - expect(response).to render_template(:show) - end - end - end - - describe 'destroy' do - let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } - let!(:access_token) { Fabricate(:accessible_access_token, application: app) } - - before do - allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) - post :destroy, params: { id: app.id } - end - - it 'redirects back to applications page removes the app' do - expect(response).to redirect_to(settings_applications_path) - expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil - end - - it 'sends a session kill payload to the streaming server' do - expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') - end - end - - describe 'regenerate' do - let(:token) { user.token_for_app(app) } - - it 'creates new token' do - expect(token).to_not be_nil - post :regenerate, params: { id: app.id } - - expect(user.token_for_app(app)).to_not eql(token) - end - end -end diff --git a/spec/controllers/settings/featured_tags_controller_spec.rb b/spec/controllers/settings/featured_tags_controller_spec.rb index a56ae1c498cf00..f414e818f5f8f7 100644 --- a/spec/controllers/settings/featured_tags_controller_spec.rb +++ b/spec/controllers/settings/featured_tags_controller_spec.rb @@ -5,16 +5,10 @@ RSpec.describe Settings::FeaturedTagsController do render_views - shared_examples 'authenticate user' do - it 'redirects to sign_in page' do - expect(subject).to redirect_to new_user_session_path - end - end - context 'when user is not signed in' do subject { post :create } - it_behaves_like 'authenticate user' + it { is_expected.to redirect_to new_user_session_path } end context 'when user is signed in' do diff --git a/spec/controllers/settings/migrations_controller_spec.rb b/spec/controllers/settings/migrations_controller_spec.rb index 93c5de08990e96..dca4c925fd81bf 100644 --- a/spec/controllers/settings/migrations_controller_spec.rb +++ b/spec/controllers/settings/migrations_controller_spec.rb @@ -5,17 +5,11 @@ RSpec.describe Settings::MigrationsController do render_views - shared_examples 'authenticate user' do - it 'redirects to sign_in page' do - expect(subject).to redirect_to new_user_session_path - end - end - describe 'GET #show' do context 'when user is not sign in' do subject { get :show } - it_behaves_like 'authenticate user' + it { is_expected.to redirect_to new_user_session_path } end context 'when user is sign in' do @@ -49,7 +43,7 @@ context 'when user is not sign in' do subject { post :create } - it_behaves_like 'authenticate user' + it { is_expected.to redirect_to new_user_session_path } end context 'when user is signed in' do diff --git a/spec/lib/admin/system_check/software_version_check_spec.rb b/spec/lib/admin/system_check/software_version_check_spec.rb index 1affaa3a969d82..8460d9066881bf 100644 --- a/spec/lib/admin/system_check/software_version_check_spec.rb +++ b/spec/lib/admin/system_check/software_version_check_spec.rb @@ -51,8 +51,8 @@ Fabricate(:software_update, version: '99.99.99', type: 'major', urgent: false) end - it 'returns true' do - expect(check.pass?).to be true + it 'returns false' do + expect(check.pass?).to be false end end diff --git a/spec/lib/permalink_redirector_spec.rb b/spec/lib/permalink_redirector_spec.rb index 3f77d7665a23d2..5a544c3d38e136 100644 --- a/spec/lib/permalink_redirector_spec.rb +++ b/spec/lib/permalink_redirector_spec.rb @@ -29,5 +29,20 @@ redirector = described_class.new('@alice/123') expect(redirector.redirect_path).to eq 'https://example.com/status-123' end + + it 'returns path for legacy status links with a query param' do + redirector = described_class.new('statuses/123?foo=bar') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + + it 'returns path for pretty status links with a query param' do + redirector = described_class.new('@alice/123?foo=bar') + expect(redirector.redirect_path).to eq 'https://example.com/status-123' + end + + it 'returns path for deck URLs with query params' do + redirector = described_class.new('/deck/directory?local=true') + expect(redirector.redirect_path).to eq '/directory?local=true' + end end end diff --git a/spec/lib/scope_transformer_spec.rb b/spec/lib/scope_transformer_spec.rb index 09a31e04c57f32..f4003352e40ec9 100644 --- a/spec/lib/scope_transformer_spec.rb +++ b/spec/lib/scope_transformer_spec.rb @@ -7,16 +7,13 @@ subject { described_class.new.apply(ScopeParser.new.parse(input)) } shared_examples 'a scope' do |namespace, term, access| - it 'parses the term' do - expect(subject.term).to eq term - end - - it 'parses the namespace' do - expect(subject.namespace).to eq namespace - end - - it 'parses the access' do - expect(subject.access).to eq access + it 'parses the attributes' do + expect(subject) + .to have_attributes( + term: term, + namespace: namespace, + access: access + ) end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index eab196166d3219..4c6107d9f76fce 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -3,43 +3,28 @@ require 'rails_helper' RSpec.describe NotificationMailer do + shared_examples 'delivery to non functional user' do + context 'when user is not functional' do + before { receiver.update(confirmed_at: nil) } + + it 'does not deliver mail' do + emails = capture_emails { mail.deliver_now } + expect(emails).to be_empty + end + end + end + let(:receiver) { Fabricate(:user, account_attributes: { username: 'alice' }) } let(:sender) { Fabricate(:account, username: 'bob') } let(:foreign_status) { Fabricate(:status, account: sender, text: 'The body of the foreign status') } let(:own_status) { Fabricate(:status, account: receiver.account, text: 'The body of the own status') } - shared_examples 'standard headers' do |type| - it 'renders the email' do - expect(mail) - .to be_present - .and(have_header('To', "#{receiver.account.username} <#{receiver.email}>")) - .and(have_header('List-ID', "<#{type}.alice.cb6e6126.ngrok.io>")) - .and(have_header('List-Unsubscribe', %r{})) - .and(have_header('List-Unsubscribe', /&type=#{type}/)) - .and(have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click')) - .and(deliver_to("#{receiver.account.username} <#{receiver.email}>")) - .and(deliver_from('notifications@localhost')) - end - end - - shared_examples 'thread headers' do - it 'renders the email with conversation thread headers' do - conversation_header_regex = // - expect(mail) - .to be_present - .and(have_header('In-Reply-To', conversation_header_regex)) - .and(have_header('References', conversation_header_regex)) - end - end - describe 'mention' do let(:mention) { Mention.create!(account: receiver.account, status: foreign_status) } let(:notification) { Notification.create!(account: receiver.account, activity: mention) } let(:mail) { prepared_mailer_for(receiver.account).mention } include_examples 'localized subject', 'notification_mailer.mention.subject', name: 'bob' - include_examples 'standard headers', 'mention' - include_examples 'thread headers' it 'renders the email' do expect(mail) @@ -47,7 +32,11 @@ .and(have_subject('You were mentioned by bob')) .and(have_body_text('You were mentioned by bob')) .and(have_body_text('The body of the foreign status')) + .and have_thread_headers + .and have_standard_headers('mention').for(receiver) end + + include_examples 'delivery to non functional user' end describe 'follow' do @@ -56,14 +45,16 @@ let(:mail) { prepared_mailer_for(receiver.account).follow } include_examples 'localized subject', 'notification_mailer.follow.subject', name: 'bob' - include_examples 'standard headers', 'follow' it 'renders the email' do expect(mail) .to be_present .and(have_subject('bob is now following you')) .and(have_body_text('bob is now following you')) + .and have_standard_headers('follow').for(receiver) end + + include_examples 'delivery to non functional user' end describe 'favourite' do @@ -72,8 +63,6 @@ let(:mail) { prepared_mailer_for(own_status.account).favourite } include_examples 'localized subject', 'notification_mailer.favourite.subject', name: 'bob' - include_examples 'standard headers', 'favourite' - include_examples 'thread headers' it 'renders the email' do expect(mail) @@ -81,7 +70,11 @@ .and(have_subject('bob favorited your post')) .and(have_body_text('Your post was favorited by bob')) .and(have_body_text('The body of the own status')) + .and have_thread_headers + .and have_standard_headers('favourite').for(receiver) end + + include_examples 'delivery to non functional user' end describe 'reblog' do @@ -90,8 +83,6 @@ let(:mail) { prepared_mailer_for(own_status.account).reblog } include_examples 'localized subject', 'notification_mailer.reblog.subject', name: 'bob' - include_examples 'standard headers', 'reblog' - include_examples 'thread headers' it 'renders the email' do expect(mail) @@ -99,7 +90,11 @@ .and(have_subject('bob boosted your post')) .and(have_body_text('Your post was boosted by bob')) .and(have_body_text('The body of the own status')) + .and have_thread_headers + .and have_standard_headers('reblog').for(receiver) end + + include_examples 'delivery to non functional user' end describe 'follow_request' do @@ -108,14 +103,16 @@ let(:mail) { prepared_mailer_for(receiver.account).follow_request } include_examples 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob' - include_examples 'standard headers', 'follow_request' it 'renders the email' do expect(mail) .to be_present .and(have_subject('Pending follower: bob')) .and(have_body_text('bob has requested to follow you')) + .and have_standard_headers('follow_request').for(receiver) end + + include_examples 'delivery to non functional user' end private diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index d498ee02a556ec..67c85b40f37e2f 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -252,88 +252,83 @@ ] end - context 'with a preloaded target status' do - it 'preloads mention' do - expect(subject[0].type).to eq :mention - expect(subject[0].association(:mention)).to be_loaded - expect(subject[0].mention.association(:status)).to be_loaded + context 'with a preloaded target status and a cached status' do + it 'preloads association records and replaces association records' do + expect(subject) + .to contain_exactly( + mention_attributes, + status_attributes, + reblog_attributes, + follow_attributes, + follow_request_attributes, + favourite_attributes, + poll_attributes + ) end - it 'preloads status' do - expect(subject[1].type).to eq :status - expect(subject[1].association(:status)).to be_loaded + def mention_attributes + have_attributes( + type: :mention, + target_status: eq(mention.status).and(have_loaded_association(:account)), + mention: have_loaded_association(:status) + ).and(have_loaded_association(:mention)) end - it 'preloads reblog' do - expect(subject[2].type).to eq :reblog - expect(subject[2].association(:status)).to be_loaded - expect(subject[2].status.association(:reblog)).to be_loaded + def status_attributes + have_attributes( + type: :status, + target_status: eq(status).and(have_loaded_association(:account)) + ).and(have_loaded_association(:status)) end - it 'preloads follow as nil' do - expect(subject[3].type).to eq :follow - expect(subject[3].target_status).to be_nil + def reblog_attributes + have_attributes( + type: :reblog, + status: have_loaded_association(:reblog), + target_status: eq(reblog.reblog).and(have_loaded_association(:account)) + ).and(have_loaded_association(:status)) end - it 'preloads follow_request as nill' do - expect(subject[4].type).to eq :follow_request - expect(subject[4].target_status).to be_nil + def follow_attributes + have_attributes( + type: :follow, + target_status: be_nil + ) end - it 'preloads favourite' do - expect(subject[5].type).to eq :favourite - expect(subject[5].association(:favourite)).to be_loaded - expect(subject[5].favourite.association(:status)).to be_loaded + def follow_request_attributes + have_attributes( + type: :follow_request, + target_status: be_nil + ) end - it 'preloads poll' do - expect(subject[6].type).to eq :poll - expect(subject[6].association(:poll)).to be_loaded - expect(subject[6].poll.association(:status)).to be_loaded - end - end - - context 'with a cached status' do - it 'replaces mention' do - expect(subject[0].type).to eq :mention - expect(subject[0].target_status.association(:account)).to be_loaded - expect(subject[0].target_status).to eq mention.status - end - - it 'replaces status' do - expect(subject[1].type).to eq :status - expect(subject[1].target_status.association(:account)).to be_loaded - expect(subject[1].target_status).to eq status - end - - it 'replaces reblog' do - expect(subject[2].type).to eq :reblog - expect(subject[2].target_status.association(:account)).to be_loaded - expect(subject[2].target_status).to eq reblog.reblog - end - - it 'replaces follow' do - expect(subject[3].type).to eq :follow - expect(subject[3].target_status).to be_nil + def favourite_attributes + have_attributes( + type: :favourite, + favourite: have_loaded_association(:status), + target_status: eq(favourite.status).and(have_loaded_association(:account)) + ).and(have_loaded_association(:favourite)) end - it 'replaces follow_request' do - expect(subject[4].type).to eq :follow_request - expect(subject[4].target_status).to be_nil - end - - it 'replaces favourite' do - expect(subject[5].type).to eq :favourite - expect(subject[5].target_status.association(:account)).to be_loaded - expect(subject[5].target_status).to eq favourite.status - end - - it 'replaces poll' do - expect(subject[6].type).to eq :poll - expect(subject[6].target_status.association(:account)).to be_loaded - expect(subject[6].target_status).to eq poll.status + def poll_attributes + have_attributes( + type: :poll, + poll: have_loaded_association(:status), + target_status: eq(poll.status).and(have_loaded_association(:account)) + ).and(have_loaded_association(:poll)) end end end end end + +RSpec::Matchers.define :have_loaded_association do |association| + match do |record| + record.association(association).loaded? + end + + failure_message do |record| + "expected #{record} to have loaded association #{association} but it did not." + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 972453cd690835..d28e6658f1f6c2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -434,7 +434,9 @@ def within_duration_window_days end describe '#reset_password!' do - subject(:user) { Fabricate(:user, password: 'foobar12345') } + subject(:user) { Fabricate(:user, password: original_password) } + + let(:original_password) { 'foobar12345' } let!(:session_activation) { Fabricate(:session_activation, user: user) } let!(:access_token) { Fabricate(:access_token, resource_owner_id: user.id) } @@ -442,31 +444,40 @@ def within_duration_window_days let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } - before do - allow(redis).to receive(:pipelined).and_yield(redis_pipeline_stub) - user.reset_password! - end + before { stub_redis } + + it 'changes the password immediately and revokes related access' do + expect { user.reset_password! } + .to remove_activated_sessions + .and remove_active_user_tokens + .and remove_user_web_subscriptions - it 'changes the password immediately' do - expect(user.external_or_valid_password?('foobar12345')).to be false + expect(user) + .to_not be_external_or_valid_password(original_password) + expect { session_activation.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect { web_push_subscription.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect(redis_pipeline_stub) + .to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once end - it 'deactivates all sessions' do - expect(user.session_activations.count).to eq 0 - expect { session_activation.reload }.to raise_error(ActiveRecord::RecordNotFound) + def remove_activated_sessions + change(user.session_activations, :count).to(0) end - it 'revokes all access tokens' do - expect(Doorkeeper::AccessToken.active_for(user).count).to eq 0 + def remove_active_user_tokens + change { Doorkeeper::AccessToken.active_for(user).count }.to(0) end - it 'revokes streaming access for all access tokens' do - expect(redis_pipeline_stub).to have_received(:publish).with("timeline:access_token:#{access_token.id}", Oj.dump(event: :kill)).once + def remove_user_web_subscriptions + change { Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count }.to(0) end - it 'removes push subscriptions' do - expect(Web::PushSubscription.where(user: user).or(Web::PushSubscription.where(access_token: access_token)).count).to eq 0 - expect { web_push_subscription.reload }.to raise_error(ActiveRecord::RecordNotFound) + def stub_redis + allow(redis) + .to receive(:pipelined) + .and_yield(redis_pipeline_stub) end end diff --git a/spec/requests/accounts_spec.rb b/spec/requests/accounts_spec.rb index e657ae60602bda..afd9ac80e20863 100644 --- a/spec/requests/accounts_spec.rb +++ b/spec/requests/accounts_spec.rb @@ -46,21 +46,6 @@ describe 'GET to short username paths' do context 'with existing statuses' do - let!(:status) { Fabricate(:status, account: account) } - let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) } - let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) } - let!(:status_media) { Fabricate(:status, account: account) } - let!(:status_pinned) { Fabricate(:status, account: account) } - let!(:status_private) { Fabricate(:status, account: account, visibility: :private) } - let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) } - let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) } - - before do - status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image) - account.pinned_statuses << status_pinned - account.pinned_statuses << status_private - end - context 'with HTML' do let(:format) { 'html' } @@ -207,6 +192,21 @@ context 'with RSS' do let(:format) { 'rss' } + let!(:status) { Fabricate(:status, account: account) } + let!(:status_reply) { Fabricate(:status, account: account, thread: Fabricate(:status)) } + let!(:status_self_reply) { Fabricate(:status, account: account, thread: status) } + let!(:status_media) { Fabricate(:status, account: account) } + let!(:status_pinned) { Fabricate(:status, account: account) } + let!(:status_private) { Fabricate(:status, account: account, visibility: :private) } + let!(:status_direct) { Fabricate(:status, account: account, visibility: :direct) } + let!(:status_reblog) { Fabricate(:status, account: account, reblog: Fabricate(:status)) } + + before do + status_media.media_attachments << Fabricate(:media_attachment, account: account, type: :image) + account.pinned_statuses << status_pinned + account.pinned_statuses << status_private + end + context 'with a normal account in an RSS request' do before do get short_account_path(username: account.username, format: format) diff --git a/spec/requests/api/v1/accounts/follower_accounts_spec.rb b/spec/requests/api/v1/accounts/follower_accounts_spec.rb index 7db9884a57a8f7..61987fac1cc667 100644 --- a/spec/requests/api/v1/accounts/follower_accounts_spec.rb +++ b/spec/requests/api/v1/accounts/follower_accounts_spec.rb @@ -23,8 +23,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq 2 - expect([response.parsed_body[0][:id], response.parsed_body[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s), + hash_including(id: bob.id.to_s) + ) end it 'does not return blocked users', :aggregate_failures do @@ -34,8 +37,10 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq 1 - expect(response.parsed_body[0][:id]).to eq alice.id.to_s + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s) + ) end context 'when requesting user is blocked' do @@ -56,8 +61,11 @@ account.mute!(bob) get "/api/v1/accounts/#{account.id}/followers", params: { limit: 2 }, headers: headers - expect(response.parsed_body.size).to eq 2 - expect([response.parsed_body[0][:id], response.parsed_body[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s), + hash_including(id: bob.id.to_s) + ) end end end diff --git a/spec/requests/api/v1/accounts/following_accounts_spec.rb b/spec/requests/api/v1/accounts/following_accounts_spec.rb index ffb7332c4eb7b9..aae811467d2243 100644 --- a/spec/requests/api/v1/accounts/following_accounts_spec.rb +++ b/spec/requests/api/v1/accounts/following_accounts_spec.rb @@ -23,8 +23,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq 2 - expect([response.parsed_body[0][:id], response.parsed_body[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s), + hash_including(id: bob.id.to_s) + ) end it 'does not return blocked users', :aggregate_failures do @@ -34,8 +37,10 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq 1 - expect(response.parsed_body[0][:id]).to eq alice.id.to_s + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s) + ) end context 'when requesting user is blocked' do @@ -56,8 +61,11 @@ account.mute!(bob) get "/api/v1/accounts/#{account.id}/following", params: { limit: 2 }, headers: headers - expect(response.parsed_body.size).to eq 2 - expect([response.parsed_body[0][:id], response.parsed_body[1][:id]]).to contain_exactly(alice.id.to_s, bob.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s), + hash_including(id: bob.id.to_s) + ) end end end diff --git a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb index eaa011d5167716..25af0a26afef4d 100644 --- a/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb +++ b/spec/requests/api/v1/admin/canonical_email_blocks_spec.rb @@ -20,19 +20,16 @@ it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there is no canonical email block' do it 'returns an empty list' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -43,7 +40,12 @@ it 'returns the correct canonical email hashes' do subject - expect(response.parsed_body.pluck(:canonical_email_hash)).to match_array(expected_email_hashes) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body.pluck(:canonical_email_hash)) + .to match_array(expected_email_hashes) end context 'with limit param' do diff --git a/spec/requests/api/v1/admin/domain_allows_spec.rb b/spec/requests/api/v1/admin/domain_allows_spec.rb index eb5128e420834d..fba1eb15d373fb 100644 --- a/spec/requests/api/v1/admin/domain_allows_spec.rb +++ b/spec/requests/api/v1/admin/domain_allows_spec.rb @@ -20,18 +20,14 @@ it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there is no allowed domains' do it 'returns an empty body' do subject + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') expect(response.parsed_body).to be_empty end end @@ -51,7 +47,12 @@ it 'returns the correct allowed domains' do subject - expect(response.parsed_body).to match_array(expected_response) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to match_array(expected_response) end context 'with limit param' do diff --git a/spec/requests/api/v1/admin/domain_blocks_spec.rb b/spec/requests/api/v1/admin/domain_blocks_spec.rb index 1a506bd9bebca7..029de72fd7fd5a 100644 --- a/spec/requests/api/v1/admin/domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/domain_blocks_spec.rb @@ -20,19 +20,16 @@ it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there are no domain blocks' do it 'returns an empty list' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -66,7 +63,12 @@ it 'returns the expected domain blocks' do subject - expect(response.parsed_body).to match_array(expected_responde) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to match_array(expected_responde) end context 'with limit param' do diff --git a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb index 3f51a3ea2d4fb6..2788a45a4a2991 100644 --- a/spec/requests/api/v1/admin/email_domain_blocks_spec.rb +++ b/spec/requests/api/v1/admin/email_domain_blocks_spec.rb @@ -21,19 +21,16 @@ it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there is no email domain block' do it 'returns an empty list' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -44,7 +41,12 @@ it 'return the correct blocked email domains' do subject - expect(response.parsed_body.pluck(:domain)).to match_array(blocked_email_domains) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body.pluck(:domain)) + .to match_array(blocked_email_domains) end context 'with limit param' do diff --git a/spec/requests/api/v1/admin/ip_blocks_spec.rb b/spec/requests/api/v1/admin/ip_blocks_spec.rb index c096aa33283cae..aa3db339154fa0 100644 --- a/spec/requests/api/v1/admin/ip_blocks_spec.rb +++ b/spec/requests/api/v1/admin/ip_blocks_spec.rb @@ -20,19 +20,16 @@ it_behaves_like 'forbidden for wrong role', '' it_behaves_like 'forbidden for wrong role', 'Moderator' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there is no ip block' do it 'returns an empty body' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -60,7 +57,12 @@ it 'returns the correct blocked ips' do subject - expect(response.parsed_body).to match_array(expected_response) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to match_array(expected_response) end context 'with limit param' do diff --git a/spec/requests/api/v1/admin/reports_spec.rb b/spec/requests/api/v1/admin/reports_spec.rb index a0e7b0a369a3e1..987f0eda7fb816 100644 --- a/spec/requests/api/v1/admin/reports_spec.rb +++ b/spec/requests/api/v1/admin/reports_spec.rb @@ -19,19 +19,16 @@ it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there are no reports' do it 'returns an empty list' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -66,7 +63,12 @@ it 'returns all unresolved reports' do subject - expect(response.parsed_body).to match_array(expected_response) + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to match_array(expected_response) end context 'with resolved param' do diff --git a/spec/requests/api/v1/admin/tags_spec.rb b/spec/requests/api/v1/admin/tags_spec.rb index 3623c09ac7ad58..3a57432af78c48 100644 --- a/spec/requests/api/v1/admin/tags_spec.rb +++ b/spec/requests/api/v1/admin/tags_spec.rb @@ -20,19 +20,16 @@ it_behaves_like 'forbidden for wrong scope', 'write:statuses' it_behaves_like 'forbidden for wrong role', '' - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - expect(response.content_type) - .to start_with('application/json') - end - context 'when there are no tags' do it 'returns an empty list' do subject - expect(response.parsed_body).to be_empty + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to be_empty end end @@ -48,6 +45,11 @@ it 'returns the expected tags' do subject + + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') tags.each do |tag| expect(response.parsed_body.find { |item| item[:id] == tag.id.to_s && item[:name] == tag.name }).to_not be_nil end @@ -82,8 +84,11 @@ expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body[:id].to_i).to eq(tag.id) - expect(response.parsed_body[:name]).to eq(tag.name) + expect(response.parsed_body) + .to include( + id: tag.id.to_s, + name: tag.name + ) end context 'when the requested tag does not exist' do @@ -116,8 +121,11 @@ expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body[:id].to_i).to eq(tag.id) - expect(response.parsed_body[:name]).to eq(tag.name.upcase) + expect(response.parsed_body) + .to include( + id: tag.id.to_s, + name: tag.name.upcase + ) end context 'when the updated display name is invalid' do diff --git a/spec/requests/api/v1/apps/credentials_spec.rb b/spec/requests/api/v1/apps/credentials_spec.rb index 30200ed60c3471..8e5fa14b7e82a5 100644 --- a/spec/requests/api/v1/apps/credentials_spec.rb +++ b/spec/requests/api/v1/apps/credentials_spec.rb @@ -41,8 +41,9 @@ expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body[:client_id]).to_not be_present - expect(response.parsed_body[:client_secret]).to_not be_present + expect(response.parsed_body) + .to not_include(client_id: be_present) + .and not_include(client_secret: be_present) end end diff --git a/spec/requests/api/v1/directories_spec.rb b/spec/requests/api/v1/directories_spec.rb index 282be9a582551e..07e65f49b75b54 100644 --- a/spec/requests/api/v1/directories_spec.rb +++ b/spec/requests/api/v1/directories_spec.rb @@ -84,8 +84,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq(2) - expect(response.parsed_body.pluck(:id)).to contain_exactly(eligible_remote_account.id.to_s, local_discoverable_account.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: eligible_remote_account.id.to_s), + hash_including(id: local_discoverable_account.id.to_s) + ) end end @@ -105,9 +108,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq(1) - expect(response.parsed_body.first[:id]).to include(local_account.id.to_s) - expect(response.body).to_not include(remote_account.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: local_account.id.to_s) + ) + .and not_include(remote_account.id.to_s) end end @@ -121,9 +126,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq(2) - expect(response.parsed_body.first[:id]).to include(new_stat.account_id.to_s) - expect(response.parsed_body.second[:id]).to include(old_stat.account_id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: new_stat.account_id.to_s), + hash_including(id: old_stat.account_id.to_s) + ) end end @@ -138,9 +145,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size).to eq(2) - expect(response.parsed_body.first[:id]).to include(account_new.id.to_s) - expect(response.parsed_body.second[:id]).to include(account_old.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: account_new.id.to_s), + hash_including(id: account_old.id.to_s) + ) end end end diff --git a/spec/requests/api/v1/peers/search_spec.rb b/spec/requests/api/v1/peers/search_spec.rb index d00a2437f279d6..afcc14190296b4 100644 --- a/spec/requests/api/v1/peers/search_spec.rb +++ b/spec/requests/api/v1/peers/search_spec.rb @@ -55,10 +55,10 @@ .to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size) - .to eq(1) - expect(response.parsed_body.first) - .to eq(account.domain) + expect(response.parsed_body) + .to contain_exactly( + eq(account.domain) + ) end end end diff --git a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb index 6471697154c7df..441664d0994e21 100644 --- a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb @@ -36,8 +36,6 @@ expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size) - .to eq(2) expect(response.parsed_body) .to contain_exactly( include(id: alice.id.to_s), @@ -50,9 +48,10 @@ subject - expect(response.parsed_body.size) - .to eq 1 - expect(response.parsed_body.first[:id]).to eq(alice.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s) + ) end end end diff --git a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb index 40457f6e894a57..824b5aa2755e99 100644 --- a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb @@ -35,8 +35,6 @@ expect(response.content_type) .to start_with('application/json') - expect(response.parsed_body.size) - .to eq(2) expect(response.parsed_body) .to contain_exactly( include(id: alice.id.to_s), @@ -49,9 +47,10 @@ subject - expect(response.parsed_body.size) - .to eq 1 - expect(response.parsed_body.first[:id]).to eq(alice.id.to_s) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: alice.id.to_s) + ) end end end diff --git a/spec/requests/api/v2/admin/accounts_spec.rb b/spec/requests/api/v2/admin/accounts_spec.rb index bc3db4f8860fcf..1d1fda3e67df1c 100644 --- a/spec/requests/api/v2/admin/accounts_spec.rb +++ b/spec/requests/api/v2/admin/accounts_spec.rb @@ -36,7 +36,10 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(body_json_ids).to eq([admin_account.id]) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: admin_account.id.to_s) + ) end end @@ -47,8 +50,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(body_json_ids).to include(remote_account.id) - expect(body_json_ids).to_not include(other_remote_account.id) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: remote_account.id.to_s) + ) + .and not_include(hash_including(id: other_remote_account.id.to_s)) end end @@ -59,7 +65,11 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(body_json_ids).to include(suspended_remote.id, suspended_account.id) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: suspended_remote.id.to_s), + hash_including(id: suspended_account.id.to_s) + ) end end @@ -70,7 +80,10 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(body_json_ids).to include(disabled_account.id) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: disabled_account.id.to_s) + ) end end @@ -81,14 +94,13 @@ expect(response).to have_http_status(200) expect(response.content_type) .to start_with('application/json') - expect(body_json_ids).to include(pending_account.id) + expect(response.parsed_body) + .to contain_exactly( + hash_including(id: pending_account.id.to_s) + ) end end - def body_json_ids - response.parsed_body.map { |a| a[:id].to_i } - end - context 'with limit param' do let(:params) { { limit: 1 } } diff --git a/spec/requests/api/v2_alpha/notifications_spec.rb b/spec/requests/api/v2_alpha/notifications_spec.rb deleted file mode 100644 index 6d7df45b6563ff..00000000000000 --- a/spec/requests/api/v2_alpha/notifications_spec.rb +++ /dev/null @@ -1,345 +0,0 @@ -# frozen_string_literal: true - -# TODO: remove this before 4.3.0-rc1 - -require 'rails_helper' - -RSpec.describe 'Notifications' do - let(:user) { Fabricate(:user, account_attributes: { username: 'alice' }) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } - let(:scopes) { 'read:notifications write:notifications' } - let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - - describe 'GET /api/v2_alpha/notifications/unread_count', :inline_jobs do - subject do - get '/api/v2_alpha/notifications/unread_count', headers: headers, params: params - end - - let(:params) { {} } - - before do - first_status = PostStatusService.new.call(user.account, text: 'Test') - ReblogService.new.call(Fabricate(:account), first_status) - PostStatusService.new.call(Fabricate(:account), text: 'Hello @alice') - FavouriteService.new.call(Fabricate(:account), first_status) - FavouriteService.new.call(Fabricate(:account), first_status) - FollowService.new.call(Fabricate(:account), user.account) - end - - it_behaves_like 'forbidden for wrong scope', 'write write:notifications' - - context 'with no options' do - it 'returns expected notifications count' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq 4 - end - end - - context 'with grouped_types parameter' do - let(:params) { { grouped_types: %w(reblog) } } - - it 'returns expected notifications count' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq 5 - end - end - - context 'with a read marker' do - before do - id = user.account.notifications.browserable.order(id: :desc).offset(2).first.id - user.markers.create!(timeline: 'notifications', last_read_id: id) - end - - it 'returns expected notifications count' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq 2 - end - end - - context 'with exclude_types param' do - let(:params) { { exclude_types: %w(mention) } } - - it 'returns expected notifications count' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq 3 - end - end - - context 'with a user-provided limit' do - let(:params) { { limit: 2 } } - - it 'returns a capped value' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq 2 - end - end - - context 'when there are more notifications than the limit' do - before do - stub_const('Api::V2::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT', 2) - end - - it 'returns a capped value' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:count]).to eq Api::V2::NotificationsController::DEFAULT_NOTIFICATIONS_COUNT_LIMIT - end - end - end - - describe 'GET /api/v2_alpha/notifications', :inline_jobs do - subject do - get '/api/v2_alpha/notifications', headers: headers, params: params - end - - let(:bob) { Fabricate(:user) } - let(:tom) { Fabricate(:user) } - let(:params) { {} } - - before do - first_status = PostStatusService.new.call(user.account, text: 'Test') - ReblogService.new.call(bob.account, first_status) - PostStatusService.new.call(bob.account, text: 'Hello @alice') - FavouriteService.new.call(bob.account, first_status) - FavouriteService.new.call(tom.account, first_status) - FollowService.new.call(bob.account, user.account) - end - - it_behaves_like 'forbidden for wrong scope', 'write write:notifications' - - context 'when there are no notifications' do - before do - user.account.notifications.destroy_all - end - - it 'returns 0 notifications' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:notification_groups]).to eq [] - end - end - - context 'with no options' do - it 'returns expected notification types', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow') - end - end - - context 'with grouped_types param' do - let(:params) { { grouped_types: %w(reblog) } } - - it 'returns everything, but does not group favourites' do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:notification_groups]).to contain_exactly( - a_hash_including( - type: 'reblog', - sample_account_ids: [bob.account_id.to_s] - ), - a_hash_including( - type: 'mention', - sample_account_ids: [bob.account_id.to_s] - ), - a_hash_including( - type: 'favourite', - sample_account_ids: [bob.account_id.to_s] - ), - a_hash_including( - type: 'favourite', - sample_account_ids: [tom.account_id.to_s] - ), - a_hash_including( - type: 'follow', - sample_account_ids: [bob.account_id.to_s] - ) - ) - end - end - - context 'with exclude_types param' do - let(:params) { { exclude_types: %w(mention) } } - - it 'returns everything but excluded type', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body.size).to_not eq 0 - expect(body_json_types.uniq).to_not include 'mention' - end - end - - context 'with types param' do - let(:params) { { types: %w(mention) } } - - it 'returns only requested type', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(body_json_types.uniq).to eq ['mention'] - expect(response.parsed_body.dig(:notification_groups, 0, :page_min_id)).to_not be_nil - end - end - - context 'with limit param' do - let(:params) { { limit: 3 } } - let(:notifications) { user.account.notifications.reorder(id: :desc) } - - it 'returns the requested number of notifications paginated', :aggregate_failures do - subject - - expect(response.parsed_body[:notification_groups].size) - .to eq(params[:limit]) - - expect(response) - .to include_pagination_headers( - prev: api_v2_notifications_url(limit: params[:limit], min_id: notifications.first.id), - # TODO: one downside of the current approach is that we return the first ID matching the group, - # not the last that has been skipped, so pagination is very likely to give overlap - next: api_v2_notifications_url(limit: params[:limit], max_id: notifications[3].id) - ) - end - end - - context 'with since_id param' do - let(:params) { { since_id: notifications[2].id } } - let(:notifications) { user.account.notifications.reorder(id: :desc) } - - it 'returns the requested number of notifications paginated', :aggregate_failures do - subject - - expect(response.parsed_body[:notification_groups].size) - .to eq(2) - - expect(response) - .to include_pagination_headers( - prev: api_v2_notifications_url(limit: params[:limit], min_id: notifications.first.id), - # TODO: one downside of the current approach is that we return the first ID matching the group, - # not the last that has been skipped, so pagination is very likely to give overlap - next: api_v2_notifications_url(limit: params[:limit], max_id: notifications[1].id) - ) - end - end - - context 'when requesting stripped-down accounts' do - let(:params) { { expand_accounts: 'partial_avatars' } } - - let(:recent_account) { Fabricate(:account) } - - before do - FavouriteService.new.call(recent_account, user.account.statuses.first) - end - - it 'returns an account in "partial_accounts", with the expected keys', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - expect(response.parsed_body[:partial_accounts].size).to be > 0 - expect(response.parsed_body[:partial_accounts][0].keys.map(&:to_sym)).to contain_exactly(:acct, :avatar, :avatar_static, :bot, :id, :locked, :url) - expect(response.parsed_body[:partial_accounts].pluck(:id)).to_not include(recent_account.id.to_s) - expect(response.parsed_body[:accounts].pluck(:id)).to include(recent_account.id.to_s) - end - end - - context 'when passing an invalid value for "expand_accounts"' do - let(:params) { { expand_accounts: 'unknown_foobar' } } - - it 'returns http bad request' do - subject - - expect(response).to have_http_status(400) - end - end - - def body_json_types - response.parsed_body[:notification_groups].pluck(:type) - end - end - - describe 'GET /api/v2_alpha/notifications/:id' do - subject do - get "/api/v2_alpha/notifications/#{notification.group_key}", headers: headers - end - - let(:notification) { Fabricate(:notification, account: user.account, group_key: 'foobar') } - - it_behaves_like 'forbidden for wrong scope', 'write write:notifications' - - it 'returns http success' do - subject - - expect(response).to have_http_status(200) - end - - context 'when notification belongs to someone else' do - let(:notification) { Fabricate(:notification, group_key: 'foobar') } - - it 'returns http not found' do - subject - - expect(response).to have_http_status(404) - end - end - end - - describe 'POST /api/v2_alpha/notifications/:id/dismiss' do - subject do - post "/api/v2_alpha/notifications/#{notification.group_key}/dismiss", headers: headers - end - - let!(:notification) { Fabricate(:notification, account: user.account, group_key: 'foobar') } - - it_behaves_like 'forbidden for wrong scope', 'read read:notifications' - - it 'destroys the notification' do - subject - - expect(response).to have_http_status(200) - expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - - context 'when notification belongs to someone else' do - let(:notification) { Fabricate(:notification) } - - it 'returns http not found' do - subject - - expect(response).to have_http_status(404) - end - end - end - - describe 'POST /api/v2_alpha/notifications/clear' do - subject do - post '/api/v2_alpha/notifications/clear', headers: headers - end - - before do - Fabricate(:notification, account: user.account) - end - - it_behaves_like 'forbidden for wrong scope', 'read read:notifications' - - it 'clears notifications for the account' do - subject - - expect(user.account.reload.notifications).to be_empty - expect(response).to have_http_status(200) - end - end -end diff --git a/spec/requests/settings/applications_spec.rb b/spec/requests/settings/applications_spec.rb new file mode 100644 index 00000000000000..8a5b3de895b47f --- /dev/null +++ b/spec/requests/settings/applications_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Settings / Exports' do + let(:user) { Fabricate :user } + + before { sign_in user } + + describe 'GET /settings/application/:id' do + context 'when user does not own application' do + let(:application) { Fabricate :application } + + it 'returns http missing' do + get settings_application_path(application) + + expect(response) + .to have_http_status(404) + end + end + end + + describe 'POST /settings/applications' do + subject { post '/settings/applications', params: params } + + let(:params) do + { + doorkeeper_application: { + name: 'My New App', + redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', + website: 'http://google.com', + scopes: 'read write follow', + }, + } + end + + it 'supports passing scope values as string' do + expect { subject } + .to change(Doorkeeper::Application, :count).by(1) + expect(response) + .to redirect_to(settings_applications_path) + end + end +end diff --git a/spec/requests/tags_spec.rb b/spec/requests/tags_spec.rb index 7974a6b15267b9..fbd1f7d56ee4ae 100644 --- a/spec/requests/tags_spec.rb +++ b/spec/requests/tags_spec.rb @@ -7,18 +7,6 @@ context 'when tag exists' do let(:tag) { Fabricate :tag } - context 'with HTML format' do - # TODO: Update the have_cacheable_headers matcher to operate on capybara sessions - # Remove this example, rely on system spec (which should use matcher) - before { get tag_path(tag) } - - it 'returns http success' do - expect(response) - .to have_http_status(200) - .and have_cacheable_headers.with_vary('Accept, Accept-Language, Cookie') - end - end - context 'with JSON format' do before { get tag_path(tag, format: :json) } diff --git a/spec/requests/well_known/webfinger_spec.rb b/spec/requests/well_known/webfinger_spec.rb index 6880ba4b5895e5..aeff56aebfa955 100644 --- a/spec/requests/well_known/webfinger_spec.rb +++ b/spec/requests/well_known/webfinger_spec.rb @@ -168,10 +168,12 @@ it 'returns avatar in response' do perform_request! - avatar_link = get_avatar_link(response.parsed_body) - expect(avatar_link).to_not be_nil - expect(avatar_link[:type]).to eq alice.avatar.content_type - expect(avatar_link[:href]).to eq Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s + expect(response_avatar_link) + .to be_present + .and include( + type: eq(alice.avatar.content_type), + href: eq(Addressable::URI.new(host: Rails.configuration.x.local_domain, path: alice.avatar.to_s, scheme: 'https').to_s) + ) end context 'with limited federation mode' do @@ -182,8 +184,8 @@ it 'does not return avatar in response' do perform_request! - avatar_link = get_avatar_link(response.parsed_body) - expect(avatar_link).to be_nil + expect(response_avatar_link) + .to be_nil end end @@ -197,8 +199,8 @@ it 'does not return avatar in response' do perform_request! - avatar_link = get_avatar_link(response.parsed_body) - expect(avatar_link).to be_nil + expect(response_avatar_link) + .to be_nil end end end @@ -212,8 +214,8 @@ end it 'does not return avatar in response' do - avatar_link = get_avatar_link(response.parsed_body) - expect(avatar_link).to be_nil + expect(response_avatar_link) + .to be_nil end end @@ -247,7 +249,9 @@ private - def get_avatar_link(json) - json[:links].find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' } + def response_avatar_link + response + .parsed_body[:links] + .find { |link| link[:rel] == 'http://webfinger.net/rel/avatar' } end end diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index 635fcb7976c954..9d8c6e0e0a6b60 100644 --- a/spec/services/activitypub/fetch_remote_status_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb @@ -72,7 +72,7 @@ expect(status).to_not be_nil expect(status.url).to eq 'https://foo.bar/watch?v=12345' - expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345' + expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remix\n\nhttps://foo.bar/watch?v=12345" end end @@ -105,7 +105,7 @@ expect(status).to_not be_nil expect(status.url).to eq 'https://foo.bar/watch?v=12345' - expect(strip_tags(status.text)).to eq 'Nyan Cat 10 hours remixhttps://foo.bar/watch?v=12345' + expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remix\n\nhttps://foo.bar/watch?v=12345" end end @@ -125,7 +125,58 @@ expect(status).to_not be_nil expect(status.url).to eq 'https://foo.bar/@foo/1234' - expect(strip_tags(status.text)).to eq "Let's change the worldhttps://foo.bar/@foo/1234" + expect(strip_tags(status.text)).to eq "Let's change the world\n\nhttps://foo.bar/@foo/1234" + end + end + + context 'with Event object that contains a HTML summary' do + let(:object) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'https://foo.bar/@foo/1234', + type: 'Event', + name: 'Fediverse Birthday Party', + startTime: '2024-01-31T20:00:00.000+01:00', + location: { + type: 'Place', + name: 'FooBar – The not converted location', + }, + content: 'The not converted detailed description of the event object.', + summary: '

See you at the FooBar!

  • Doors: 8pm
  • Music: 10pm
', + attributedTo: ActivityPub::TagManager.instance.uri_for(sender), + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.url).to eq 'https://foo.bar/@foo/1234' + expect(status.text).to start_with "

#{object[:name]}

\n\n#{object[:summary]}\n\n" + expect(status.text).to include "href=\"#{object[:id]}\"" + end + end + + context 'with Article object that contains a HTML summary' do + let(:object) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'https://foo.bar/blog/future-of-the-fediverse', + type: 'Article', + name: 'Future of the Fediverse', + content: 'Lorem Ipsum', + summary: '

Guest article by John Mastodon

The fediverse is great reading this you will find out why!

', + attributedTo: ActivityPub::TagManager.instance.uri_for(sender), + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.url).to eq object[:id] + expect(status.text).to start_with "

#{object[:name]}

\n\n#{object[:summary]}\n\n" + expect(status.text).to include "href=\"#{object[:id]}\"" end end diff --git a/spec/services/approve_appeal_service_spec.rb b/spec/services/approve_appeal_service_spec.rb index 5707c5d7f4c5ea..52e073df0c769b 100644 --- a/spec/services/approve_appeal_service_spec.rb +++ b/spec/services/approve_appeal_service_spec.rb @@ -4,27 +4,55 @@ RSpec.describe ApproveAppealService do describe '#call' do - context 'with an existing appeal' do - let(:appeal) { Fabricate(:appeal) } - let(:account) { Fabricate(:account) } - - it 'processes the appeal approval' do - expect { subject.call(appeal, account) } - .to mark_overruled - .and record_approver - end + let(:appeal) { Fabricate(:appeal) } + let(:account) { Fabricate(:account) } + + it 'processes the appeal approval' do + expect { subject.call(appeal, account) } + .to mark_overruled + .and record_approver + end - def mark_overruled - change(appeal.strike, :overruled_at) - .from(nil) - .to(be > 1.minute.ago) + context 'with an appeal about then-deleted posts marked as sensitive by moderators' do + let(:target_account) { Fabricate(:account) } + let(:appeal) { Fabricate(:appeal, strike: strike, account: target_account) } + let(:deleted_media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status, account: target_account), account: target_account) } + let(:kept_media) { Fabricate(:media_attachment, type: :video, status: Fabricate(:status, account: target_account), account: target_account) } + let(:strike) { Fabricate(:account_warning, target_account: target_account, action: :mark_statuses_as_sensitive, status_ids: [deleted_media.status.id, kept_media.status.id]) } + + before do + target_account.unsuspend! + deleted_media.status.discard! end - def record_approver - change(appeal, :approved_by_account) - .from(nil) - .to(account) + it 'approves the appeal, marks the statuses as not sensitive and notifies target account about the approval', :inline_jobs do + emails = capture_emails { subject.call(appeal, account) } + + expect(appeal.reload).to be_approved + expect(strike.reload).to be_overruled + + expect(kept_media.status.reload).to_not be_sensitive + + expect(emails.size) + .to eq(1) + expect(emails.first) + .to have_attributes( + to: contain_exactly(target_account.user.email), + subject: eq(I18n.t('user_mailer.appeal_approved.subject', date: I18n.l(appeal.created_at))) + ) end end + + def mark_overruled + change(appeal.strike, :overruled_at) + .from(nil) + .to(be > 1.minute.ago) + end + + def record_approver + change(appeal, :approved_by_account) + .from(nil) + .to(account) + end end end diff --git a/spec/support/examples/mailers.rb b/spec/support/examples/mailers.rb index a8469f196490ac..c1767dc419f189 100644 --- a/spec/support/examples/mailers.rb +++ b/spec/support/examples/mailers.rb @@ -12,3 +12,32 @@ expect(mail.subject).to eq I18n.t(*args, **kwrest.merge(locale: I18n.default_locale)) end end + +RSpec::Matchers.define :have_thread_headers do + match(notify_expectation_failures: true) do |mail| + expect(mail) + .to be_present + .and(have_header('In-Reply-To', conversation_header_regex)) + .and(have_header('References', conversation_header_regex)) + end + + def conversation_header_regex = // +end + +RSpec::Matchers.define :have_standard_headers do |type| + chain :for do |user| + @user = user + end + + match(notify_expectation_failures: true) do |mail| + expect(mail) + .to be_present + .and(have_header('To', "#{@user.account.username} <#{@user.email}>")) + .and(have_header('List-ID', "<#{type}.#{@user.account.username}.#{Rails.configuration.x.local_domain}>")) + .and(have_header('List-Unsubscribe', %r{})) + .and(have_header('List-Unsubscribe', /&type=#{type}/)) + .and(have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click')) + .and(deliver_to("#{@user.account.username} <#{@user.email}>")) + .and(deliver_from(Rails.configuration.action_mailer.default_options[:from])) + end +end diff --git a/spec/system/settings/applications_spec.rb b/spec/system/settings/applications_spec.rb new file mode 100644 index 00000000000000..ee43da3d5d6171 --- /dev/null +++ b/spec/system/settings/applications_spec.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Settings applications page' do + let!(:application) { Fabricate :application, owner: user } + let(:user) { Fabricate :user } + + before { sign_in user } + + describe 'Viewing the list of applications' do + it 'sees the applications' do + visit settings_applications_path + + expect(page) + .to have_content(application.name) + .and have_private_cache_control + end + end + + describe 'Viewing a single application' do + it 'shows a page with application details' do + visit settings_application_path(application) + + expect(page) + .to have_content(application.name) + end + end + + describe 'Creating a new application' do + it 'accepts form input to make an application' do + visit new_settings_application_path + + fill_in_form + + expect { submit_form } + .to change(Doorkeeper::Application, :count).by(1) + expect(page) + .to have_content(I18n.t('doorkeeper.applications.index.title')) + .and have_content('My new app') + end + + it 'does not save with invalid form values' do + visit new_settings_application_path + + expect { submit_form } + .to not_change(Doorkeeper::Application, :count) + expect(page) + .to have_content("can't be blank") + end + + def fill_in_form + fill_in form_app_name_label, + with: 'My new app' + fill_in I18n.t('activerecord.attributes.doorkeeper/application.website'), + with: 'http://google.com' + fill_in I18n.t('activerecord.attributes.doorkeeper/application.redirect_uri'), + with: 'urn:ietf:wg:oauth:2.0:oob' + + check 'read', id: :doorkeeper_application_scopes_read + check 'write', id: :doorkeeper_application_scopes_write + check 'follow', id: :doorkeeper_application_scopes_follow + end + + def submit_form + click_on I18n.t('doorkeeper.applications.buttons.submit') + end + end + + describe 'Updating an application' do + it 'successfully updates with valid values' do + visit settings_application_path(application) + + fill_in form_app_name_label, + with: 'My new app name with a new value' + submit_form + + expect(page) + .to have_content('My new app name with a new value') + end + + it 'does not update with wrong values' do + visit settings_application_path(application) + + fill_in form_app_name_label, + with: '' + submit_form + + expect(page) + .to have_content("can't be blank") + end + + def submit_form + click_on I18n.t('generic.save_changes') + end + end + + describe 'Destroying an application' do + let(:redis_pipeline_stub) { instance_double(Redis::Namespace, publish: nil) } + let!(:access_token) { Fabricate(:accessible_access_token, application: application) } + + before { stub_redis_pipeline } + + it 'destroys the record and tells the broader universe about that' do + visit settings_applications_path + + expect { destroy_application } + .to change(Doorkeeper::Application, :count).by(-1) + expect(page) + .to have_no_content(application.name) + expect(redis_pipeline_stub) + .to have_received(:publish).with("timeline:access_token:#{access_token.id}", '{"event":"kill"}') + end + + def destroy_application + click_on I18n.t('doorkeeper.applications.index.delete') + end + + def stub_redis_pipeline + allow(redis) + .to receive(:pipelined) + .and_yield(redis_pipeline_stub) + end + end + + describe 'Regenerating an app token' do + it 'updates the app token' do + visit settings_application_path(application) + + expect { regenerate_token } + .to(change { user.token_for_app(application) }) + expect(page) + .to have_content(I18n.t('applications.token_regenerated')) + end + + def regenerate_token + click_on I18n.t('applications.regenerate_token') + end + end + + def form_app_name_label + I18n.t('activerecord.attributes.doorkeeper/application.name') + end +end diff --git a/streaming/package.json b/streaming/package.json index 64947749a17ad8..d573c9b2845139 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/streaming", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.4.1", + "packageManager": "yarn@4.5.0", "engines": { "node": ">=18" }, diff --git a/yarn.lock b/yarn.lock index 5de514cc5a1204..628b3c43ad9221 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2010,6 +2010,55 @@ __metadata: languageName: node linkType: hard +"@dnd-kit/accessibility@npm:^3.1.0": + version: 3.1.0 + resolution: "@dnd-kit/accessibility@npm:3.1.0" + dependencies: + tslib: "npm:^2.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: 10c0/4f9d24e801d66d4fbb551ec389ed90424dd4c5bbdf527000a618e9abb9833cbd84d9a79e362f470ccbccfbd6d00217a9212c92f3cef66e01c951c7f79625b9d7 + languageName: node + linkType: hard + +"@dnd-kit/core@npm:^6.1.0": + version: 6.1.0 + resolution: "@dnd-kit/core@npm:6.1.0" + dependencies: + "@dnd-kit/accessibility": "npm:^3.1.0" + "@dnd-kit/utilities": "npm:^3.2.2" + tslib: "npm:^2.0.0" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10c0/c793eb97cb59285ca8937ebcdfcd27cff09d750ae06722e36ca5ed07925e41abc36a38cff98f9f6056f7a07810878d76909826142a2968330e7e22060e6be584 + languageName: node + linkType: hard + +"@dnd-kit/sortable@npm:^8.0.0": + version: 8.0.0 + resolution: "@dnd-kit/sortable@npm:8.0.0" + dependencies: + "@dnd-kit/utilities": "npm:^3.2.2" + tslib: "npm:^2.0.0" + peerDependencies: + "@dnd-kit/core": ^6.1.0 + react: ">=16.8.0" + checksum: 10c0/a6066c652b892c6a11320c7d8f5c18fdf723e721e8eea37f4ab657dee1ac5e7ca710ac32ce0712a57fe968bc07c13bcea5d5599d90dfdd95619e162befd4d2fb + languageName: node + linkType: hard + +"@dnd-kit/utilities@npm:^3.2.2": + version: 3.2.2 + resolution: "@dnd-kit/utilities@npm:3.2.2" + dependencies: + tslib: "npm:^2.0.0" + peerDependencies: + react: ">=16.8.0" + checksum: 10c0/9aa90526f3e3fd567b5acc1b625a63177b9e8d00e7e50b2bd0e08fa2bf4dba7e19529777e001fdb8f89a7ce69f30b190c8364d390212634e0afdfa8c395e85a0 + languageName: node + linkType: hard + "@dual-bundle/import-meta-resolve@npm:^4.1.0": version: 4.1.0 resolution: "@dual-bundle/import-meta-resolve@npm:4.1.0" @@ -2330,9 +2379,9 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl@npm:2.10.4": - version: 2.10.4 - resolution: "@formatjs/intl@npm:2.10.4" +"@formatjs/intl@npm:2.10.5": + version: 2.10.5 + resolution: "@formatjs/intl@npm:2.10.5" dependencies: "@formatjs/ecma402-abstract": "npm:2.0.0" "@formatjs/fast-memoize": "npm:2.2.0" @@ -2346,7 +2395,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/ca7877e962f73f1fe0e358f12d73bdc3ec4006c14ee801e06d9f7aef06bcdcc12355a8f53f32b0e890f829949ded35e825c914ca5f4709eb1e08c2a18c1368c2 + checksum: 10c0/d00ef00e41200947ed22895b73a0863283de4762ec238b4a81e2252e642e30a309cd9c73174e4917b6c675ab6f148eda5a4e3345c3caeef64e090fc8374d27c4 languageName: node linkType: hard @@ -2753,6 +2802,9 @@ __metadata: "@babel/preset-react": "npm:^7.22.3" "@babel/preset-typescript": "npm:^7.21.5" "@babel/runtime": "npm:^7.22.3" + "@dnd-kit/core": "npm:^6.1.0" + "@dnd-kit/sortable": "npm:^8.0.0" + "@dnd-kit/utilities": "npm:^3.2.2" "@formatjs/cli": "npm:^6.1.1" "@formatjs/intl-pluralrules": "npm:^5.2.2" "@gamestdio/websocket": "npm:^0.3.2" @@ -3713,9 +3765,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.7 - resolution: "@types/lodash@npm:4.17.7" - checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561 + version: 4.17.9 + resolution: "@types/lodash@npm:4.17.9" + checksum: 10c0/54de935e835508b5f835a5dfaedd2b9a299685a21d11e9c5cd2dde57331d03bc2f98b71d2424ca8460f447ecd55a673e45ccdb70e58f9f72745710f6b91abc60 languageName: node linkType: hard @@ -3789,9 +3841,9 @@ __metadata: linkType: hard "@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5": - version: 15.7.12 - resolution: "@types/prop-types@npm:15.7.12" - checksum: 10c0/1babcc7db6a1177779f8fde0ccc78d64d459906e6ef69a4ed4dd6339c920c2e05b074ee5a92120fe4e9d9f1a01c952f843ebd550bee2332fc2ef81d1706878f8 + version: 15.7.13 + resolution: "@types/prop-types@npm:15.7.13" + checksum: 10c0/1b20fc67281902c6743379960247bc161f3f0406ffc0df8e7058745a85ea1538612109db0406290512947f9632fe9e10e7337bf0ce6338a91d6c948df16a7c61 languageName: node linkType: hard @@ -3934,12 +3986,12 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.3.5 - resolution: "@types/react@npm:18.3.5" + version: 18.3.10 + resolution: "@types/react@npm:18.3.10" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10c0/548b1d3d7c2f0242fbfdbbd658731b4ce69a134be072fa83e6ab516f2840402a3f20e3e7f72e95133b23d4880ef24a6d864050dc8e1f7c68f39fa87ca8445917 + checksum: 10c0/f5be1de1b0331c1fdb33d577f4cf7f1b949d4bded5347b2351a537f03c51dade5be115e21b161dcf1b37061954d320f6a0bdf8d7b70e24eda51071fdd614383d languageName: node linkType: hard @@ -6836,12 +6888,12 @@ __metadata: languageName: node linkType: hard -"cssstyle@npm:^4.0.1": - version: 4.0.1 - resolution: "cssstyle@npm:4.0.1" +"cssstyle@npm:^4.1.0": + version: 4.1.0 + resolution: "cssstyle@npm:4.1.0" dependencies: - rrweb-cssom: "npm:^0.6.0" - checksum: 10c0/cadf9a8b23e11f4c6d63f21291096a0b0be868bd4ab9c799daa2c5b18330e39e5281605f01da906e901b42f742df0f3b3645af6465e83377ff7d15a88ee432a0 + rrweb-cssom: "npm:^0.7.1" + checksum: 10c0/05c6597e5d3e0ec6b15221f2c0ce9a0443a46cc50a6089a3ba9ee1ac27f83ff86a445a8f95435137dadd859f091fc61b6d342abaf396d3c910471b5b33cfcbfa languageName: node linkType: hard @@ -11129,10 +11181,10 @@ __metadata: linkType: hard "jsdom@npm:^25.0.0": - version: 25.0.0 - resolution: "jsdom@npm:25.0.0" + version: 25.0.1 + resolution: "jsdom@npm:25.0.1" dependencies: - cssstyle: "npm:^4.0.1" + cssstyle: "npm:^4.1.0" data-urls: "npm:^5.0.0" decimal.js: "npm:^10.4.3" form-data: "npm:^4.0.0" @@ -11145,7 +11197,7 @@ __metadata: rrweb-cssom: "npm:^0.7.1" saxes: "npm:^6.0.0" symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.1.4" + tough-cookie: "npm:^5.0.0" w3c-xmlserializer: "npm:^5.0.0" webidl-conversions: "npm:^7.0.0" whatwg-encoding: "npm:^3.1.1" @@ -11158,7 +11210,7 @@ __metadata: peerDependenciesMeta: canvas: optional: true - checksum: 10c0/1552bcfb816b2c69ae159ba0cd79e8964030c106cc0cb2deb20a64c1ca54e1ea41352b9802d89b7cf823e43e6d74ed7289abff4aacc95b1b2bc936570aab3594 + checksum: 10c0/6bda32a6dfe4e37a30568bf51136bdb3ba9c0b72aadd6356280404275a34c9e097c8c25b5eb3c742e602623741e172da977ff456684befd77c9042ed9bf8c2b4 languageName: node linkType: hard @@ -14533,12 +14585,12 @@ __metadata: linkType: hard "react-intl@npm:^6.4.2": - version: 6.6.8 - resolution: "react-intl@npm:6.6.8" + version: 6.7.0 + resolution: "react-intl@npm:6.7.0" dependencies: "@formatjs/ecma402-abstract": "npm:2.0.0" "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/intl": "npm:2.10.4" + "@formatjs/intl": "npm:2.10.5" "@formatjs/intl-displaynames": "npm:6.6.8" "@formatjs/intl-listformat": "npm:7.5.7" "@types/hoist-non-react-statics": "npm:^3.3.1" @@ -14552,7 +14604,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/7673507eb73ad4edd1593da7173cec68f316cf77037e0959900babd32d5984a39ba7fa10aaa0a23bcddb7b98daf7dd007cb73ddfc39127ede87c18ec780a519c + checksum: 10c0/210088bf0e934ad5f09d8e7c6d7d72682bb806583645fb333d4efd8ae55585b675ea8e47bb240140d5143ca15ecc0457c3ddc3e8ca45e9b576bce1fa2f9886b3 languageName: node linkType: hard @@ -15390,13 +15442,6 @@ __metadata: languageName: node linkType: hard -"rrweb-cssom@npm:^0.6.0": - version: 0.6.0 - resolution: "rrweb-cssom@npm:0.6.0" - checksum: 10c0/3d9d90d53c2349ea9c8509c2690df5a4ef930c9cf8242aeb9425d4046f09d712bb01047e00da0e1c1dab5db35740b3d78fd45c3e7272f75d3724a563f27c30a3 - languageName: node - linkType: hard - "rrweb-cssom@npm:^0.7.1": version: 0.7.1 resolution: "rrweb-cssom@npm:0.7.1" @@ -15499,15 +15544,15 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.79.2 - resolution: "sass@npm:1.79.2" + version: 1.79.4 + resolution: "sass@npm:1.79.4" dependencies: chokidar: "npm:^4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/b637daf133da4fbafbb7e6ae07b01ff7c73e406f3134e66749bf6f712dcc0056c6971d8629d8cc2b186df5ffb2282baa8f1818f35e326b3558ab284e31fdd87d + checksum: 10c0/505ff0d9267d0fb990971e617acfeabf7c060c55d4cef68fe8a4bc693e7ea88ae7d7caeca3975e4b453459ba4a707b6e5b6979fc9395a7e08f0a43ca6aed06b8 languageName: node linkType: hard @@ -17060,6 +17105,24 @@ __metadata: languageName: node linkType: hard +"tldts-core@npm:^6.1.47": + version: 6.1.47 + resolution: "tldts-core@npm:6.1.47" + checksum: 10c0/538372072aea7153e842646a9e22d0d9335acf7fd877d10ee374cf78dceff79a2ccebadf7d25e0dbddd7b7b60bafe1c885aac3e3b1d5bec7806963c89b163ee7 + languageName: node + linkType: hard + +"tldts@npm:^6.1.32": + version: 6.1.47 + resolution: "tldts@npm:6.1.47" + dependencies: + tldts-core: "npm:^6.1.47" + bin: + tldts: bin/cli.js + checksum: 10c0/42c999ab24ce3ab221cfefe77488d145d16d9523524913badaa4af4f1f0d65e0a92a678659b22b7d26d1c62796540c95158049220c9ff243090b93470f236302 + languageName: node + linkType: hard + "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -17135,7 +17198,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.1.2, tough-cookie@npm:^4.1.4": +"tough-cookie@npm:^4.1.2": version: 4.1.4 resolution: "tough-cookie@npm:4.1.4" dependencies: @@ -17147,6 +17210,15 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^5.0.0": + version: 5.0.0 + resolution: "tough-cookie@npm:5.0.0" + dependencies: + tldts: "npm:^6.1.32" + checksum: 10c0/4a69c885bf6f45c5a64e60262af99e8c0d58a33bd3d0ce5da62121eeb9c00996d0128a72df8fc4614cbde59cc8b70aa3e21e4c3c98c2bbde137d7aba7fa00124 + languageName: node + linkType: hard + "tr46@npm:^1.0.1": version: 1.0.1 resolution: "tr46@npm:1.0.1" @@ -17209,10 +17281,10 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.4.0, tslib@npm:^2.6.2": - version: 2.6.3 - resolution: "tslib@npm:2.6.3" - checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a +"tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard