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/.env.production.sample b/.env.production.sample index e8c1529f920c08..83e2b198d22879 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -73,6 +73,16 @@ DB_PORT=5432 SECRET_KEY_BASE= OTP_SECRET= +# Encryption secrets +# ------------------ +# Must be available (and set to same values) for all server processes +# These are private/secret values, do not share outside hosting environment +# Use `bin/rails db:encryption:init` to generate fresh secrets +# Do not change these secrets once in use, as this would cause data loss and other issues +# ------------------ +# ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY= +# ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT= +# ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY= # Web Push # -------- diff --git a/.eslintrc.js b/.eslintrc.js index f9ddb42ae02558..ce9fb0927e4432 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -64,7 +64,6 @@ module.exports = defineConfig({ 'indent': ['error', 2], 'jsx-quotes': ['error', 'prefer-single'], 'semi': ['error', 'always'], - 'no-case-declarations': 'off', 'no-catch-shadow': 'error', 'no-console': [ 'warn', diff --git a/.github/ISSUE_TEMPLATE/1.web_bug_report.yml b/.github/ISSUE_TEMPLATE/1.web_bug_report.yml index 20e27d103cdb07..f897a7d7da434e 100644 --- a/.github/ISSUE_TEMPLATE/1.web_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1.web_bug_report.yml @@ -1,6 +1,7 @@ name: Bug Report (Web Interface) -description: If you are using Mastodon's web interface and something is not working as expected -labels: [bug, 'status/to triage', 'area/web interface'] +description: There is a problem using Mastodon's web interface. +labels: ['status/to triage', 'area/web interface'] +type: Bug body: - type: markdown attributes: @@ -47,8 +48,8 @@ body: attributes: label: Mastodon version description: | - This is displayed at the bottom of the About page, eg. `v4.1.2+nightly-20230627` - placeholder: v4.1.2 + This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1` + placeholder: v4.3.0 validations: required: true - type: input @@ -56,7 +57,7 @@ body: label: Browser name and version description: | What browser are you using when getting this bug? Please specify the version as well. - placeholder: Firefox 105.0.3 + placeholder: Firefox 131.0.0 validations: required: true - type: input @@ -64,7 +65,7 @@ body: label: Operating system description: | What OS are you running? Please specify the version as well. - placeholder: macOS 13.4.1 + placeholder: macOS 15.0.1 validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/2.server_bug_report.yml b/.github/ISSUE_TEMPLATE/2.server_bug_report.yml index 49d5f57209fd80..a66f5c1076d504 100644 --- a/.github/ISSUE_TEMPLATE/2.server_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/2.server_bug_report.yml @@ -1,7 +1,8 @@ name: Bug Report (server / API) description: | - If something is not working as expected, but is not from using the web interface. -labels: [bug, 'status/to triage'] + There is a problem with the HTTP server, REST API, ActivityPub interaction, etc. +labels: ['status/to triage'] +type: 'Bug' body: - type: markdown attributes: @@ -48,8 +49,8 @@ body: attributes: label: Mastodon version description: | - This is displayed at the bottom of the About page, eg. `v4.1.2+nightly-20230627` - placeholder: v4.1.2 + This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1` + placeholder: v4.3.0 validations: required: false - type: textarea @@ -59,7 +60,7 @@ body: Any additional technical details you may have, like logs or error traces value: | If this is happening on your own Mastodon server, please fill out those: - - Ruby version: (from `ruby --version`, eg. v3.1.2) - - Node.js version: (from `node --version`, eg. v18.16.0) + - Ruby version: (from `ruby --version`, eg. v3.3.5) + - Node.js version: (from `node --version`, eg. v20.18.0) validations: required: false diff --git a/.github/ISSUE_TEMPLATE/3.troubleshooting.yml b/.github/ISSUE_TEMPLATE/3.troubleshooting.yml new file mode 100644 index 00000000000000..eeb74b160b1040 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3.troubleshooting.yml @@ -0,0 +1,74 @@ +name: Deployment troubleshooting +description: | + You are a server administrator and you are encountering a technical issue during installation, upgrade or operations of Mastodon. +labels: ['status/to triage'] +type: 'Troubleshooting' +body: + - type: markdown + attributes: + value: | + Make sure that you are submitting a new bug that was not previously reported or already fixed. + + Please use a concise and distinct title for the issue. + - type: textarea + attributes: + label: Steps to reproduce the problem + description: What were you trying to do? + value: | + 1. + 2. + 3. + ... + validations: + required: true + - type: input + attributes: + label: Expected behaviour + description: What should have happened? + validations: + required: true + - type: input + attributes: + label: Actual behaviour + description: What happened? + validations: + required: true + - type: textarea + attributes: + label: Detailed description + validations: + required: false + - type: input + attributes: + label: Mastodon instance + description: The address of the Mastodon instance where you experienced the issue + placeholder: mastodon.social + validations: + required: true + - type: input + attributes: + label: Mastodon version + description: | + This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1` + placeholder: v4.3.0 + validations: + required: false + - type: textarea + attributes: + label: Environment + description: | + Details about your environment, like how Mastodon is deployed, if containers are used, version numbers, etc. + value: | + Please at least include those informations: + - Operating system: (eg. Ubuntu 22.04) + - Ruby version: (from `ruby --version`, eg. v3.3.5) + - Node.js version: (from `node --version`, eg. v20.18.0) + validations: + required: false + - type: textarea + attributes: + label: Technical details + description: | + Any additional technical details you may have, like logs or error traces + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/3.feature_request.yml b/.github/ISSUE_TEMPLATE/4.feature_request.yml similarity index 96% rename from .github/ISSUE_TEMPLATE/3.feature_request.yml rename to .github/ISSUE_TEMPLATE/4.feature_request.yml index 2cabcf61e08ecc..7146b4f8a3e436 100644 --- a/.github/ISSUE_TEMPLATE/3.feature_request.yml +++ b/.github/ISSUE_TEMPLATE/4.feature_request.yml @@ -1,6 +1,6 @@ name: Feature Request description: I have a suggestion -labels: [suggestion] +type: Suggestion body: - type: markdown attributes: diff --git a/.github/workflows/build-push-pr.yml b/.github/workflows/build-push-pr.yml index 4505151e1a6af7..d6324bad89259a 100644 --- a/.github/workflows/build-push-pr.yml +++ b/.github/workflows/build-push-pr.yml @@ -21,9 +21,11 @@ jobs: uses: actions/checkout@v4 - id: version_vars run: | - echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT + echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT + echo mastodon_short_sha=$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT outputs: metadata: ${{ steps.version_vars.outputs.mastodon_version_metadata }} + short_sha: ${{ steps.version_vars.outputs.mastodon_short_sha }} build-image: needs: compute-suffix @@ -39,6 +41,7 @@ jobs: latest=auto tags: | type=ref,event=pr + type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }} secrets: inherit build-image-streaming: @@ -55,4 +58,5 @@ jobs: latest=auto tags: | type=ref,event=pr + type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }} secrets: inherit diff --git a/.github/workflows/build-releases.yml b/.github/workflows/build-releases.yml index 8e0fe5dfa8a862..808ffe115d952e 100644 --- a/.github/workflows/build-releases.yml +++ b/.github/workflows/build-releases.yml @@ -22,7 +22,7 @@ jobs: # Only tag with latest when ran against the latest stable branch # This needs to be updated after each minor version release flavor: | - latest=${{ startsWith(github.ref, 'refs/tags/v4.2.') }} + latest=${{ startsWith(github.ref, 'refs/tags/v4.3.') }} tags: | type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} diff --git a/.github/workflows/build-security.yml b/.github/workflows/build-security.yml index e9f1862f5d1b54..37c8ba59a37d54 100644 --- a/.github/workflows/build-security.yml +++ b/.github/workflows/build-security.yml @@ -32,7 +32,7 @@ jobs: labels: | org.opencontainers.image.description=Nightly build image used for testing purposes flavor: | - latest=true + latest=auto tags: | type=raw,value=edge type=raw,value=nightly @@ -53,7 +53,7 @@ jobs: labels: | org.opencontainers.image.description=Nightly build image used for testing purposes flavor: | - latest=true + latest=auto tags: | type=raw,value=edge type=raw,value=nightly diff --git a/.github/workflows/crowdin-download-stable.yml b/.github/workflows/crowdin-download-stable.yml new file mode 100644 index 00000000000000..18911d49c2ff25 --- /dev/null +++ b/.github/workflows/crowdin-download-stable.yml @@ -0,0 +1,70 @@ +name: Crowdin / Download translations (stable branches) +on: + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + download-translations-stable: + runs-on: ubuntu-latest + if: github.repository == 'mastodon/mastodon' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Increase Git http.postBuffer + # This is needed due to a bug in Ubuntu's cURL version? + # See https://github.com/orgs/community/discussions/55820 + run: | + git config --global http.version HTTP/1.1 + git config --global http.postBuffer 157286400 + + # Download the translation files from Crowdin + - name: crowdin action + uses: crowdin/github-action@v2 + with: + config: crowdin-glitch.yml + upload_sources: false + upload_translations: false + download_translations: true + crowdin_branch_name: ${{ github.base_ref || github.ref_name }} + push_translations: false + create_pull_request: false + env: + CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + # As the files are extracted from a Docker container, they belong to root:root + # We need to fix this before the next steps + - name: Fix file permissions + run: sudo chown -R runner:docker . + + # This is needed to run the normalize step + - name: Set up Ruby environment + uses: ./.github/actions/setup-ruby + + - name: Run i18n normalize task + run: bundle exec i18n-tasks normalize + + # Create or update the pull request + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7.0.5 + with: + commit-message: 'New Crowdin translations' + title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)' + author: 'GitHub Actions ' + body: | + New Crowdin translations, automated with GitHub Actions + + See `.github/workflows/crowdin-download.yml` + + This PR will be updated every day with new translations. + + Due to a limitation in GitHub Actions, checks are not running on this PR without manual action. + If you want to run the checks, then close and re-open it. + branch: i18n/crowdin/translations-${{ github.base_ref || github.ref_name }} + base: ${{ github.base_ref || github.ref_name }} + labels: i18n diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml index b3d908b77e8c9b..02d8a949dec541 100644 --- a/.github/workflows/crowdin-download.yml +++ b/.github/workflows/crowdin-download.yml @@ -53,7 +53,7 @@ jobs: # Create or update the pull request - name: Create Pull Request - uses: peter-evans/create-pull-request@v7.0.1 + uses: peter-evans/create-pull-request@v7.0.5 with: commit-message: 'New Crowdin translations' title: 'New Crowdin Translations (automated)' diff --git a/.github/workflows/crowdin-upload.yml b/.github/workflows/crowdin-upload.yml index d07f661ace8b26..c48668d3bc3e55 100644 --- a/.github/workflows/crowdin-upload.yml +++ b/.github/workflows/crowdin-upload.yml @@ -1,7 +1,6 @@ name: Crowdin / Upload translations on: - merge_group: push: branches: - 'main' @@ -32,7 +31,7 @@ jobs: upload_sources: true upload_translations: false download_translations: false - crowdin_branch_name: main + crowdin_branch_name: ${{ github.base_ref || github.ref_name }} env: CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index 6a0e67c58ee500..5b80fef03724db 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -32,6 +32,8 @@ jobs: postgres: - 14-alpine - 15-alpine + - 16-alpine + - 17-alpine services: postgres: diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 3da53c1ae8e0dc..c05c8333b2048c 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -143,7 +143,7 @@ jobs: uses: ./.github/actions/setup-ruby with: ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg libpam-dev + additional-system-dependencies: ffmpeg imagemagick libpam-dev - name: Load database schema run: | @@ -245,7 +245,7 @@ jobs: uses: ./.github/actions/setup-ruby with: ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg libpam-dev libyaml-dev + additional-system-dependencies: ffmpeg libpam-dev - name: Load database schema run: './bin/rails db:create db:schema:load db:seed' @@ -325,7 +325,7 @@ jobs: uses: ./.github/actions/setup-ruby with: ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg + additional-system-dependencies: ffmpeg imagemagick - name: Set up Javascript environment uses: ./.github/actions/setup-javascript @@ -445,7 +445,7 @@ jobs: uses: ./.github/actions/setup-ruby with: ruby-version: ${{ matrix.ruby-version}} - additional-system-dependencies: ffmpeg + additional-system-dependencies: ffmpeg imagemagick - name: Set up Javascript environment uses: ./.github/actions/setup-javascript diff --git a/.nvmrc b/.nvmrc index 65da8ce3917325..10fef252a9f178 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.17 +20.18 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1e0bfcf78061..0fc5291d7226b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. -## [4.3.0] - UNRELEASED +## [4.3.0] - 2024-10-08 The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by @mjankowski. @@ -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. -- Change `form-action` Content-Security-Policy directive to be more restrictive (#26897 by @ClearlyClaire) +- 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 and #32241 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, #32085, #32243, #32179 and #32254 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, #32062 and #32281 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.\ @@ -60,13 +61,13 @@ The following changelog entries focus on changes visible to users, administrator - **Add timeline of public posts about a trending link** (#30381 and #30840 by @Gargron)\ You can now see public posts mentioning currently-trending articles from people who have opted into discovery features.\ This adds a new REST API endpoint: https://docs.joinmastodon.org/methods/timelines/#link -- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, #30846, #31819, and #31900 by @Gargron and @oneiros)\ +- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, #30846, #31819, #31900 and #32188 by @Gargron, @mjankowski and @oneiros)\ This adds a mechanism to [highlight the author of news articles](https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/) shared on Mastodon.\ Articles hosted outside the fediverse can indicate a fediverse author with a meta tag: ```html ``` - On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors\ + On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors \ Users can allow arbitrary domains to use `fediverse:creator` to credit them by visiting `/settings/verification`.\ This is federated as a new `attributionDomains` property in the `http://joinmastodon.org/ns` namespace, containing an array of domain names: https://docs.joinmastodon.org/spec/activitypub/#properties-used-1 - **Add in-app notifications for moderation actions and warnings** (#30065, #30082, and #30081 by @ClearlyClaire)\ @@ -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) @@ -146,10 +150,12 @@ The following changelog entries focus on changes visible to users, administrator - Add groundwork for annual reports for accounts (#28693 by @Gargron)\ This lays the groundwork for a “year-in-review”/“wrapped” style report for local users, but is currently not in use. - Add notification email on invalid second authenticator (#28822 by @ClearlyClaire) +- Add date of account deletion in list of accounts in the admin interface (#25640 by @tribela) - Add new emojis from `jdecked/twemoji` 15.0 (#28404 by @TheEssem) - Add configurable error handling in attachment batch deletion (#28184 by @vmstan)\ This makes the S3 batch size configurable through the `S3_BATCH_DELETE_LIMIT` environment variable (defaults to 1000), and adds some retry logic, configurable through the `S3_BATCH_DELETE_RETRY` environment variable (defaults to 3). - Add VAPID public key to instance serializer (#28006 by @ThisIsMissEm) +- Add support for serving JRD `/.well-known/host-meta.json` in addition to XRD host-meta (#32206 by @c960657) - Add `nodeName` and `nodeDescription` to nodeinfo `metadata` (#28079 by @6543) - Add Thai diacritics and tone marks in `HASHTAG_INVALID_CHARS_RE` (#26576 by @ppnplus) - Add variable delay before link verification of remote account links (#27774 by @ClearlyClaire) @@ -164,18 +170,18 @@ The following changelog entries focus on changes visible to users, administrator ### Changed -- **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)\ +- **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, #31525, #32153, and #32201 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 +194,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, #32135 and #32271 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, #31967, #32217, #32224 and #32257 by @ClearlyClaire and @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 +267,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 +283,22 @@ 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 unresolvable mentions sometimes preventing processing incoming posts (#29215 by @tribela and @ClearlyClaire) +- 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 and #32270 by @Gargron and @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,10 +312,12 @@ 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, #32091, #32147 and #32137 by @ClearlyClaire, @mjankowski, @valtlai and @vmstan) +- Fix editing description of media uploads with custom thumbnails (#32221 by @ClearlyClaire) - 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) +- Fix unneeded requests to blocked domains when receiving relayed signed activities from them (#31161 by @ClearlyClaire) - Fix logo pushing header buttons out of view on certain conditions in mobile layout (#29787 by @ClearlyClaire) - Fix notification-related records not being reattributed when merging accounts (#29694 by @ClearlyClaire) - Fix results/query in `api/v1/featured_tags/suggestions` (#29597 by @mjankowski) @@ -298,6 +327,7 @@ The following changelog entries focus on changes visible to users, administrator - Fix full date display not respecting the locale 12/24h format (#29448 by @renchap) - Fix filters title and keywords overflow (#29396 by @GeopJr) - Fix incorrect date format in “Follows and followers” (#29390 by @JasonPunyon) +- Fix navigation item active highlight for some paths (#32159 by @mjankowski) - Fix “Edit media” modal sizing and layout when space-constrained (#27095 by @ronilaukkarinen) - Fix modal container bounds (#29185 by @nico3333fr) - Fix inefficient HTTP signature parsing using regexps and `StringScanner` (#29133 by @ClearlyClaire) diff --git a/Dockerfile b/Dockerfile index c7c02d9b467ef9..a5e35025ae2f6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.9 +# syntax=docker/dockerfile:1.10 # This file is designed for production server deployment, not local development work # For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/README.md#docker @@ -214,7 +214,7 @@ FROM build AS ffmpeg # ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"] # renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg -ARG FFMPEG_VERSION=7.0.2 +ARG FFMPEG_VERSION=7.1 # ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"] ARG FFMPEG_URL=https://ffmpeg.org/releases diff --git a/Gemfile.lock b/Gemfile.lock index 3483a498e362eb..d1ee8e0fa8eacd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,35 +10,35 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) + actioncable (7.1.4.1) + actionpack (= 7.1.4.1) + activesupport (= 7.1.4.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.4) - actionpack (= 7.1.4) - activejob (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) + actionmailbox (7.1.4.1) + actionpack (= 7.1.4.1) + activejob (= 7.1.4.1) + activerecord (= 7.1.4.1) + activestorage (= 7.1.4.1) + activesupport (= 7.1.4.1) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.1.4) - actionpack (= 7.1.4) - actionview (= 7.1.4) - activejob (= 7.1.4) - activesupport (= 7.1.4) + actionmailer (7.1.4.1) + actionpack (= 7.1.4.1) + actionview (= 7.1.4.1) + activejob (= 7.1.4.1) + activesupport (= 7.1.4.1) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.2) - actionpack (7.1.4) - actionview (= 7.1.4) - activesupport (= 7.1.4) + actionpack (7.1.4.1) + actionview (= 7.1.4.1) + activesupport (= 7.1.4.1) nokogiri (>= 1.8.5) racc rack (>= 2.2.4) @@ -46,15 +46,15 @@ GEM rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.4) - actionpack (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) + actiontext (7.1.4.1) + actionpack (= 7.1.4.1) + activerecord (= 7.1.4.1) + activestorage (= 7.1.4.1) + activesupport (= 7.1.4.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.4) - activesupport (= 7.1.4) + actionview (7.1.4.1) + activesupport (= 7.1.4.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) @@ -64,22 +64,22 @@ GEM activemodel (>= 4.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.1.4) - activesupport (= 7.1.4) + activejob (7.1.4.1) + activesupport (= 7.1.4.1) globalid (>= 0.3.6) - activemodel (7.1.4) - activesupport (= 7.1.4) - activerecord (7.1.4) - activemodel (= 7.1.4) - activesupport (= 7.1.4) + activemodel (7.1.4.1) + activesupport (= 7.1.4.1) + activerecord (7.1.4.1) + activemodel (= 7.1.4.1) + activesupport (= 7.1.4.1) timeout (>= 0.4.0) - activestorage (7.1.4) - actionpack (= 7.1.4) - activejob (= 7.1.4) - activerecord (= 7.1.4) - activesupport (= 7.1.4) + activestorage (7.1.4.1) + actionpack (= 7.1.4.1) + activejob (= 7.1.4.1) + activerecord (= 7.1.4.1) + activesupport (= 7.1.4.1) marcel (~> 1.0) - activesupport (7.1.4) + activesupport (7.1.4.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) @@ -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.983.0) + aws-sdk-core (3.209.1) 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.167.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) @@ -301,7 +301,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.58.0) + haml_lint (0.59.0) haml (>= 5.0) parallel (~> 1.10) rainbow @@ -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) @@ -369,7 +369,7 @@ GEM json-ld-preloaded (3.3.0) json-ld (~> 3.3) rdf (~> 3.3) - json-schema (5.0.0) + json-schema (5.0.1) addressable (~> 2.8) jsonapi-renderer (0.2.2) jwt (2.7.1) @@ -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) @@ -591,7 +591,7 @@ GEM pastel (0.8.0) tty-color (~> 0.5) pg (1.5.8) - pghero (3.6.0) + pghero (3.6.1) activerecord (>= 6.1) premailer (1.27.0) addressable @@ -601,7 +601,7 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) - propshaft (1.0.0) + propshaft (1.1.0) actionpack (>= 7.0.0) activesupport (>= 7.0.0) rack @@ -615,7 +615,7 @@ GEM activesupport (>= 3.0.0) raabro (1.4.0) racc (1.8.1) - rack (2.2.9) + rack (2.2.10) rack-attack (6.7.0) rack (>= 1.0, < 4) rack-cors (2.0.2) @@ -638,20 +638,20 @@ GEM rackup (1.0.0) rack (< 3) webrick - rails (7.1.4) - actioncable (= 7.1.4) - actionmailbox (= 7.1.4) - actionmailer (= 7.1.4) - actionpack (= 7.1.4) - actiontext (= 7.1.4) - actionview (= 7.1.4) - activejob (= 7.1.4) - activemodel (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) + rails (7.1.4.1) + actioncable (= 7.1.4.1) + actionmailbox (= 7.1.4.1) + actionmailer (= 7.1.4.1) + actionpack (= 7.1.4.1) + actiontext (= 7.1.4.1) + actionview (= 7.1.4.1) + activejob (= 7.1.4.1) + activemodel (= 7.1.4.1) + activerecord (= 7.1.4.1) + activestorage (= 7.1.4.1) + activesupport (= 7.1.4.1) bundler (>= 1.15.0) - railties (= 7.1.4) + railties (= 7.1.4.1) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -666,9 +666,9 @@ GEM rails-i18n (7.0.9) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) + railties (7.1.4.1) + actionpack (= 7.1.4.1) + activesupport (= 7.1.4.1) irb rackup (>= 1.0.0) rake (>= 12.2) @@ -698,7 +698,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.7) + rexml (3.3.8) rotp (6.3.0) rouge (4.3.0) rpam2 (4.0.2) @@ -748,15 +748,15 @@ GEM parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) - rubocop-performance (1.21.1) + rubocop-performance (1.22.1) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.25.1) + rubocop-rails (2.26.2) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 1.33.0, < 2.0) + rubocop (>= 1.52.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.0.4) + rubocop-rspec (3.1.0) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) @@ -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) @@ -815,14 +815,14 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) + simplecov-html (0.13.1) simplecov-lcov (0.8.0) simplecov_json_formatter (0.1.4) stackprof (0.2.26) stoplight (4.1.0) redlock (~> 1.0) stringio (3.1.1) - strong_migrations (2.0.0) + strong_migrations (2.0.1) activerecord (>= 6.1) swd (1.3.0) activesupport (>= 3) @@ -862,7 +862,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.9.1) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) uri (0.13.1) validate_email (0.1.6) activemodel (>= 3.0) @@ -884,7 +884,7 @@ GEM webfinger (1.2.0) activesupport httpclient (>= 2.4) - webmock (3.23.1) + webmock (3.24.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -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/SECURITY.md b/SECURITY.md index 156954ce02352e..43ab4454c456f0 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,8 +13,9 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through ## Supported Versions -| Version | Supported | -| ------- | --------- | -| 4.2.x | Yes | -| 4.1.x | Yes | -| < 4.1 | No | +| Version | Supported | +| ------- | ---------------- | +| 4.3.x | Yes | +| 4.2.x | Yes | +| 4.1.x | Until 2025-04-08 | +| < 4.1 | No | 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/admin/announcements_controller.rb b/app/controllers/admin/announcements_controller.rb index 8f9708183a81cf..12230a6506d929 100644 --- a/app/controllers/admin/announcements_controller.rb +++ b/app/controllers/admin/announcements_controller.rb @@ -6,6 +6,7 @@ class Admin::AnnouncementsController < Admin::BaseController def index authorize :announcement, :index? + @published_announcements_count = Announcement.published.async_count end def new diff --git a/app/controllers/admin/disputes/appeals_controller.rb b/app/controllers/admin/disputes/appeals_controller.rb index 5e342409b021cb..0c41553676735a 100644 --- a/app/controllers/admin/disputes/appeals_controller.rb +++ b/app/controllers/admin/disputes/appeals_controller.rb @@ -6,6 +6,7 @@ class Admin::Disputes::AppealsController < Admin::BaseController def index authorize :appeal, :index? + @pending_appeals_count = Appeal.pending.async_count @appeals = filtered_appeals.page(params[:page]) end diff --git a/app/controllers/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/admin/trends/links/preview_card_providers_controller.rb index 768b79f8dbce45..5e4b4084f808d2 100644 --- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb +++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb @@ -4,6 +4,7 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll def index authorize :preview_card_provider, :review? + @pending_preview_card_providers_count = PreviewCardProvider.unreviewed.async_count @preview_card_providers = filtered_preview_card_providers.page(params[:page]) @form = Trends::PreviewCardProviderBatch.new end diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb index f5946448ae1f71..fcd23fbf66b676 100644 --- a/app/controllers/admin/trends/tags_controller.rb +++ b/app/controllers/admin/trends/tags_controller.rb @@ -4,6 +4,7 @@ class Admin::Trends::TagsController < Admin::BaseController def index authorize :tag, :review? + @pending_tags_count = Tag.pending_review.async_count @tags = filtered_tags.page(params[:page]) @form = Trends::TagBatch.new end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 84b604b305e7a7..28acaeea051834 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -16,6 +16,7 @@ class Api::V1::AccountsController < Api::BaseController before_action :check_account_confirmation, except: [:index, :create] before_action :check_enabled_registrations, only: [:create] before_action :check_accounts_limit, only: [:index] + before_action :check_following_self, only: [:follow] skip_before_action :require_authenticated_user!, only: :create @@ -101,6 +102,10 @@ def check_accounts_limit raise(Mastodon::ValidationError) if account_ids.size > DEFAULT_ACCOUNTS_LIMIT end + def check_following_self + render json: { error: I18n.t('accounts.self_follow_error') }, status: 403 if current_user.account.id == @account.id + end + def relationships(**options) AccountRelationshipsPresenter.new([@account], current_user.account_id, **options) 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/api/v1/notifications/requests_controller.rb b/app/controllers/api/v1/notifications/requests_controller.rb index 36ee073b9cef27..3c90f13ce24ec9 100644 --- a/app/controllers/api/v1/notifications/requests_controller.rb +++ b/app/controllers/api/v1/notifications/requests_controller.rb @@ -52,7 +52,7 @@ def dismiss_bulk private def load_requests - requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( + requests = NotificationRequest.where(account: current_account).without_suspended.includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), params_slice(:max_id, :since_id, :min_id) ) diff --git a/app/controllers/api/v1/statuses/translations_controller.rb b/app/controllers/api/v1/statuses/translations_controller.rb index 8cf495f78ac95d..bd5cd9bb07febc 100644 --- a/app/controllers/api/v1/statuses/translations_controller.rb +++ b/app/controllers/api/v1/statuses/translations_controller.rb @@ -23,6 +23,6 @@ def create private def set_translation - @translation = TranslateStatusService.new.call(@status, content_locale) + @translation = TranslateStatusService.new.call(@status, I18n.locale.to_s) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9ec50926671eaf..9ed35c523faee7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests - rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error + rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error) rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable rescue_from Seahorse::Client::NetworkingError do |e| diff --git a/app/controllers/concerns/api/error_handling.rb b/app/controllers/concerns/api/error_handling.rb index ad559fe2d713e1..9ce4795b02bcac 100644 --- a/app/controllers/concerns/api/error_handling.rb +++ b/app/controllers/concerns/api/error_handling.rb @@ -20,7 +20,7 @@ module Api::ErrorHandling render json: { error: 'Record not found' }, status: 404 end - rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do + rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::UnexpectedResponseError) do render json: { error: 'Remote data could not be fetched' }, status: 503 end diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 68f09ee0238eb2..4ae63632c0cf0d 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -80,7 +80,7 @@ def signed_request_actor fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature'] rescue SignatureVerificationError => e fail_with! e.message - rescue HTTP::Error, OpenSSL::SSL::SSLError => e + rescue *Mastodon::HTTP_CONNECTION_ERRORS => e fail_with! "Failed to fetch remote data: #{e.message}" rescue Mastodon::UnexpectedResponseError fail_with! 'Failed to fetch remote data (got unexpected reply from server)' diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index d43a658421f6b3..3447bb0d5cc5d9 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -13,7 +13,7 @@ module WebAppControllerConcern policy = ContentSecurityPolicy.new if policy.sso_host.present? - p.form_action policy.sso_host + p.form_action policy.sso_host, -> { "https://#{request.host}/auth/auth/" } else p.form_action :none end @@ -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/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb index c4230d62c38479..f68d85e44e2fdd 100644 --- a/app/controllers/media_proxy_controller.rb +++ b/app/controllers/media_proxy_controller.rb @@ -13,7 +13,7 @@ class MediaProxyController < ApplicationController rescue_from ActiveRecord::RecordInvalid, with: :not_found rescue_from Mastodon::UnexpectedResponseError, with: :not_found rescue_from Mastodon::NotPermittedError, with: :not_found - rescue_from HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, with: :internal_server_error + rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error) def show with_redis_lock("media_download:#{params[:id]}") do diff --git a/app/controllers/settings/exports_controller.rb b/app/controllers/settings/exports_controller.rb index 076ed5dadb178f..263d20eaeae683 100644 --- a/app/controllers/settings/exports_controller.rb +++ b/app/controllers/settings/exports_controller.rb @@ -9,7 +9,7 @@ class Settings::ExportsController < Settings::BaseController skip_before_action :require_functional! def show - @export = Export.new(current_account) + @export_summary = ExportSummary.new(preloaded_account) @backups = current_user.backups end @@ -25,4 +25,15 @@ def create redirect_to settings_export_path end + + private + + def preloaded_account + current_account.tap do |account| + ActiveRecord::Associations::Preloader.new( + records: [account], + associations: :account_stat + ).call + end + end end diff --git a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb index 0bff01ec2793a4..ca8d46afe48199 100644 --- a/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb +++ b/app/controllers/settings/two_factor_authentication/otp_authentication_controller.rb @@ -15,7 +15,7 @@ def show end def create - session[:new_otp_secret] = User.generate_otp_secret(32) + session[:new_otp_secret] = User.generate_otp_secret redirect_to new_settings_two_factor_authentication_confirmation_path end diff --git a/app/controllers/well_known/host_meta_controller.rb b/app/controllers/well_known/host_meta_controller.rb index 201da9fbc3b440..6dee587baf4fc8 100644 --- a/app/controllers/well_known/host_meta_controller.rb +++ b/app/controllers/well_known/host_meta_controller.rb @@ -7,7 +7,23 @@ class HostMetaController < ActionController::Base # rubocop:disable Rails/Applic def show @webfinger_template = "#{webfinger_url}?resource={uri}" expires_in 3.days, public: true - render content_type: 'application/xrd+xml', formats: [:xml] + + respond_to do |format| + format.any do + render content_type: 'application/xrd+xml', formats: [:xml] + end + + format.json do + render json: { + links: [ + { + rel: 'lrdd', + template: @webfinger_template, + }, + ], + } + end + end end end end diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index e8d56341262cc5..51e28d8b4e9234 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -35,4 +35,11 @@ def log_target(log) end end end + + def sorted_action_log_types + Admin::ActionLogFilter::ACTION_TYPE_MAP + .keys + .map { |key| [I18n.t("admin.action_logs.action_types.#{key}"), key] } + .sort_by(&:first) + end end diff --git a/app/helpers/admin/dashboard_helper.rb b/app/helpers/admin/dashboard_helper.rb index 6096ff1381e7bb..f87fdad70832de 100644 --- a/app/helpers/admin/dashboard_helper.rb +++ b/app/helpers/admin/dashboard_helper.rb @@ -18,6 +18,11 @@ def relevant_account_ip(account, ip_query) end end + def date_range(range) + [l(range.first), l(range.last)] + .join(' - ') + end + def relevant_account_timestamp(account) timestamp, exact = if account.user_current_sign_in_at && account.user_current_sign_in_at < 24.hours.ago [account.user_current_sign_in_at, true] @@ -25,6 +30,8 @@ def relevant_account_timestamp(account) [account.user_current_sign_in_at, false] elsif account.user_pending? [account.user_created_at, true] + elsif account.suspended_at.present? && account.local? && account.user.nil? + [account.suspended_at, true] elsif account.last_status_at.present? [account.last_status_at, true] else diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a7ae4d6a0447e2..7665c0011a24d6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,12 +1,6 @@ # frozen_string_literal: true module ApplicationHelper - DANGEROUS_SCOPES = %w( - read - write - follow - ).freeze - RTL_LOCALES = %i( ar ckb @@ -95,8 +89,11 @@ def title Rails.env.production? ? site_title : "#{site_title} (Dev)" end - def class_for_scope(scope) - 'scope-danger' if DANGEROUS_SCOPES.include?(scope.to_s) + def label_for_scope(scope) + safe_join [ + tag.samp(scope, class: { 'scope-danger' => SessionActivation::DEFAULT_SCOPES.include?(scope.to_s) }), + tag.span(t("doorkeeper.scopes.#{scope}"), class: :hint), + ] end def can?(action, record) @@ -244,6 +241,15 @@ def mascot_url full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg')) end + def copyable_input(options = {}) + tag.input(type: :text, maxlength: 999, spellcheck: false, readonly: true, **options) + end + + def recent_tag_usage(tag) + people = tag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts + I18n.t 'user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(people), count: people + end + # glitch-soc addition to handle the multiple flavors def preload_locale_pack supported_locales = Themes.instance.flavour(current_flavour)['locales'] diff --git a/app/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index f0d583bc541ec7..bc3d07a6bb01af 100644 --- a/app/helpers/formatting_helper.rb +++ b/app/helpers/formatting_helper.rb @@ -1,6 +1,14 @@ # frozen_string_literal: true module FormattingHelper + SYNDICATED_EMOJI_STYLES = <<~CSS.squish + height: 1.1em; + margin: -.2ex .15em .2ex; + object-fit: contain; + vertical-align: middle; + width: 1.1em; + CSS + def html_aware_format(text, local, options = {}) HtmlAwareFormatter.new(text, local, options).to_s end @@ -23,33 +31,10 @@ def status_content_format(status) end def rss_status_content_format(status) - html = status_content_format(status) - - before_html = if status.spoiler_text? - tag.p do - tag.strong do - I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) - end - - status.spoiler_text - end + tag.hr - end - - after_html = if status.preloadable_poll - tag.p do - safe_join( - status.preloadable_poll.options.map do |o| - tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', o, disabled: true) - end, - tag.br - ) - end - end - prerender_custom_emojis( - safe_join([before_html, html, after_html]), + wrapped_status_content_format(status), status.emojis, - style: 'width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: middle; margin: -.2ex .15em .2ex' + style: SYNDICATED_EMOJI_STYLES ).to_str end @@ -64,4 +49,47 @@ def account_field_value_format(field, with_rel_me: true) html_aware_format(field.value, field.account.local?, with_rel_me: with_rel_me, with_domains: true, multiline: false) end end + + private + + def wrapped_status_content_format(status) + safe_join [ + rss_content_preroll(status), + status_content_format(status), + rss_content_postroll(status), + ] + end + + def rss_content_preroll(status) + if status.spoiler_text? + safe_join [ + tag.p { spoiler_with_warning(status) }, + tag.hr, + ] + end + end + + def spoiler_with_warning(status) + safe_join [ + tag.strong { I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) }, + status.spoiler_text, + ] + end + + def rss_content_postroll(status) + if status.preloadable_poll + tag.p do + poll_option_tags(status) + end + end + end + + def poll_option_tags(status) + safe_join( + status.preloadable_poll.options.map do |option| + tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', option, disabled: true) + end, + tag.br + ) + end end diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb index b6c09b7314722e..394202e39ad78a 100644 --- a/app/helpers/languages_helper.rb +++ b/app/helpers/languages_helper.rb @@ -193,6 +193,7 @@ module LanguagesHelper ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze, cnr: ['Montenegrin', 'crnogorski'].freeze, csb: ['Kashubian', 'Kaszëbsczi'].freeze, + gsw: ['Swiss German', 'Schwiizertütsch'].freeze, jbo: ['Lojban', 'la .lojban.'].freeze, kab: ['Kabyle', 'Taqbaylit'].freeze, ldn: ['Láadan', 'Láadan'].freeze, 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/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index bba6d64a4783a3..9bbb03fd820230 100644 --- a/app/helpers/statuses_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -12,7 +12,7 @@ module StatusesHelper }.freeze def nothing_here(extra_classes = '') - content_tag(:div, class: "nothing-here #{extra_classes}") do + tag.div(class: ['nothing-here', extra_classes]) do t('accounts.nothing_here') end end diff --git a/app/helpers/webfinger_helper.rb b/app/helpers/webfinger_helper.rb deleted file mode 100644 index 482f4e19eabef0..00000000000000 --- a/app/helpers/webfinger_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -module WebfingerHelper - def webfinger!(uri) - Webfinger.new(uri).perform - end -end 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/markers.ts b/app/javascript/flavours/glitch/actions/markers.ts index 37067dbcf7b56c..ea325109c5ea3b 100644 --- a/app/javascript/flavours/glitch/actions/markers.ts +++ b/app/javascript/flavours/glitch/actions/markers.ts @@ -37,8 +37,7 @@ export const synchronouslySubmitMarkers = createAppAsyncThunk( }); return; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - } else if ('navigator' && 'sendBeacon' in navigator) { + } else if ('sendBeacon' in navigator) { // Failing that, we can use sendBeacon, but we have to encode the data as // FormData for DoorKeeper to recognize the token. const formData = new FormData(); diff --git a/app/javascript/flavours/glitch/actions/notification_groups.ts b/app/javascript/flavours/glitch/actions/notification_groups.ts index 9b5a1ffeef0a1f..f85dfac9335e72 100644 --- a/app/javascript/flavours/glitch/actions/notification_groups.ts +++ b/app/javascript/flavours/glitch/actions/notification_groups.ts @@ -8,6 +8,7 @@ import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts'; import type { ApiNotificationGroupJSON, ApiNotificationJSON, + NotificationType, } from 'flavours/glitch/api_types/notifications'; import { allNotificationTypes } from 'flavours/glitch/api_types/notifications'; import type { ApiStatusJSON } from 'flavours/glitch/api_types/statuses'; @@ -15,6 +16,7 @@ import { usePendingItems } from 'flavours/glitch/initial_state'; import type { NotificationGap } from 'flavours/glitch/reducers/notification_groups'; import { selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsGroupFollows, selectSettingsNotificationsQuickFilterActive, selectSettingsNotificationsShows, } from 'flavours/glitch/selectors/settings'; @@ -68,10 +70,21 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } +function selectNotificationGroupedTypes(state: RootState) { + const types: NotificationType[] = ['favourite', 'reblog']; + + if (selectSettingsNotificationsGroupFollows(state)) types.push('follow'); + + return types; +} + export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => - apiFetchNotificationGroups({ exclude_types: getExcludedTypes(getState()) }), + apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), + exclude_types: getExcludedTypes(getState()), + }), ({ notifications, accounts, statuses }, { dispatch }) => { dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedStatuses(statuses)); @@ -93,6 +106,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -109,6 +123,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { return apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), max_id: undefined, exclude_types: getExcludedTypes(getState()), // In slow mode, we don't want to include notifications that duplicate the already-displayed ones @@ -157,7 +172,10 @@ export const processNewNotificationForGroups = createAppAsyncThunk( dispatchAssociatedRecords(dispatch, [notification]); - return notification; + return { + notification, + groupedTypes: selectNotificationGroupedTypes(state), + }; }, ); 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/actions/streaming.js b/app/javascript/flavours/glitch/actions/streaming.js index 7948984fba59b7..fa7af7055e6180 100644 --- a/app/javascript/flavours/glitch/actions/streaming.js +++ b/app/javascript/flavours/glitch/actions/streaming.js @@ -106,12 +106,13 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti dispatch(processNewNotificationForGroups(notificationJSON)); break; } - case 'notifications_merged': + case 'notifications_merged': { const state = getState(); if (state.notifications.top || !state.notifications.mounted) dispatch(expandNotifications({ forceLoad: true, maxId: undefined })); dispatch(refreshStaleNotificationGroups()); break; + } case 'conversation': // @ts-expect-error dispatch(updateConversations(JSON.parse(data.payload))); 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/api_types/accounts.ts b/app/javascript/flavours/glitch/api_types/accounts.ts index d6dada067b6678..d028104ef86760 100644 --- a/app/javascript/flavours/glitch/api_types/accounts.ts +++ b/app/javascript/flavours/glitch/api_types/accounts.ts @@ -13,7 +13,7 @@ export interface ApiAccountRoleJSON { } // See app/serializers/rest/account_serializer.rb -export interface ApiAccountJSON { +export interface BaseApiAccountJSON { acct: string; avatar: string; avatar_static: string; @@ -46,3 +46,12 @@ export interface ApiAccountJSON { hide_collections: boolean; account_css?: string; } + +// See app/serializers/rest/muted_account_serializer.rb +export interface ApiMutedAccountJSON extends BaseApiAccountJSON { + mute_expires_at?: string | null; +} + +// For now, we have the same type representing both `Account` and `MutedAccount` +// objects, but we should refactor this in the future. +export type ApiAccountJSON = ApiMutedAccountJSON; 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/avatar.tsx b/app/javascript/flavours/glitch/components/avatar.tsx index c8bf388d268d9b..bb146f0edbd0f7 100644 --- a/app/javascript/flavours/glitch/components/avatar.tsx +++ b/app/javascript/flavours/glitch/components/avatar.tsx @@ -1,10 +1,11 @@ +import { useState, useCallback } from 'react'; + import classNames from 'classnames'; +import { useHovering } from 'flavours/glitch/hooks/useHovering'; +import { autoPlayGif } from 'flavours/glitch/initial_state'; import type { Account } from 'flavours/glitch/models/account'; -import { useHovering } from '../hooks/useHovering'; -import { autoPlayGif } from '../initial_state'; - interface Props { account: Account | undefined; // FIXME: remove `undefined` once we know for sure its always there size: number; @@ -25,6 +26,8 @@ export const Avatar: React.FC = ({ counterBorderColor, }) => { const { hovering, handleMouseEnter, handleMouseLeave } = useHovering(animate); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); const style = { ...styleFromParent, @@ -37,17 +40,29 @@ export const Avatar: React.FC = ({ ? account?.get('avatar') : account?.get('avatar_static'); + const handleLoad = useCallback(() => { + setLoading(false); + }, [setLoading]); + + const handleError = useCallback(() => { + setError(true); + }, [setError]); + return (
- {src && } + {src && !error && ( + + )} + {counter && (
, '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..f2f8b21e3b5389 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 @@ -190,7 +198,7 @@ class Item extends PureComponent { {visible && thumbnail} - {badges && ( + {visible && badges && (
{badges}
@@ -348,14 +356,14 @@ class MediaGallery extends PureComponent { return (
+ {children} + {(!visible || uncached) && (
{spoilerButton}
)} - {children} - {(visible && !uncached) && (
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 2eff30d76656c0..d31a2be790f430 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -649,6 +649,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'); @@ -704,27 +725,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..d276affcef6636 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.jsx +++ b/app/javascript/flavours/glitch/components/status_action_bar.jsx @@ -233,7 +233,7 @@ class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.share), action: this.handleShareClick }); } - if (publicStatus && (signedIn || !isRemote)) { + if (publicStatus && !isRemote) { menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); } @@ -315,36 +315,48 @@ class StatusActionBar extends ImmutablePureComponent { } const filterButton = this.props.onFilter && ( - +
+ +
); return (
- - - - +
+ +
+
+ +
+
+ +
+
+ +
{filterButton} - +
+ +
diff --git a/app/javascript/flavours/glitch/components/status_content.jsx b/app/javascript/flavours/glitch/components/status_content.jsx index 23ace5d8215b3e..7dd5dba69be0c9 100644 --- a/app/javascript/flavours/glitch/components/status_content.jsx +++ b/app/javascript/flavours/glitch/components/status_content.jsx @@ -40,7 +40,7 @@ const isLinkMisleading = (link) => { case Node.TEXT_NODE: linkTextParts.push(node.textContent); break; - case Node.ELEMENT_NODE: + case Node.ELEMENT_NODE: { if (node.classList.contains('invisible')) return; const children = node.childNodes; for (let i = 0; i < children.length; i++) { @@ -48,6 +48,7 @@ const isLinkMisleading = (link) => { } break; } + } }; walk(link); 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/community_timeline/components/column_settings.jsx b/app/javascript/flavours/glitch/features/community_timeline/components/column_settings.jsx index a13081e82b35d9..b6200106dd9beb 100644 --- a/app/javascript/flavours/glitch/features/community_timeline/components/column_settings.jsx +++ b/app/javascript/flavours/glitch/features/community_timeline/components/column_settings.jsx @@ -27,15 +27,19 @@ class ColumnSettings extends PureComponent { return (
-
- } /> -
- - - -
- -
+
+
+ } /> +
+
+ +
+ + +
+ +
+
); } diff --git a/app/javascript/flavours/glitch/features/compose/components/poll_form.jsx b/app/javascript/flavours/glitch/features/compose/components/poll_form.jsx index 361522d7b48d57..49d66dfbb40b1c 100644 --- a/app/javascript/flavours/glitch/features/compose/components/poll_form.jsx +++ b/app/javascript/flavours/glitch/features/compose/components/poll_form.jsx @@ -26,7 +26,7 @@ const messages = defineMessages({ minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' }, hours: { id: 'intervals.full.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}}' }, days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' }, - singleChoice: { id: 'compose_form.poll.single', defaultMessage: 'Pick one' }, + singleChoice: { id: 'compose_form.poll.single', defaultMessage: 'Single choice' }, multipleChoice: { id: 'compose_form.poll.multiple', defaultMessage: 'Multiple choice' }, }); 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/home_timeline/components/inline_follow_suggestions.jsx b/app/javascript/flavours/glitch/features/home_timeline/components/inline_follow_suggestions.jsx index 4e727a63edf843..9734763138a8e8 100644 --- a/app/javascript/flavours/glitch/features/home_timeline/components/inline_follow_suggestions.jsx +++ b/app/javascript/flavours/glitch/features/home_timeline/components/inline_follow_suggestions.jsx @@ -129,8 +129,13 @@ export const InlineFollowSuggestions = ({ hidden }) => { return; } - setCanScrollLeft(bodyRef.current.scrollLeft > 0); - setCanScrollRight((bodyRef.current.scrollLeft + bodyRef.current.clientWidth) < bodyRef.current.scrollWidth); + if (getComputedStyle(bodyRef.current).direction === 'rtl') { + setCanScrollLeft((bodyRef.current.clientWidth - bodyRef.current.scrollLeft) < bodyRef.current.scrollWidth); + setCanScrollRight(bodyRef.current.scrollLeft < 0); + } else { + setCanScrollLeft(bodyRef.current.scrollLeft > 0); + setCanScrollRight((bodyRef.current.scrollLeft + bodyRef.current.clientWidth) < bodyRef.current.scrollWidth); + } }, [setCanScrollRight, setCanScrollLeft, bodyRef, suggestions]); const handleLeftNav = useCallback(() => { @@ -146,8 +151,13 @@ export const InlineFollowSuggestions = ({ hidden }) => { return; } - setCanScrollLeft(bodyRef.current.scrollLeft > 0); - setCanScrollRight((bodyRef.current.scrollLeft + bodyRef.current.clientWidth) < bodyRef.current.scrollWidth); + if (getComputedStyle(bodyRef.current).direction === 'rtl') { + setCanScrollLeft((bodyRef.current.clientWidth - bodyRef.current.scrollLeft) < bodyRef.current.scrollWidth); + setCanScrollRight(bodyRef.current.scrollLeft < 0); + } else { + setCanScrollLeft(bodyRef.current.scrollLeft > 0); + setCanScrollRight((bodyRef.current.scrollLeft + bodyRef.current.clientWidth) < bodyRef.current.scrollWidth); + } }, [setCanScrollRight, setCanScrollLeft, bodyRef]); const handleDismiss = useCallback(() => { diff --git a/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx b/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx index ea57f2999b455e..81a9d9e1d1f4ed 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx +++ b/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx @@ -40,6 +40,7 @@ class ColumnSettings extends PureComponent { const alertStr = ; const showStr = ; const soundStr = ; + const groupStr = ; const showPushSettings = pushSettings.get('browserSupport') && pushSettings.get('isSubscribed'); const pushStr = showPushSettings && ; @@ -96,6 +97,10 @@ class ColumnSettings extends PureComponent {
+ +
+ +
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/notifications/containers/column_settings_container.js b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js index 3c4c4b30ca1ffa..3e0da03e33f40f 100644 --- a/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js +++ b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js @@ -56,11 +56,12 @@ const mapDispatchToProps = (dispatch) => ({ } else { dispatch(changeSetting(['notifications', ...path], checked)); } - } else if(path[0] === 'groupingBeta') { - dispatch(changeSetting(['notifications', ...path], checked)); - dispatch(initializeNotifications()); } else { dispatch(changeSetting(['notifications', ...path], checked)); + + if(path[0] === 'group' && path[1] === 'follow') { + dispatch(initializeNotifications()); + } } }, diff --git a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow.tsx index f154e801fb9017..cabb671815a99b 100644 --- a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow.tsx +++ b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_follow.tsx @@ -1,16 +1,19 @@ import { FormattedMessage } from 'react-intl'; +import { Link } from 'react-router-dom'; + import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; import { FollowersCounter } from 'flavours/glitch/components/counters'; import { FollowButton } from 'flavours/glitch/components/follow_button'; import { ShortNumber } from 'flavours/glitch/components/short_number'; +import { me } from 'flavours/glitch/initial_state'; import type { NotificationGroupFollow } from 'flavours/glitch/models/notification_group'; import { useAppSelector } from 'flavours/glitch/store'; import type { LabelRenderer } from './notification_group_with_status'; import { NotificationGroupWithStatus } from './notification_group_with_status'; -const labelRenderer: LabelRenderer = (displayedName, total) => { +const labelRenderer: LabelRenderer = (displayedName, total, seeMoreHref) => { if (total === 1) return ( { return ( + seeMoreHref ? {chunks} : chunks, }} /> ); @@ -46,6 +51,10 @@ export const NotificationFollow: React.FC<{ notification: NotificationGroupFollow; unread: boolean; }> = ({ notification, unread }) => { + const username = useAppSelector( + (state) => state.accounts.getIn([me, 'username']) as string, + ); + let actions: JSX.Element | undefined; let additionalContent: JSX.Element | undefined; @@ -68,6 +77,7 @@ export const NotificationFollow: React.FC<{ timestamp={notification.latest_page_notification_at} count={notification.notifications_count} labelRenderer={labelRenderer} + labelSeeMoreHref={`/@${username}/followers`} unread={unread} actions={actions} additionalContent={additionalContent} diff --git a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_with_status.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_with_status.tsx index 941b1254f7cd02..4f45189e59cefa 100644 --- a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_with_status.tsx +++ b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_with_status.tsx @@ -16,6 +16,7 @@ import { import type { IconProp } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon'; import Status from 'flavours/glitch/containers/status_container'; +import { getStatusHidden } from 'flavours/glitch/selectors/filters'; import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; import { DisplayedName } from './displayed_name'; @@ -51,6 +52,12 @@ export const NotificationWithStatus: React.FC<{ (state) => state.statuses.getIn([statusId, 'visibility']) === 'direct', ); + const isFiltered = useAppSelector( + (state) => + statusId && + getStatusHidden(state, { id: statusId, contextType: 'notifications' }), + ); + const handlers = useMemo( () => ({ open: () => { @@ -77,7 +84,7 @@ export const NotificationWithStatus: React.FC<{ [dispatch, statusId], ); - if (!statusId) return null; + if (!statusId || isFiltered) return null; return ( diff --git a/app/javascript/flavours/glitch/features/notifications_v2/filter_bar.tsx b/app/javascript/flavours/glitch/features/notifications_v2/filter_bar.tsx index 1299796662b1d6..d9a6b4d07fb57a 100644 --- a/app/javascript/flavours/glitch/features/notifications_v2/filter_bar.tsx +++ b/app/javascript/flavours/glitch/features/notifications_v2/filter_bar.tsx @@ -14,6 +14,7 @@ import { Icon } from 'flavours/glitch/components/icon'; import { selectSettingsNotificationsQuickFilterActive, selectSettingsNotificationsQuickFilterAdvanced, + selectSettingsNotificationsQuickFilterShow, } from 'flavours/glitch/selectors/settings'; import { useAppDispatch, useAppSelector } from 'flavours/glitch/store'; @@ -65,6 +66,11 @@ export const FilterBar: React.FC = () => { const advancedMode = useAppSelector( selectSettingsNotificationsQuickFilterAdvanced, ); + const useFilterBar = useAppSelector( + selectSettingsNotificationsQuickFilterShow, + ); + + if (!useFilterBar) return null; if (advancedMode) return ( diff --git a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx index b57f882a74fe76..2ddbed77ffd20b 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx @@ -14,6 +14,8 @@ import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import StarIcon from '@/material-icons/400-24px/star.svg?react'; +import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react'; +import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react'; import { replyCompose } from 'flavours/glitch/actions/compose'; import { toggleReblog, toggleFavourite } from 'flavours/glitch/actions/interactions'; import { openModal } from 'flavours/glitch/actions/modal'; @@ -161,16 +163,20 @@ class Footer extends ImmutablePureComponent { replyTitle = intl.formatMessage(messages.replyAll); } - let reblogTitle = ''; + let reblogTitle, reblogIconComponent; if (status.get('reblogged')) { reblogTitle = intl.formatMessage(messages.cancel_reblog_private); + reblogIconComponent = publicStatus ? RepeatIcon : RepeatPrivateIcon; } else if (publicStatus) { reblogTitle = intl.formatMessage(messages.reblog); + reblogIconComponent = RepeatIcon; } else if (reblogPrivate) { reblogTitle = intl.formatMessage(messages.reblog_private); + reblogIconComponent = RepeatPrivateIcon; } else { reblogTitle = intl.formatMessage(messages.cannot_reblog); + reblogIconComponent = RepeatDisabledIcon; } let replyButton = null; @@ -201,7 +207,7 @@ class Footer extends ImmutablePureComponent { return (
{replyButton} - + {withOpenButton && }
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..d1d955395f4216 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..b61e21d9f94b06 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); @@ -15,7 +15,7 @@ const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text if (href) { return ( - + {active ? activeIconElement : iconElement} {text} {badgeElement} @@ -23,7 +23,7 @@ const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text ); } else if (to) { return ( - + {active ? activeIconElement : iconElement} {text} {badgeElement} @@ -37,7 +37,7 @@ const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text }; return ( // eslint-disable-next-line jsx-a11y/anchor-is-valid -- intentional to have the same look and feel as other menu items - + {iconElement} {text} {badgeElement} @@ -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/mute_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx index e208f12173e093..2e944151bf234e 100644 --- a/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx @@ -116,6 +116,7 @@ export const MuteModal = ({ accountId, acct }) => {
+ 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 = (); + 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..1ef29f8db20eda 100644 --- a/app/javascript/flavours/glitch/features/ui/index.jsx +++ b/app/javascript/flavours/glitch/features/ui/index.jsx @@ -21,6 +21,7 @@ import { Permalink } from 'flavours/glitch/components/permalink'; import { PictureInPicture } from 'flavours/glitch/features/picture_in_picture'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; import { layoutFromWindow } from 'flavours/glitch/is_mobile'; +import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications'; import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router'; import { uploadCompose, resetCompose, changeComposeSpoilerness } from '../../actions/compose'; @@ -90,7 +91,7 @@ const mapStateToProps = state => ({ hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0, canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4, isWide: state.getIn(['local_settings', 'stretch']), - unreadNotifications: state.getIn(['notifications', 'unread']), + unreadNotifications: selectUnreadNotificationGroupsCount(state), showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']), hicolorPrivacyIcons: state.getIn(['local_settings', 'hicolor_privacy_icons']), moved: state.getIn(['accounts', me, 'moved']) && state.getIn(['accounts', state.getIn(['accounts', me, 'moved'])]), @@ -196,7 +197,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/account.ts b/app/javascript/flavours/glitch/models/account.ts index eaad1fd3d9a9fb..34007c9a1c0b86 100644 --- a/app/javascript/flavours/glitch/models/account.ts +++ b/app/javascript/flavours/glitch/models/account.ts @@ -95,6 +95,9 @@ export const accountDefaultValues: AccountShape = { limited: false, moved: null, hide_collections: false, + // This comes from `ApiMutedAccountJSON`, but we should eventually + // store that in a different object. + mute_expires_at: null, account_css: '', }; 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/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index 361b1fc081f7d0..52b08666a6495a 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -527,12 +527,12 @@ export default function compose(state = initialState, action) { .set('isUploadingThumbnail', false) .update('media_attachments', list => list.map(item => { if (item.get('id') === action.media.id) { - return fromJS(action.media); + return fromJS(action.media).set('unattached', item.get('unattached')); } return item; })); - case INIT_MEDIA_EDIT_MODAL: + case INIT_MEDIA_EDIT_MODAL: { const media = state.get('media_attachments').find(item => item.get('id') === action.id); return state.set('media_modal', ImmutableMap({ id: action.id, @@ -541,6 +541,7 @@ export default function compose(state = initialState, action) { focusY: media.getIn(['meta', 'focus', 'y'], 0), dirty: false, })); + } case COMPOSE_CHANGE_MEDIA_DESCRIPTION: return state.setIn(['media_modal', 'description'], action.description).setIn(['media_modal', 'dirty'], true); case COMPOSE_CHANGE_MEDIA_FOCUS: @@ -597,7 +598,7 @@ export default function compose(state = initialState, action) { })); case COMPOSE_DOODLE_SET: return state.mergeIn(['doodle'], action.options); - case REDRAFT: + case REDRAFT: { const do_not_federate = !!action.status.get('local_only'); let text = action.raw_text || unescapeHTML(expandMentions(action.status)); if (do_not_federate) text = text.replace(/ ?👁\ufe0f?\u200b?$/, ''); @@ -638,6 +639,7 @@ export default function compose(state = initialState, action) { })); } }); + } case COMPOSE_SET_STATUS: return state.withMutations(map => { map.set('id', action.status.get('id')); diff --git a/app/javascript/flavours/glitch/reducers/notification_groups.ts b/app/javascript/flavours/glitch/reducers/notification_groups.ts index 30f7b58737124c..09c0c5c3ee3e28 100644 --- a/app/javascript/flavours/glitch/reducers/notification_groups.ts +++ b/app/javascript/flavours/glitch/reducers/notification_groups.ts @@ -29,6 +29,7 @@ import { import type { ApiNotificationJSON, ApiNotificationGroupJSON, + NotificationType, } from 'flavours/glitch/api_types/notifications'; import { compareId } from 'flavours/glitch/compare_id'; import { usePendingItems } from 'flavours/glitch/initial_state'; @@ -204,7 +205,15 @@ function mergeGapsAround( function processNewNotification( groups: NotificationGroupsState['groups'], notification: ApiNotificationJSON, + groupedTypes: NotificationType[], ) { + if (!groupedTypes.includes(notification.type)) { + notification = { + ...notification, + group_key: `ungrouped-${notification.id}`, + }; + } + const existingGroupIndex = groups.findIndex( (group) => group.type !== 'gap' && group.group_key === notification.group_key, @@ -242,7 +251,7 @@ function processNewNotification( groups.unshift(existingGroup); } } else { - // Create a new group + // We have not found an existing group, create a new one groups.unshift(createNotificationGroupFromNotificationJSON(notification)); } } @@ -468,11 +477,13 @@ export const notificationGroupsReducer = createReducer( trimNotifications(state); }) .addCase(processNewNotificationForGroups.fulfilled, (state, action) => { - const notification = action.payload; - if (notification) { + if (action.payload) { + const { notification, groupedTypes } = action.payload; + processNewNotification( usePendingItems ? state.pendingGroups : state.groups, notification, + groupedTypes, ); updateLastReadId(state); trimNotifications(state); @@ -551,7 +562,10 @@ export const notificationGroupsReducer = createReducer( compareId(state.lastReadId, mostRecentGroup.page_max_id) < 0 ) state.lastReadId = mostRecentGroup.page_max_id; - commitLastReadId(state); + + // We don't call `commitLastReadId`, because that is conditional + // and we want to unconditionally update the state instead. + state.readMarkerId = state.lastReadId; }) .addCase(fetchMarkers.fulfilled, (state, action) => { if ( 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/reducers/notifications.js b/app/javascript/flavours/glitch/reducers/notifications.js index b9773a0da65f5c..8453dd70385423 100644 --- a/app/javascript/flavours/glitch/reducers/notifications.js +++ b/app/javascript/flavours/glitch/reducers/notifications.js @@ -369,9 +369,10 @@ export default function notifications(state = initialState, action) { } return markAllForDelete(st, action.yes); - case NOTIFICATIONS_MARK_AS_READ: + case NOTIFICATIONS_MARK_AS_READ: { const lastNotification = state.get('items').find(item => item !== null); return lastNotification ? recountUnread(state, lastNotification.get('id')) : state; + } default: return state; diff --git a/app/javascript/flavours/glitch/reducers/search.js b/app/javascript/flavours/glitch/reducers/search.js index 7828d49eeedd9a..7de1c65c07a295 100644 --- a/app/javascript/flavours/glitch/reducers/search.js +++ b/app/javascript/flavours/glitch/reducers/search.js @@ -72,9 +72,10 @@ export default function search(state = initialState, action) { }); case SEARCH_EXPAND_REQUEST: return state.set('type', action.searchType).set('isLoading', true); - case SEARCH_EXPAND_SUCCESS: + case SEARCH_EXPAND_SUCCESS: { const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id); return state.updateIn(['results', action.searchType], list => list.union(results)).set('isLoading', false); + } case SEARCH_HISTORY_UPDATE: return state.set('recent', ImmutableOrderedSet(fromJS(action.recent))); default: diff --git a/app/javascript/flavours/glitch/reducers/settings.js b/app/javascript/flavours/glitch/reducers/settings.js index 660b5f11ca4b93..bfea4abe44b9b0 100644 --- a/app/javascript/flavours/glitch/reducers/settings.js +++ b/app/javascript/flavours/glitch/reducers/settings.js @@ -79,6 +79,10 @@ const initialState = ImmutableMap({ 'admin.sign_up': true, 'admin.report': true, }), + + group: ImmutableMap({ + follow: true + }), }), firehose: ImmutableMap({ diff --git a/app/javascript/flavours/glitch/selectors/filters.ts b/app/javascript/flavours/glitch/selectors/filters.ts new file mode 100644 index 00000000000000..5d7bfcbdc7a075 --- /dev/null +++ b/app/javascript/flavours/glitch/selectors/filters.ts @@ -0,0 +1,50 @@ +import { createSelector } from '@reduxjs/toolkit'; + +import type { RootState } from 'flavours/glitch/store'; +import { toServerSideType } from 'flavours/glitch/utils/filters'; + +// TODO: move to `app/javascript/flavours/glitch/models` and use more globally +type Filter = Immutable.Map; + +// TODO: move to `app/javascript/flavours/glitch/models` and use more globally +type FilterResult = Immutable.Map; + +export const getFilters = createSelector( + [ + (state: RootState) => state.filters as Immutable.Map, + (_, { contextType }: { contextType: string }) => contextType, + ], + (filters, contextType) => { + if (!contextType) { + return null; + } + + const now = new Date(); + const serverSideType = toServerSideType(contextType); + + return filters.filter((filter) => { + const context = filter.get('context') as Immutable.List; + const expiration = filter.get('expires_at') as Date | null; + return ( + context.includes(serverSideType) && + (expiration === null || expiration > now) + ); + }); + }, +); + +export const getStatusHidden = ( + state: RootState, + { id, contextType }: { id: string; contextType: string }, +) => { + const filters = getFilters(state, { contextType }); + if (filters === null) return false; + + const filtered = state.statuses.getIn([id, 'filtered']) as + | Immutable.List + | undefined; + return filtered?.some( + (result) => + filters.getIn([result.get('filter'), 'filter_action']) === 'hide', + ); +}; diff --git a/app/javascript/flavours/glitch/selectors/index.js b/app/javascript/flavours/glitch/selectors/index.js index 1b2d63ae36d1b5..7c9a68cba41429 100644 --- a/app/javascript/flavours/glitch/selectors/index.js +++ b/app/javascript/flavours/glitch/selectors/index.js @@ -1,22 +1,11 @@ import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; -import { toServerSideType } from 'flavours/glitch/utils/filters'; - import { me } from '../initial_state'; -export { makeGetAccount } from "./accounts"; - -const getFilters = createSelector([state => state.get('filters'), (_, { contextType }) => contextType], (filters, contextType) => { - if (!contextType) { - return null; - } +import { getFilters } from './filters'; - const now = new Date(); - const serverSideType = toServerSideType(contextType); - - return filters.filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now)); -}); +export { makeGetAccount } from "./accounts"; export const makeGetStatus = () => { return createSelector( diff --git a/app/javascript/flavours/glitch/selectors/settings.ts b/app/javascript/flavours/glitch/selectors/settings.ts index d66f00f0e1db32..5229b15cf051d0 100644 --- a/app/javascript/flavours/glitch/selectors/settings.ts +++ b/app/javascript/flavours/glitch/selectors/settings.ts @@ -52,4 +52,7 @@ export const selectSettingsNotificationsMinimizeFilteredBanner = ( ) => state.settings.getIn(['notifications', 'minimizeFilteredBanner']) as boolean; +export const selectSettingsNotificationsGroupFollows = (state: RootState) => + state.settings.getIn(['notifications', 'group', 'follow']) as boolean; + /* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ diff --git a/app/javascript/flavours/glitch/styles/admin.scss b/app/javascript/flavours/glitch/styles/admin.scss index c4a16247b8dad0..fadc678de3c25f 100644 --- a/app/javascript/flavours/glitch/styles/admin.scss +++ b/app/javascript/flavours/glitch/styles/admin.scss @@ -226,6 +226,10 @@ $content-width: 840px; gap: 5px; white-space: nowrap; + @media screen and (max-width: $mobile-breakpoint) { + flex: 1 0 50%; + } + &:hover, &:focus, &:active { @@ -1046,6 +1050,12 @@ a.name-tag, color: var(--user-role-accent); } +.applications-list { + .icon { + vertical-align: middle; + } +} + .announcements-list, .filters-list { border: 1px solid var(--background-border-color); @@ -1075,6 +1085,10 @@ a.name-tag, } } + .icon { + vertical-align: middle; + } + a.announcements-list__item__title { &:hover, &:focus, diff --git a/app/javascript/flavours/glitch/styles/basics.scss b/app/javascript/flavours/glitch/styles/basics.scss index 2223893336c30c..2ecc855b9c6a7d 100644 --- a/app/javascript/flavours/glitch/styles/basics.scss +++ b/app/javascript/flavours/glitch/styles/basics.scss @@ -141,6 +141,7 @@ body { width: 100%; height: auto; margin-top: -120px; + margin-bottom: -45px; } } diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 6ee86f5ee0fb28..b66312a1653488 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); } @@ -2213,7 +2259,6 @@ body > [data-popper-placement] { display: block; position: relative; border-radius: var(--avatar-border-radius); - background-color: var(--surface-background-color); img { width: 100%; @@ -2223,7 +2268,11 @@ body > [data-popper-placement] { display: inline-block; // to not show broken images } - &-inline { + &--loading { + background-color: var(--surface-background-color); + } + + &--inline { display: inline-block; vertical-align: middle; margin-inline-end: 5px; @@ -2889,7 +2938,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 +3707,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 +3725,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, @@ -3715,6 +3796,7 @@ $ui-header-logo-wordmark-width: 99px; overflow-y: auto; width: 100%; height: 100%; + z-index: 0; } .drawer__inner__mastodon { @@ -4037,22 +4119,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 +6311,7 @@ a.status-card { .icon { width: 24px; height: 24px; + filter: var(--overlay-icon-shadow); } &:hover, @@ -6339,6 +6406,10 @@ a.status-card { .icon-button { color: $white; + .icon { + filter: var(--overlay-icon-shadow); + } + &:hover, &:focus, &:active { @@ -6397,6 +6468,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 +6745,14 @@ a.status-card { display: flex; gap: 16px; align-items: center; + + strong { + font-weight: 700; + } + } + + &--deemphasized { + color: $secondary-text-color; } &__icon { @@ -7392,7 +7472,7 @@ img.modal-warning { .media-gallery__actions { position: absolute; - bottom: 6px; + top: 6px; inset-inline-end: 6px; display: flex; gap: 2px; @@ -7415,75 +7495,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 +7512,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 +7620,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 +7692,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 +7711,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 +7770,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 +7783,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 +7799,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 +7821,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 +7879,7 @@ img.modal-warning { .video-player__controls { padding-top: 10px; background: transparent; + z-index: 1; } } @@ -7752,16 +7893,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 +7913,7 @@ img.modal-warning { display: block; max-width: 100vw; max-height: 80vh; - z-index: 1; + z-index: -2; position: relative; } @@ -7800,7 +7940,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 +8255,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; } } @@ -8395,18 +8525,50 @@ noscript { background: rgba($base-overlay-background, 0.5); } +.list-adder, .list-editor { - background: $ui-base-color; + backdrop-filter: var(--background-filter); + background: var(--modal-background-color); + border: 1px solid var(--modal-border-color); flex-direction: column; border-radius: 8px; - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); width: 380px; overflow: hidden; @media screen and (width <= 420px) { width: 90%; } +} +.list-adder { + &__lists { + height: 50vh; + border-radius: 0 0 8px 8px; + overflow-y: auto; + } + + .list { + padding: 10px; + border-bottom: 1px solid var(--background-border-color); + } + + .list__wrapper { + display: flex; + } + + .list__display-name { + flex: 1 1 auto; + overflow: hidden; + text-decoration: none; + font-size: 16px; + padding: 10px; + display: flex; + align-items: center; + gap: 4px; + } +} + +.list-editor { h4 { padding: 15px 0; background: lighten($ui-base-color, 13%); @@ -8418,12 +8580,10 @@ noscript { .drawer__pager { height: 50vh; - border-radius: 4px; + border: 0; } .drawer__inner { - border-radius: 0 0 8px 8px; - &.backdrop { width: calc(100% - 60px); box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); @@ -8432,6 +8592,7 @@ noscript { } &__accounts { + background: unset; overflow-y: auto; } @@ -8450,47 +8611,6 @@ noscript { } } -.list-adder { - background: $ui-base-color; - flex-direction: column; - border-radius: 8px; - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); - width: 380px; - overflow: hidden; - - @media screen and (width <= 420px) { - width: 90%; - } - - &__account { - background: lighten($ui-base-color, 13%); - } - - &__lists { - background: lighten($ui-base-color, 13%); - height: 50vh; - border-radius: 0 0 8px 8px; - overflow-y: auto; - } - - .list { - padding: 10px; - border-bottom: 1px solid var(--background-border-color); - } - - .list__wrapper { - display: flex; - } - - .list__display-name { - flex: 1 1 auto; - overflow: hidden; - text-decoration: none; - font-size: 16px; - padding: 10px; - } -} - .focal-point { position: relative; cursor: move; @@ -11045,6 +11165,7 @@ noscript { gap: 8px; .logo { + width: 16px; height: 16px; color: $darker-text-color; } @@ -11233,21 +11354,17 @@ noscript { color: $darker-text-color; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - max-height: 4 * 22px; + max-height: none; overflow: hidden; - p { - display: none; - - &:first-child { - display: initial; - } - } - p, a { color: inherit; } + + p { + margin-bottom: 8px; + } } .reply-indicator__attachments { 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 fb1badca342b6f..eddf281f7e9bff 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -25,6 +25,8 @@ code { position: relative; overflow: hidden; height: 160px; + max-width: 566px; + margin-inline: auto; &::after { content: ''; @@ -315,6 +317,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/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index f6140b87e2c072..ba60983436e646 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -90,6 +90,10 @@ body.rtl { direction: rtl; } + .column-back-button__icon { + transform: scale(-1, 1); + } + .simple_form select { background: $ui-base-color url("data:image/svg+xml;utf8,") diff --git a/app/javascript/flavours/glitch/styles/tables.scss b/app/javascript/flavours/glitch/styles/tables.scss index 6c7723b60d774e..75fc29aed5ea10 100644 --- a/app/javascript/flavours/glitch/styles/tables.scss +++ b/app/javascript/flavours/glitch/styles/tables.scss @@ -137,6 +137,7 @@ a.table-action-link { padding: 0 10px; color: $darker-text-color; font-weight: 500; + white-space: nowrap; &:hover { color: $highlight-text-color; @@ -355,6 +356,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/flavours/glitch/utils/resize_image.js b/app/javascript/flavours/glitch/utils/resize_image.js index e3d4e6a354b9e9..c579fe5a2c6f1e 100644 --- a/app/javascript/flavours/glitch/utils/resize_image.js +++ b/app/javascript/flavours/glitch/utils/resize_image.js @@ -17,7 +17,7 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { case false: resolve(orientation); break; - default: + default: { // black 2x1 JPEG, with the following meta information set: // - EXIF Orientation: 6 (Rotated 90° CCW) const testImageURL = @@ -39,6 +39,7 @@ const dropOrientationIfNeeded = (orientation) => new Promise(resolve => { }; img.src = testImageURL; } + } }); // Some browsers don't allow reading from a canvas and instead return all-white @@ -52,7 +53,7 @@ const checkCanvasReliability = () => new Promise((resolve, reject) => { case false: resolve(); break; - default: + default: { // 2×2 GIF with white, red, green and blue pixels const testImageURL = 'data:image/gif;base64,R0lGODdhAgACAKEDAAAA//8AAAD/AP///ywAAAAAAgACAAACA1wEBQA7'; @@ -78,6 +79,7 @@ const checkCanvasReliability = () => new Promise((resolve, reject) => { }; img.src = testImageURL; } + } }); const getImageUrl = inputFile => new Promise((resolve, reject) => { 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/markers.ts b/app/javascript/mastodon/actions/markers.ts index 0b3280c2128dea..251546cb9a35b3 100644 --- a/app/javascript/mastodon/actions/markers.ts +++ b/app/javascript/mastodon/actions/markers.ts @@ -37,8 +37,7 @@ export const synchronouslySubmitMarkers = createAppAsyncThunk( }); return; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - } else if ('navigator' && 'sendBeacon' in navigator) { + } else if ('sendBeacon' in navigator) { // Failing that, we can use sendBeacon, but we have to encode the data as // FormData for DoorKeeper to recognize the token. const formData = new FormData(); diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts index 9d3fc0d4254dcf..a3c8095ac44fe4 100644 --- a/app/javascript/mastodon/actions/notification_groups.ts +++ b/app/javascript/mastodon/actions/notification_groups.ts @@ -8,6 +8,7 @@ import type { ApiAccountJSON } from 'mastodon/api_types/accounts'; import type { ApiNotificationGroupJSON, ApiNotificationJSON, + NotificationType, } from 'mastodon/api_types/notifications'; import { allNotificationTypes } from 'mastodon/api_types/notifications'; import type { ApiStatusJSON } from 'mastodon/api_types/statuses'; @@ -15,6 +16,7 @@ import { usePendingItems } from 'mastodon/initial_state'; import type { NotificationGap } from 'mastodon/reducers/notification_groups'; import { selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsGroupFollows, selectSettingsNotificationsQuickFilterActive, selectSettingsNotificationsShows, } from 'mastodon/selectors/settings'; @@ -68,10 +70,21 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } +function selectNotificationGroupedTypes(state: RootState) { + const types: NotificationType[] = ['favourite', 'reblog']; + + if (selectSettingsNotificationsGroupFollows(state)) types.push('follow'); + + return types; +} + export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => - apiFetchNotificationGroups({ exclude_types: getExcludedTypes(getState()) }), + apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), + exclude_types: getExcludedTypes(getState()), + }), ({ notifications, accounts, statuses }, { dispatch }) => { dispatch(importFetchedAccounts(accounts)); dispatch(importFetchedStatuses(statuses)); @@ -93,6 +106,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -109,6 +123,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { return apiFetchNotificationGroups({ + grouped_types: selectNotificationGroupedTypes(getState()), max_id: undefined, exclude_types: getExcludedTypes(getState()), // In slow mode, we don't want to include notifications that duplicate the already-displayed ones @@ -157,7 +172,10 @@ export const processNewNotificationForGroups = createAppAsyncThunk( dispatchAssociatedRecords(dispatch, [notification]); - return notification; + return { + notification, + groupedTypes: selectNotificationGroupedTypes(state), + }; }, ); 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/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index b6fc31fae855ac..30e643363a1c0d 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -106,12 +106,13 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti dispatch(processNewNotificationForGroups(notificationJSON)); break; } - case 'notifications_merged': + case 'notifications_merged': { const state = getState(); if (state.notifications.top || !state.notifications.mounted) dispatch(expandNotifications({ forceLoad: true, maxId: undefined })); dispatch(refreshStaleNotificationGroups()); break; + } case 'conversation': // @ts-expect-error dispatch(updateConversations(JSON.parse(data.payload))); 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/api_types/accounts.ts b/app/javascript/mastodon/api_types/accounts.ts index 5bf3e64288c76e..fdbd7523fc15cd 100644 --- a/app/javascript/mastodon/api_types/accounts.ts +++ b/app/javascript/mastodon/api_types/accounts.ts @@ -13,7 +13,7 @@ export interface ApiAccountRoleJSON { } // See app/serializers/rest/account_serializer.rb -export interface ApiAccountJSON { +export interface BaseApiAccountJSON { acct: string; avatar: string; avatar_static: string; @@ -45,3 +45,12 @@ export interface ApiAccountJSON { memorial?: boolean; hide_collections: boolean; } + +// See app/serializers/rest/muted_account_serializer.rb +export interface ApiMutedAccountJSON extends BaseApiAccountJSON { + mute_expires_at?: string | null; +} + +// For now, we have the same type representing both `Account` and `MutedAccount` +// objects, but we should refactor this in the future. +export type ApiAccountJSON = ApiMutedAccountJSON; diff --git a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.jsx.snap b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.jsx.snap index 2f0a2de324b551..124b50d8c78c0e 100644 --- a/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.jsx.snap +++ b/app/javascript/mastodon/components/__tests__/__snapshots__/avatar-test.jsx.snap @@ -2,7 +2,7 @@ exports[` Autoplay renders a animated avatar 1`] = `
Autoplay renders a animated avatar 1`] = ` >
@@ -21,7 +23,7 @@ exports[` Autoplay renders a animated avatar 1`] = ` exports[` Still renders a still avatar 1`] = `
Still renders a still avatar 1`] = ` >
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/avatar.tsx b/app/javascript/mastodon/components/avatar.tsx index 8b16296c2c0403..f61d9676de50b5 100644 --- a/app/javascript/mastodon/components/avatar.tsx +++ b/app/javascript/mastodon/components/avatar.tsx @@ -1,10 +1,11 @@ +import { useState, useCallback } from 'react'; + import classNames from 'classnames'; +import { useHovering } from 'mastodon/../hooks/useHovering'; +import { autoPlayGif } from 'mastodon/initial_state'; import type { Account } from 'mastodon/models/account'; -import { useHovering } from '../../hooks/useHovering'; -import { autoPlayGif } from '../initial_state'; - interface Props { account: Account | undefined; // FIXME: remove `undefined` once we know for sure its always there size: number; @@ -25,6 +26,8 @@ export const Avatar: React.FC = ({ counterBorderColor, }) => { const { hovering, handleMouseEnter, handleMouseLeave } = useHovering(animate); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); const style = { ...styleFromParent, @@ -37,16 +40,28 @@ export const Avatar: React.FC = ({ ? account?.get('avatar') : account?.get('avatar_static'); + const handleLoad = useCallback(() => { + setLoading(false); + }, [setLoading]); + + const handleError = useCallback(() => { + setError(true); + }, [setError]); + return (
- {src && } + {src && !error && ( + + )} + {counter && (
, '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..e059978442a131 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 @@ -188,7 +196,7 @@ class Item extends PureComponent { {visible && thumbnail} - {badges && ( + {visible && badges && (
{badges}
@@ -328,14 +336,14 @@ class MediaGallery extends PureComponent { return (
+ {children} + {(!visible || uncached) && (
{spoilerButton}
)} - {children} - {(visible && !uncached) && (
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..94cd7e3e077178 100644 --- a/app/javascript/mastodon/components/status_action_bar.jsx +++ b/app/javascript/mastodon/components/status_action_bar.jsx @@ -264,7 +264,7 @@ class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.share), action: this.handleShareClick }); } - if (publicStatus && (signedIn || !isRemote)) { + if (publicStatus && !isRemote) { menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); } @@ -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/notifications/components/filtered_notifications_banner.tsx b/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx index d9e60d48cdbca4..d2241af38964f4 100644 --- a/app/javascript/mastodon/features/notifications/components/filtered_notifications_banner.tsx +++ b/app/javascript/mastodon/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/mastodon/features/notifications/containers/column_settings_container.js b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js index 8bcc7ab4ef79ab..4ac6cfa629ba10 100644 --- a/app/javascript/mastodon/features/notifications/containers/column_settings_container.js +++ b/app/javascript/mastodon/features/notifications/containers/column_settings_container.js @@ -56,11 +56,12 @@ const mapDispatchToProps = (dispatch) => ({ } else { dispatch(changeSetting(['notifications', ...path], checked)); } - } else if(path[0] === 'groupingBeta') { - dispatch(changeSetting(['notifications', ...path], checked)); - dispatch(initializeNotifications()); } else { dispatch(changeSetting(['notifications', ...path], checked)); + + if(path[0] === 'group' && path[1] === 'follow') { + dispatch(initializeNotifications()); + } } }, diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx index 6a9a45d242c348..2c90777b9f62a4 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx @@ -1,16 +1,19 @@ import { FormattedMessage } from 'react-intl'; +import { Link } from 'react-router-dom'; + import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; import { FollowersCounter } from 'mastodon/components/counters'; import { FollowButton } from 'mastodon/components/follow_button'; import { ShortNumber } from 'mastodon/components/short_number'; +import { me } from 'mastodon/initial_state'; import type { NotificationGroupFollow } from 'mastodon/models/notification_group'; import { useAppSelector } from 'mastodon/store'; import type { LabelRenderer } from './notification_group_with_status'; import { NotificationGroupWithStatus } from './notification_group_with_status'; -const labelRenderer: LabelRenderer = (displayedName, total) => { +const labelRenderer: LabelRenderer = (displayedName, total, seeMoreHref) => { if (total === 1) return ( { return ( + seeMoreHref ? {chunks} : chunks, }} /> ); @@ -46,6 +51,10 @@ export const NotificationFollow: React.FC<{ notification: NotificationGroupFollow; unread: boolean; }> = ({ notification, unread }) => { + const username = useAppSelector( + (state) => state.accounts.getIn([me, 'username']) as string, + ); + let actions: JSX.Element | undefined; let additionalContent: JSX.Element | undefined; @@ -68,6 +77,7 @@ export const NotificationFollow: React.FC<{ timestamp={notification.latest_page_notification_at} count={notification.notifications_count} labelRenderer={labelRenderer} + labelSeeMoreHref={`/@${username}/followers`} unread={unread} actions={actions} additionalContent={additionalContent} diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx index a1c275a1f39309..3e6428287d822f 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx @@ -13,6 +13,7 @@ import { import type { IconProp } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon'; import Status from 'mastodon/containers/status_container'; +import { getStatusHidden } from 'mastodon/selectors/filters'; import { useAppSelector, useAppDispatch } from 'mastodon/store'; import { DisplayedName } from './displayed_name'; @@ -48,6 +49,12 @@ export const NotificationWithStatus: React.FC<{ (state) => state.statuses.getIn([statusId, 'visibility']) === 'direct', ); + const isFiltered = useAppSelector( + (state) => + statusId && + getStatusHidden(state, { id: statusId, contextType: 'notifications' }), + ); + const handlers = useMemo( () => ({ open: () => { @@ -73,7 +80,7 @@ export const NotificationWithStatus: React.FC<{ [dispatch, statusId], ); - if (!statusId) return null; + if (!statusId || isFiltered) return null; return ( diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx index 300c8dd5b3ef05..5c83f99b54f55d 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx @@ -14,6 +14,8 @@ import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import ReplyIcon from '@/material-icons/400-24px/reply.svg?react'; import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react'; import StarIcon from '@/material-icons/400-24px/star.svg?react'; +import RepeatDisabledIcon from '@/svg-icons/repeat_disabled.svg?react'; +import RepeatPrivateIcon from '@/svg-icons/repeat_private.svg?react'; import { replyCompose } from 'mastodon/actions/compose'; import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions'; import { openModal } from 'mastodon/actions/modal'; @@ -159,22 +161,26 @@ class Footer extends ImmutablePureComponent { replyTitle = intl.formatMessage(messages.replyAll); } - let reblogTitle = ''; + let reblogTitle, reblogIconComponent; if (status.get('reblogged')) { reblogTitle = intl.formatMessage(messages.cancel_reblog_private); + reblogIconComponent = publicStatus ? RepeatIcon : RepeatPrivateIcon; } else if (publicStatus) { reblogTitle = intl.formatMessage(messages.reblog); + reblogIconComponent = RepeatIcon; } else if (reblogPrivate) { reblogTitle = intl.formatMessage(messages.reblog_private); + reblogIconComponent = RepeatPrivateIcon; } else { reblogTitle = intl.formatMessage(messages.cannot_reblog); + reblogIconComponent = RepeatDisabledIcon; } return (
- + {withOpenButton && }
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx index fa843122fbce8a..0bf1bfda8bf8b2 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.tsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx @@ -151,7 +151,25 @@ export const DetailedStatus: React.FC<{ if (pictureInPicture.get('inUse')) { media = ; } else if (status.get('media_attachments').size > 0) { - if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { + if ( + ['image', 'gifv'].includes( + status.getIn(['media_attachments', 0, 'type']) as string, + ) || + status.get('media_attachments').size > 1 + ) { + media = ( + + ); + } else if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); const description = attachment.getIn(['translation', 'description']) || @@ -200,19 +218,6 @@ export const DetailedStatus: React.FC<{ onToggleVisibility={onToggleMediaVisibility} /> ); - } else { - media = ( - - ); } } else if (status.get('spoiler_text').length === 0) { media = ( diff --git a/app/javascript/mastodon/features/ui/components/block_modal.jsx b/app/javascript/mastodon/features/ui/components/block_modal.jsx index d6fc6c41546d2e..21a984f97f4e35 100644 --- a/app/javascript/mastodon/features/ui/components/block_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/block_modal.jsx @@ -99,7 +99,7 @@ export const BlockModal = ({ accountId, acct }) => { -
diff --git a/app/javascript/mastodon/features/ui/components/column_link.jsx b/app/javascript/mastodon/features/ui/components/column_link.jsx index 6ef122c07be844..f27ed50675a789 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); @@ -15,7 +15,7 @@ const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text if (href) { return ( - + {active ? activeIconElement : iconElement} {text} {badgeElement} @@ -23,7 +23,7 @@ const ColumnLink = ({ icon, activeIcon, iconComponent, activeIconComponent, text ); } else { return ( - + {active ? activeIconElement : iconElement} {text} {badgeElement} @@ -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/mute_modal.jsx b/app/javascript/mastodon/features/ui/components/mute_modal.jsx index 70d95b593161a1..90b88030a09f92 100644 --- a/app/javascript/mastodon/features/ui/components/mute_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/mute_modal.jsx @@ -116,6 +116,7 @@ export const MuteModal = ({ accountId, acct }) => {
+ 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 = (); + 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..6d8290f8a13294 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -84,6 +84,7 @@ "alert.rate_limited.title": "معدل الطلبات محدود", "alert.unexpected.message": "لقد طرأ خطأ غير متوقّع.", "alert.unexpected.title": "المعذرة!", + "alt_text_badge.title": "نص بديل", "announcement.announcement": "إعلان", "attachments_list.unprocessed": "(غير معالَج)", "audio.hide": "إخفاء المقطع الصوتي", @@ -156,7 +157,6 @@ "compose_form.poll.duration": "مُدَّة اِستطلاع الرأي", "compose_form.poll.multiple": "متعدد الخيارات", "compose_form.poll.option_placeholder": "الخيار {number}", - "compose_form.poll.single": "اختر واحدا", "compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة", "compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط", "compose_form.poll.type": "الطراز", @@ -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": "إظهار الملف التعريفي على أي حال", @@ -761,7 +758,7 @@ "status.history.edited": "عدله {name} {date}", "status.load_more": "حمّل المزيد", "status.media.open": "اضغط للفتح", - "status.media.show": "اضغط لإظهاره", + "status.media.show": "اضغط لإظهارها", "status.media_hidden": "وسائط مخفية", "status.mention": "أذكُر @{name}", "status.more": "المزيد", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 219ea0d17cf1c4..f2a0c22a771550 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -29,7 +29,7 @@ "account.followers": "Siguidores", "account.followers.empty": "Naide sigue a esti perfil.", "account.follows.empty": "Esti perfil nun sigue a naide.", - "account.hide_reblogs": "Anubrir los artículos compartíos de @{name}", + "account.hide_reblogs": "Esconder los artículos compartíos de @{name}", "account.in_memoriam": "N'alcordanza.", "account.joined_short": "Data de xunión", "account.link_verified_on": "La propiedá d'esti enllaz comprobóse'l {date}", @@ -122,6 +122,7 @@ "conversation.open": "Ver la conversación", "conversation.with": "Con {names}", "copypaste.copied": "Copióse", + "copypaste.copy_to_clipboard": "Copiar nel cartafueyu", "directory.federated": "Del fediversu conocíu", "directory.local": "De «{domain}» namás", "directory.new_arrivals": "Cuentes nueves", @@ -130,7 +131,7 @@ "dismissable_banner.dismiss": "Escartar", "dismissable_banner.explore_tags": "Esta seición contién les etiquetes del fediversu que tán ganando popularidá güei. Les etiquetes más usaes polos perfiles apaecen no cimero.", "dismissable_banner.public_timeline": "Esta seición contién los artículos más nuevos de les persones na web social que les persones de {domain} siguen.", - "embed.instructions": "Empotra esti artículu nel to sitiu web pente la copia del códigu d'abaxo.", + "embed.instructions": "Empotra esti artículu nel to sitiu web copiando'l códigu d'abaxo.", "embed.preview": "Va apaecer asina:", "emoji_button.activity": "Actividá", "emoji_button.flags": "Banderes", @@ -251,7 +252,7 @@ "keyboard_shortcuts.requests": "Abrir la llista de solicitúes de siguimientu", "keyboard_shortcuts.search": "Enfocar la barra de busca", "keyboard_shortcuts.start": "Abrir la columna «Entamar»", - "keyboard_shortcuts.toggle_sensitivity": "Amosar/anubrir el conteníu multimedia", + "keyboard_shortcuts.toggle_sensitivity": "Amosar/esconder el conteníu multimedia", "keyboard_shortcuts.toot": "Comenzar un artículu nuevu", "keyboard_shortcuts.unfocus": "Desenfocar l'área de composición/busca", "keyboard_shortcuts.up": "Xubir na llista", @@ -299,6 +300,7 @@ "notifications.column_settings.admin.sign_up": "Rexistros nuevos:", "notifications.column_settings.follow": "Siguidores nuevos:", "notifications.column_settings.follow_request": "Solicitúes de siguimientu nueves:", + "notifications.column_settings.group": "Agrupar", "notifications.column_settings.mention": "Menciones:", "notifications.column_settings.poll": "Resultaos de les encuestes:", "notifications.column_settings.reblog": "Artículos compartíos:", @@ -418,11 +420,12 @@ "status.direct": "Mentar a @{name} per privao", "status.direct_indicator": "Mención privada", "status.edited_x_times": "Editóse {count, plural, one {{count} vegada} other {{count} vegaes}}", + "status.embed": "Consiguir el códigu pa empotrar", "status.filter": "Peñerar esti artículu", "status.history.created": "{name} creó {date}", "status.history.edited": "{name} editó {date}", "status.load_more": "Cargar más", - "status.media_hidden": "Conteníu multimedia anubríu", + "status.media_hidden": "Conteníu multimedia escondíu", "status.mention": "Mentar a @{name}", "status.more": "Más", "status.mute": "Desactivar los avisos de @{name}", @@ -468,14 +471,14 @@ "upload_modal.applying": "Aplicando…", "upload_modal.detect_text": "Detectar el testu de la semeya", "upload_modal.edit_media": "Edición", - "upload_modal.hint": "Calca o arrastra'l círculu de la previsualización pa escoyer el puntu d'enfoque que siempres va tar a la vista en toles miniatures.", + "upload_modal.hint": "Calca o arrastra'l círculu de la previsualización pa escoyer el puntu d'enfoque que siempre va tar a la vista en toles miniatures.", "upload_progress.label": "Xubiendo…", "upload_progress.processing": "Procesando…", "video.close": "Zarrar el videu", "video.download": "Baxar el ficheru", "video.expand": "Espander el videu", "video.fullscreen": "Pantalla completa", - "video.hide": "Anubrir el videu", + "video.hide": "Esconder el videu", "video.mute": "Desactivar el soníu", "video.pause": "Posar", "video.play": "Reproducir", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 8c28e71d2cf2b5..eb5cd5053dd5a9 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.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": "Схаваць аўдыя", @@ -155,7 +156,6 @@ "compose_form.poll.duration": "Працягласць апытання", "compose_form.poll.multiple": "Множны выбар", "compose_form.poll.option_placeholder": "Варыянт {number}", - "compose_form.poll.single": "Адзін варыянт", "compose_form.poll.switch_to_multiple": "Змяніце апытанне, каб дазволіць некалькі варыянтаў адказу", "compose_form.poll.switch_to_single": "Змяніце апытанне, каб дазволіць адзіны варыянт адказу", "compose_form.poll.type": "Стыль", @@ -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..3d5d8a85850879 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": "Скриване на звука", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Времетраене на анкетата", "compose_form.poll.multiple": "Множествен избор", "compose_form.poll.option_placeholder": "Избор {number}", - "compose_form.poll.single": "Подберете нещо", "compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора", "compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор", "compose_form.poll.type": "Стил", @@ -220,7 +220,6 @@ "domain_block_modal.they_cant_follow": "Никого от този сървър не може да ви последва.", "domain_block_modal.they_wont_know": "Няма да узнаят, че са били блокирани.", "domain_block_modal.title": "Блокирате ли домейн?", - "domain_block_modal.you_will_lose_followers": "Всичките ви последователи от този сървър ще се премахнат.", "domain_block_modal.you_wont_see_posts": "Няма да виждате публикации или известия от потребителите на този сървър.", "domain_pill.activitypub_lets_connect": "Позволява ви да се свързвате и взаимодействате с хора не само в Mastodon, но и през различни социални приложения.", "domain_pill.activitypub_like_language": "ActivityPub е като език на Mastodon, говорещ с други социални мрежи.", @@ -419,8 +418,6 @@ "keyboard_shortcuts.unfocus": "Разфокусиране на текстовото поле за съставяне/търсене", "keyboard_shortcuts.up": "Преместване нагоре в списъка", "lightbox.close": "Затваряне", - "lightbox.compress": "Свиване на полето за преглед на образи", - "lightbox.expand": "Разгъване на полето за преглед на образи", "lightbox.next": "Напред", "lightbox.previous": "Назад", "limited_account_hint.action": "Показване на профила въпреки това", @@ -492,7 +489,6 @@ "notification.favourite": "{name} направи любима публикацията ви", "notification.favourite.name_and_others_with_link": "{name} и {count, plural, one {# друг} other {# други}} направиха любима ваша публикация", "notification.follow": "{name} ви последва", - "notification.follow.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} ви последваха", "notification.follow_request": "{name} поиска да ви последва", "notification.follow_request.name_and_others": "{name} и {count, plural, one {# друг} other {# други}} поискаха да ви последват", "notification.label.mention": "Споменаване", diff --git a/app/javascript/mastodon/locales/br.json b/app/javascript/mastodon/locales/br.json index 18616fcef2cc29..1f0c90efcb048b 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -145,7 +145,6 @@ "compose_form.poll.duration": "Pad ar sontadeg", "compose_form.poll.multiple": "Meur a choaz", "compose_form.poll.option_placeholder": "Choaz {number}", - "compose_form.poll.single": "Dibabit unan", "compose_form.poll.switch_to_multiple": "Kemmañ ar sontadeg evit aotren meur a zibab", "compose_form.poll.switch_to_single": "Kemmañ ar sontadeg evit aotren un dibab hepken", "compose_form.poll.type": "Neuz", @@ -338,8 +337,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", @@ -387,6 +384,7 @@ "notification.admin.report": "Disklêriet eo bet {target} gant {name}", "notification.admin.sign_up": "{name} en·he deus lakaet e·hec'h anv", "notification.follow": "heuliañ a ra {name} ac'hanoc'h", + "notification.follow.name_and_others": "{name} {count, plural, one {hag # den all} two {ha # zen all} few {ha # den all} many {ha # den all} other {ha # den all}} zo o heuliañ ac'hanoc'h", "notification.follow_request": "Gant {name} eo bet goulennet ho heuliañ", "notification.moderation-warning.learn_more": "Gouzout hiroc'h", "notification.own_poll": "Echu eo ho sontadeg", @@ -401,6 +399,7 @@ "notifications.column_settings.favourite": "Muiañ-karet:", "notifications.column_settings.follow": "Heulierien nevez:", "notifications.column_settings.follow_request": "Pedadoù heuliañ nevez :", + "notifications.column_settings.group": "Strollañ", "notifications.column_settings.mention": "Menegoù:", "notifications.column_settings.poll": "Disoc'hoù ar sontadeg:", "notifications.column_settings.push": "Kemennoù push", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 3cdeab3ae42d46..990a3ef97d373e 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", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Durada de l'enquesta", "compose_form.poll.multiple": "Opcions múltiples", "compose_form.poll.option_placeholder": "Opció {number}", - "compose_form.poll.single": "Trieu-ne una", "compose_form.poll.switch_to_multiple": "Canvia l’enquesta per a permetre múltiples opcions", "compose_form.poll.switch_to_single": "Canvia l’enquesta per a permetre una única opció", "compose_form.poll.type": "Estil", @@ -221,7 +221,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 +433,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}", @@ -506,7 +507,6 @@ "notification.favourite": "{name} ha afavorit el teu tut", "notification.favourite.name_and_others_with_link": "{name} i {count, plural, one {# altre} other {# altres}} han afavorit la vostra publicació", "notification.follow": "{name} et segueix", - "notification.follow.name_and_others": "{name} i {count, plural, one {# altre} other {# altres}} us han seguit", "notification.follow_request": "{name} ha sol·licitat de seguir-te", "notification.follow_request.name_and_others": "{name} i {count, plural, one {# altre} other {# altres}} han demanat de seguir-vos", "notification.label.mention": "Menció", @@ -514,6 +514,7 @@ "notification.label.private_reply": "Resposta en privat", "notification.label.reply": "Resposta", "notification.mention": "Menció", + "notification.mentioned_you": "{name} us ha mencionat", "notification.moderation-warning.learn_more": "Per a saber-ne més", "notification.moderation_warning": "Heu rebut un avís de moderació", "notification.moderation_warning.action_delete_statuses": "S'han eliminat algunes de les vostres publicacions.", @@ -850,6 +851,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..469cf4410d96c6 100644 --- a/app/javascript/mastodon/locales/ckb.json +++ b/app/javascript/mastodon/locales/ckb.json @@ -143,7 +143,6 @@ "compose_form.poll.duration": "ماوەی ڕاپرسی", "compose_form.poll.multiple": "فرە هەڵبژاردە", "compose_form.poll.option_placeholder": "بژاردەی {number}", - "compose_form.poll.single": "یەکێك هەلبژێرە", "compose_form.poll.switch_to_multiple": "ڕاپرسی بگۆڕە بۆ ڕێگەدان بە چەند هەڵبژاردنێک", "compose_form.poll.switch_to_single": "گۆڕینی ڕاپرسی بۆ ڕێگەدان بە تاکە هەڵبژاردنێک", "compose_form.poll.type": "ستایڵ", @@ -335,8 +334,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..7198bcab580c18 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -157,7 +157,6 @@ "compose_form.poll.duration": "Doba trvání ankety", "compose_form.poll.multiple": "Výběr z více možností", "compose_form.poll.option_placeholder": "Volba {number}", - "compose_form.poll.single": "Vyber jednu", "compose_form.poll.switch_to_multiple": "Povolit u ankety výběr více voleb", "compose_form.poll.switch_to_single": "Povolit u ankety výběr pouze jedné volby", "compose_form.poll.type": "Styl", @@ -220,7 +219,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 +408,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..723e8ae37d5e62 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Cyfradd gyfyngedig", "alert.unexpected.message": "Digwyddodd gwall annisgwyl.", "alert.unexpected.title": "Wps!", + "alt_text_badge.title": "Testun Amgen", "announcement.announcement": "Cyhoeddiad", "attachments_list.unprocessed": "(heb eu prosesu)", "audio.hide": "Cuddio sain", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Cyfnod pleidlais", "compose_form.poll.multiple": "Dewis lluosog", "compose_form.poll.option_placeholder": "Dewis {number}", - "compose_form.poll.single": "Ddewis un", + "compose_form.poll.single": "Dewis unigol", "compose_form.poll.switch_to_multiple": "Newid pleidlais i adael mwy nag un dewis", "compose_form.poll.switch_to_single": "Newid pleidlais i gyfyngu i un dewis", "compose_form.poll.type": "Arddull", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Byddwch yn colli {followersCount, plural, one {{followersCountDisplay} dilynwr} other {{followersCountDisplay} dilynwyr}} a {followingCount, plural, one {{followingCountDisplay} person rydych yn dilyn} other {{followingCountDisplay} o bobl rydych yn eu dilyn}}.", + "domain_block_modal.you_will_lose_relationships": "Byddwch yn colli'r holl ddilynwyr a phobl rydych chi'n eu dilyn o'r gweinydd hwn.", "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 +434,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}", @@ -506,7 +508,7 @@ "notification.favourite": "Ffafriodd {name} eich postiad", "notification.favourite.name_and_others_with_link": "Ffafriodd {name} a {count, plural, one {# arall} other {# eraill}} eich postiad", "notification.follow": "Dilynodd {name} chi", - "notification.follow.name_and_others": "Mae {name} a {count, plural, one {# other} other {# others}} wedi'ch dilyn chi", + "notification.follow.name_and_others": "Mae {name} a {count, plural, zero {}one {# other} two {# others} few {# others} many {# others} other {# others}} nawr yn eich dilyn chi", "notification.follow_request": "Mae {name} wedi gwneud cais i'ch dilyn", "notification.follow_request.name_and_others": "Mae {name} a{count, plural, one {# other} other {# others}} wedi gofyn i'ch dilyn chi", "notification.label.mention": "Crybwyll", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Ateb preifat", "notification.label.reply": "Ateb", "notification.mention": "Crybwyll", + "notification.mentioned_you": "Rydych wedi'ch crybwyll gan {name}", "notification.moderation-warning.learn_more": "Dysgu mwy", "notification.moderation_warning": "Rydych wedi derbyn rhybudd gan gymedrolwr", "notification.moderation_warning.action_delete_statuses": "Mae rhai o'ch postiadau wedi'u dileu.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Bar hidlo cyflym", "notifications.column_settings.follow": "Dilynwyr newydd:", "notifications.column_settings.follow_request": "Ceisiadau dilyn newydd:", + "notifications.column_settings.group": "Grŵp", "notifications.column_settings.mention": "Crybwylliadau:", "notifications.column_settings.poll": "Canlyniadau pleidlais:", "notifications.column_settings.push": "Hysbysiadau gwthiadwy", @@ -787,6 +791,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", @@ -849,6 +854,11 @@ "upload_error.poll": "Nid oes modd llwytho ffeiliau â phleidleisiau.", "upload_form.audio_description": "Disgrifio ar gyfer pobl sydd â cholled clyw", "upload_form.description": "Disgrifio i'r rheini a nam ar ei golwg", + "upload_form.drag_and_drop.instructions": "I godi atodiad cyfryngau, pwyswch y space neu enter. Wrth lusgo, defnyddiwch y bysellau saeth i symud yr atodiad cyfryngau i unrhyw gyfeiriad penodol. Pwyswch space neu enter eto i ollwng yr atodiad cyfryngau yn ei safle newydd, neu pwyswch escape i ddiddymu.", + "upload_form.drag_and_drop.on_drag_cancel": "Cafodd llusgo ei ddiddymu. Cafodd atodiad cyfryngau {item} ei ollwng.", + "upload_form.drag_and_drop.on_drag_end": "Cafodd atodiad cyfryngau {item} ei ollwng.", + "upload_form.drag_and_drop.on_drag_over": "Symudwyd atodiad cyfryngau {item}.", + "upload_form.drag_and_drop.on_drag_start": "Atodiad cyfryngau godwyd {item}.", "upload_form.edit": "Golygu", "upload_form.thumbnail": "Newid llun bach", "upload_form.video_description": "Disgrifio ar gyfer pobl sydd â cholled clyw neu amhariad golwg", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 2c36869622ce80..0227702d515d28 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", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Afstemningens varighed", "compose_form.poll.multiple": "Multivalg", "compose_form.poll.option_placeholder": "Valgmulighed {number}", - "compose_form.poll.single": "Vælg én", "compose_form.poll.switch_to_multiple": "Ændr afstemning til flervalgstype", "compose_form.poll.switch_to_single": "Ændr afstemning til enkeltvalgstype", "compose_form.poll.type": "Stil", @@ -221,7 +221,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 +433,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}", @@ -506,7 +507,7 @@ "notification.favourite": "{name} favoritmarkerede dit indlæg", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# anden} other {# andre}} gjorde dit indlæg til favorit", "notification.follow": "{name} begyndte at følge dig", - "notification.follow.name_and_others": "{name} og {count, plural, one {# anden} other {# andre}} følger dig", + "notification.follow.name_and_others": "{name} og {count, plural, one {# andre} other {# andre}} begyndte at følge dig", "notification.follow_request": "{name} har anmodet om at følge dig", "notification.follow_request.name_and_others": "{name} og {count, plural, one {# anden} other {# andre}} har anmodet om at følger dig", "notification.label.mention": "Omtale", @@ -514,6 +515,7 @@ "notification.label.private_reply": "Privat svar", "notification.label.reply": "Besvar", "notification.mention": "Omtale", + "notification.mentioned_you": "{name} nævnte dig", "notification.moderation-warning.learn_more": "Læs mere", "notification.moderation_warning": "Du er tildelt en moderationsadvarsel", "notification.moderation_warning.action_delete_statuses": "Nogle af dine indlæg er blevet fjernet.", @@ -564,6 +566,7 @@ "notifications.column_settings.filter_bar.category": "Hurtigfiltreringsbjælke", "notifications.column_settings.follow": "Nye følgere:", "notifications.column_settings.follow_request": "Nye følgeanmodninger:", + "notifications.column_settings.group": "Gruppere", "notifications.column_settings.mention": "Omtaler:", "notifications.column_settings.poll": "Afstemningsresultater:", "notifications.column_settings.push": "Push-notifikationer", @@ -850,6 +853,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..75672a60d6c378 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -41,7 +41,7 @@ "account.go_to_profile": "Profil aufrufen", "account.hide_reblogs": "Geteilte Beiträge von @{name} ausblenden", "account.in_memoriam": "Zum Andenken.", - "account.joined_short": "Beigetreten", + "account.joined_short": "Mitglied seit", "account.languages": "Ausgewählte Sprachen ändern", "account.link_verified_on": "Das Profil mit dieser E-Mail-Adresse wurde bereits am {date} bestätigt", "account.locked_info": "Die Privatsphäre dieses Kontos wurde auf „geschützt“ gesetzt. Die Person bestimmt manuell, wer ihrem Profil folgen darf.", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} favorisierte deinen Beitrag", "notification.favourite.name_and_others_with_link": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} favorisierten deinen Beitrag", "notification.follow": "{name} folgt dir", - "notification.follow.name_and_others": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} folgen dir", + "notification.follow.name_and_others": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} folgen dir", "notification.follow_request": "{name} möchte dir folgen", "notification.follow_request.name_and_others": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} möchten dir folgen", "notification.label.mention": "Erwähnung", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Private Antwort", "notification.label.reply": "Antwort", "notification.mention": "Erwähnung", + "notification.mentioned_you": "{name} erwähnte dich", "notification.moderation-warning.learn_more": "Mehr erfahren", "notification.moderation_warning": "Du wurdest von den Moderator*innen verwarnt", "notification.moderation_warning.action_delete_statuses": "Einige deiner Beiträge sind entfernt worden.", @@ -532,7 +535,7 @@ "notification.relationships_severance_event.domain_block": "Ein Admin von {from} hat {target} blockiert – darunter {followersCount} deiner Follower und {followingCount, plural, one {# Konto, dem} other {# Konten, denen}} du folgst.", "notification.relationships_severance_event.learn_more": "Mehr erfahren", "notification.relationships_severance_event.user_domain_block": "Du hast {target} blockiert – {followersCount} deiner Follower und {followingCount, plural, one {# Konto, dem} other {# Konten, denen}} du folgst, wurden entfernt.", - "notification.status": "{name} hat gerade etwas gepostet", + "notification.status": "{name} veröffentlichte gerade", "notification.update": "{name} bearbeitete einen Beitrag", "notification_requests.accept": "Genehmigen", "notification_requests.accept_multiple": "{count, plural, one {# Anfrage genehmigen …} other {# Anfragen genehmigen …}}", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Filterleiste", "notifications.column_settings.follow": "Neue Follower:", "notifications.column_settings.follow_request": "Neue Follower-Anfragen:", + "notifications.column_settings.group": "Gruppieren", "notifications.column_settings.mention": "Erwähnungen:", "notifications.column_settings.poll": "Umfrageergebnisse:", "notifications.column_settings.push": "Push-Benachrichtigungen", @@ -850,6 +854,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..e362d9b89bb345 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.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": "Απόκρυψη αρχείου ήχου", @@ -97,6 +98,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": "Ωχ όχι!", @@ -155,7 +158,6 @@ "compose_form.poll.duration": "Διάρκεια δημοσκόπησης", "compose_form.poll.multiple": "Πολλαπλή επιλογή", "compose_form.poll.option_placeholder": "Επιλογή {number}", - "compose_form.poll.single": "Διάλεξε ένα", "compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές", "compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή", "compose_form.poll.type": "Στυλ", @@ -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,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} ακόλουθο} other {{followersCountDisplay} ακόλουθους}} και {followingCount, plural, one {{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 μιλάει με άλλα κοινωνικά δίκτυα.", @@ -299,6 +304,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 +433,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 +458,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 +470,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 +487,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": "Προσωπικά", @@ -498,7 +507,6 @@ "notification.favourite": "{name} favorited your post\n{name} προτίμησε την ανάρτηση σου", "notification.favourite.name_and_others_with_link": "{name} και {count, plural, one {# ακόμη} other {# ακόμη}} αγάπησαν την ανάρτησή σου", "notification.follow": "Ο/Η {name} σε ακολούθησε", - "notification.follow.name_and_others": "{name} και {count, plural, one {# ακόμη} other {# ακόμη}} σε ακολούθησαν", "notification.follow_request": "Ο/H {name} ζήτησε να σε ακολουθήσει", "notification.follow_request.name_and_others": "{name} και {count, plural, one {# άλλος} other {# άλλοι}} ζήτησαν να σε ακολουθήσουν", "notification.label.mention": "Επισήμανση", @@ -770,6 +778,7 @@ "status.bookmark": "Σελιδοδείκτης", "status.cancel_reblog_private": "Ακύρωση ενίσχυσης", "status.cannot_reblog": "Αυτή η ανάρτηση δεν μπορεί να ενισχυθεί", + "status.continued_thread": "Συνεχιζόμενο νήματος", "status.copy": "Αντιγραφή συνδέσμου ανάρτησης", "status.delete": "Διαγραφή", "status.detailed_status": "Προβολή λεπτομερούς συζήτησης", @@ -778,6 +787,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 +812,7 @@ "status.reblogs.empty": "Κανείς δεν ενίσχυσε αυτή την ανάρτηση ακόμα. Μόλις το κάνει κάποιος, θα εμφανιστεί εδώ.", "status.redraft": "Σβήσε & ξαναγράψε", "status.remove_bookmark": "Αφαίρεση σελιδοδείκτη", + "status.replied_in_thread": "Απαντήθηκε σε νήμα", "status.replied_to": "Απάντησε στον {name}", "status.reply": "Απάντησε", "status.replyAll": "Απάντησε στο νήμα συζήτησης", @@ -839,6 +850,11 @@ "upload_error.poll": "Στις δημοσκοπήσεις δεν επιτρέπεται η μεταφόρτωση αρχείου.", "upload_form.audio_description": "Περιγραφή για άτομα με προβλήματα ακοής", "upload_form.description": "Περιγραφή για άτομα με προβλήματα όρασης", + "upload_form.drag_and_drop.instructions": "Για να επιλέξετε ένα συνημμένο αρχείο πολυμέσων, πατήστε το Space ή το Enter. Ενώ το σέρνετε, χρησιμοποιήστε τα πλήκτρα βέλους για να μετακινήσετε το συνημμένο αρχείο πολυμέσων προς οποιαδήποτε κατεύθυνση. Πατήστε ξανά το Space ή το Enter για να αποθέσετε το συνημμένο αρχείο πολυμέσων στη νέα του θέση ή πατήστε το Escape για ακύρωση.", + "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/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index c81f389b9dd2b1..728ca89c73260b 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", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.multiple": "Multiple choice", "compose_form.poll.option_placeholder": "Option {number}", - "compose_form.poll.single": "Pick one", "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.type": "Style", @@ -221,7 +221,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 +433,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}", @@ -506,7 +507,6 @@ "notification.favourite": "{name} favourited your post", "notification.favourite.name_and_others_with_link": "{name} and {count, plural, one {# other} other {# others}} favourited your post", "notification.follow": "{name} followed you", - "notification.follow.name_and_others": "{name} and {count, plural, one {# other} other {# others}} followed you", "notification.follow_request": "{name} has requested to follow you", "notification.follow_request.name_and_others": "{name} and {count, plural, one {# other} other {# others}} has requested to follow you", "notification.label.mention": "Mention", @@ -789,7 +789,7 @@ "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}", "status.embed": "Get embed code", "status.favourite": "Favourite", - "status.favourites": "{count, plural, one {favorite} other {favorites}}", + "status.favourites": "{count, plural, one {favourite} other {favourites}}", "status.filter": "Filter this post", "status.history.created": "{name} created {date}", "status.history.edited": "{name} edited {date}", @@ -850,6 +850,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/en.json b/app/javascript/mastodon/locales/en.json index d0563bb1b2c5cd..46b7d90dba8d50 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Poll duration", "compose_form.poll.multiple": "Multiple choice", "compose_form.poll.option_placeholder": "Option {number}", - "compose_form.poll.single": "Pick one", + "compose_form.poll.single": "Single choice", "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.type": "Style", @@ -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.", @@ -506,7 +508,7 @@ "notification.favourite": "{name} favorited your post", "notification.favourite.name_and_others_with_link": "{name} and {count, plural, one {# other} other {# others}} favorited your post", "notification.follow": "{name} followed you", - "notification.follow.name_and_others": "{name} and {count, plural, one {# other} other {# others}} followed you", + "notification.follow.name_and_others": "{name} and {count, plural, one {# other} other {# others}} followed you", "notification.follow_request": "{name} has requested to follow you", "notification.follow_request.name_and_others": "{name} and {count, plural, one {# other} other {# others}} has requested to follow you", "notification.label.mention": "Mention", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Private reply", "notification.label.reply": "Reply", "notification.mention": "Mention", + "notification.mentioned_you": "{name} mentioned you", "notification.moderation-warning.learn_more": "Learn more", "notification.moderation_warning": "You have received a moderation warning", "notification.moderation_warning.action_delete_statuses": "Some of your posts have been removed.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Quick filter bar", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.group": "Group", "notifications.column_settings.mention": "Mentions:", "notifications.column_settings.poll": "Poll results:", "notifications.column_settings.push": "Push notifications", @@ -850,6 +854,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..6beb5a9716542f 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -13,7 +13,7 @@ "about.rules": "Regularo de la servilo", "account.account_note_header": "Personaj notoj", "account.add_or_remove_from_list": "Aldoni al aŭ forigi el listoj", - "account.badges.bot": "Roboto", + "account.badges.bot": "Aŭtomata", "account.badges.group": "Grupo", "account.block": "Bloki @{name}", "account.block_domain": "Bloki la domajnon {domain}", @@ -22,10 +22,10 @@ "account.cancel_follow_request": "Nuligi peton por sekvado", "account.copy": "Kopii ligilon al profilo", "account.direct": "Private mencii @{name}", - "account.disable_notifications": "Ne plu sciigi min, kiam @{name} mesaĝas", + "account.disable_notifications": "Ĉesu sciigi min kiam @{name} afiŝas", "account.domain_blocked": "Domajno blokita", "account.edit_profile": "Redakti la profilon", - "account.enable_notifications": "Sciigi min, kiam @{name} mesaĝas", + "account.enable_notifications": "Sciigu min kiam @{name} afiŝos", "account.endorse": "Rekomendi ĉe via profilo", "account.featured_tags.last_status_at": "Lasta afîŝo je {date}", "account.featured_tags.last_status_never": "Neniu afiŝo", @@ -49,14 +49,14 @@ "account.mention": "Mencii @{name}", "account.moved_to": "{name} indikis, ke ria nova konto estas nun:", "account.mute": "Silentigi @{name}", - "account.mute_notifications_short": "Silentigu Sciigojn", + "account.mute_notifications_short": "Silentigu sciigojn", "account.mute_short": "Silentigu", "account.muted": "Silentigita", "account.mutual": "Reciproka", "account.no_bio": "Neniu priskribo estas provizita.", "account.open_original_page": "Malfermi la originalan paĝon", "account.posts": "Afiŝoj", - "account.posts_with_replies": "Mesaĝoj kaj respondoj", + "account.posts_with_replies": "Afiŝoj kaj respondoj", "account.report": "Raporti @{name}", "account.requested": "Atendo de aprobo. Klaku por nuligi la peton por sekvado", "account.requested_follow": "{name} petis sekvi vin", @@ -69,7 +69,7 @@ "account.unendorse": "Ne plu rekomendi ĉe la profilo", "account.unfollow": "Ĉesi sekvi", "account.unmute": "Ne plu silentigi @{name}", - "account.unmute_notifications_short": "Malsilentigu Sciigojn", + "account.unmute_notifications_short": "Malsilentigu sciigojn", "account.unmute_short": "Ne plu silentigi", "account_note.placeholder": "Alklaku por aldoni noton", "admin.dashboard.daily_retention": "Uzantoretenprocento lau tag post registro", @@ -81,11 +81,12 @@ "admin.impact_report.instance_followers": "Sekvantojn niaj uzantoj perdus", "admin.impact_report.instance_follows": "Sekvantojn ties uzantoj perdus", "admin.impact_report.title": "Influa reporto", - "alert.rate_limited.message": "Bonvolu reprovi post {retry_time, time, medium}.", + "alert.rate_limited.message": "Bonvolu reprovi poste {retry_time, time, medium}.", "alert.rate_limited.title": "Mesaĝkvante limigita", "alert.unexpected.message": "Neatendita eraro okazis.", "alert.unexpected.title": "Aj!", - "announcement.announcement": "Anoncoj", + "alt_text_badge.title": "Alt-teksto", + "announcement.announcement": "Anonco", "attachments_list.unprocessed": "(neprilaborita)", "audio.hide": "Kaŝi aŭdion", "block_modal.remote_users_caveat": "Ni petos al la servilo {domain} respekti vian elekton. Tamen, plenumo ne estas garantiita ĉar iuj serviloj eble manipulas blokojn malsame. Publikaj afiŝoj eble ankoraŭ estas videbla por ne-ensalutintaj uzantoj.", @@ -104,13 +105,13 @@ "bundle_column_error.error.title": "Ho, ve!", "bundle_column_error.network.body": "Okazis eraro dum ŝarĝado de ĉi tiu paĝo. Tion povas kaŭzi portempa problemo pri via retkonektado aŭ pri ĉi tiu servilo.", "bundle_column_error.network.title": "Eraro de reto", - "bundle_column_error.retry": "Provu refoje", + "bundle_column_error.retry": "Provu denove", "bundle_column_error.return": "Reiri hejmen", "bundle_column_error.routing.body": "La celita paĝo ne troveblas. Ĉu vi certas, ke la retadreso (URL) en via retfoliumilo estas ĝusta?", "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "Fermi", "bundle_modal_error.message": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", - "bundle_modal_error.retry": "Bonvolu reprovi", + "bundle_modal_error.retry": "Provu denove", "closed_registrations.other_server_instructions": "Ĉar Mastodon estas malcentraliza, vi povas krei konton ĉe alia servilo kaj ankoraŭ komuniki kun ĉi tiu.", "closed_registrations_modal.description": "Krei konton ĉe {domain} aktuale ne eblas, tamen bonvole rimarku, ke vi ne bezonas konton specife ĉe {domain} por uzi Mastodon.", "closed_registrations_modal.find_another_server": "Trovi alian servilon", @@ -157,12 +158,12 @@ "compose_form.poll.duration": "Daŭro de la balotenketo", "compose_form.poll.multiple": "Multobla elekto", "compose_form.poll.option_placeholder": "Opcio {number}", - "compose_form.poll.single": "Elektu unu", + "compose_form.poll.single": "Ununura elekto", "compose_form.poll.switch_to_multiple": "Ŝanĝi la balotenketon por permesi multajn elektojn", "compose_form.poll.switch_to_single": "Ŝanĝi la balotenketon por permesi unu solan elekton", "compose_form.poll.type": "Stilo", "compose_form.publish": "Afiŝo", - "compose_form.publish_form": "Afiŝi", + "compose_form.publish_form": "Nova afiŝo", "compose_form.reply": "Respondi", "compose_form.save_changes": "Ĝisdatigi", "compose_form.spoiler.marked": "Forigi la averton de enhavo", @@ -172,7 +173,7 @@ "confirmations.block.confirm": "Bloki", "confirmations.delete.confirm": "Forigi", "confirmations.delete.message": "Ĉu vi certas, ke vi volas forigi ĉi tiun afiŝon?", - "confirmations.delete.title": "Ĉu forigi Afiŝon?", + "confirmations.delete.title": "Ĉu forigi afiŝon?", "confirmations.delete_list.confirm": "Forigi", "confirmations.delete_list.message": "Ĉu vi certas, ke vi volas porĉiame forigi ĉi tiun liston?", "confirmations.delete_list.title": "Ĉu forigi liston?", @@ -181,8 +182,8 @@ "confirmations.edit.confirm": "Redakti", "confirmations.edit.message": "Redakti nun anstataŭigos la skribatan afiŝon. Ĉu vi certas, ke vi volas daŭrigi?", "confirmations.edit.title": "Ĉu superskribi afiŝon?", - "confirmations.logout.confirm": "Adiaŭi", - "confirmations.logout.message": "Ĉu vi certas ke vi volas adiaŭi?", + "confirmations.logout.confirm": "Elsaluti", + "confirmations.logout.message": "Ĉu vi certas, ke vi volas elsaluti?", "confirmations.logout.title": "Ĉu elsaluti?", "confirmations.mute.confirm": "Silentigi", "confirmations.redraft.confirm": "Forigi kaj reskribi", @@ -197,7 +198,7 @@ "content_warning.hide": "Kaŝi afiŝon", "content_warning.show": "Montri ĉiukaze", "conversation.delete": "Forigi konversacion", - "conversation.mark_as_read": "Marki legita", + "conversation.mark_as_read": "Marku kiel legita", "conversation.open": "Vidi konversacion", "conversation.with": "Kun {names}", "copy_icon_button.copied": "Kopiis al kliptabulo", @@ -212,11 +213,31 @@ "dismissable_banner.community_timeline": "Jen la plej novaj publikaj afiŝoj de uzantoj, kies kontojn gastigas {domain}.", "dismissable_banner.dismiss": "Eksigi", "dismissable_banner.explore_links": "Tiuj novaĵoj estas aktuale priparolataj de uzantoj en tiu ĉi kaj aliaj serviloj, sur la malcentrigita reto.", - "dismissable_banner.explore_statuses": "Ĉi tioj estas afiŝoj de socia reto kiu populariĝas hodiau.", + "dismissable_banner.explore_statuses": "Ĉi tiuj estas afiŝoj de la tuta socia reto, kiuj populariĝas hodiaŭ. Pli novaj afiŝoj kun pli da diskonigoj kaj plej ŝatataj estas rangigitaj pli alte.", "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.", + "dismissable_banner.public_timeline": "Ĉi tiuj estas la plej lastatempaj publikaj afiŝoj de homoj en la socia reto, kiujn homoj sur {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", @@ -226,26 +247,26 @@ "emoji_button.food": "Manĝi kaj trinki", "emoji_button.label": "Enmeti emoĝion", "emoji_button.nature": "Naturo", - "emoji_button.not_found": "Neniu emoĝio!! (╯°□°)╯︵ ┻━┻", + "emoji_button.not_found": "Neniuj kongruaj emoĝioj trovitaj", "emoji_button.objects": "Aĵoj", "emoji_button.people": "Homoj", "emoji_button.recent": "Ofte uzataj", - "emoji_button.search": "Serĉo…", + "emoji_button.search": "Serĉo...", "emoji_button.search_results": "Serĉaj rezultoj", "emoji_button.symbols": "Simboloj", "emoji_button.travel": "Vojaĝoj kaj lokoj", "empty_column.account_hides_collections": "Ĉi tiu uzanto elektis ne disponebligi ĉi tiu informon", "empty_column.account_suspended": "Konto suspendita", - "empty_column.account_timeline": "Neniu afiŝo ĉi tie!", - "empty_column.account_unavailable": "Profilo ne disponebla", + "empty_column.account_timeline": "Neniuj afiŝoj ĉi tie!", + "empty_column.account_unavailable": "Profilo nedisponebla", "empty_column.blocks": "Vi ankoraŭ ne blokis uzanton.", "empty_column.bookmarked_statuses": "Vi ankoraŭ ne aldonis afiŝon al viaj legosignoj. Kiam vi aldonos iun, tiu aperos ĉi tie.", "empty_column.community": "La loka templinio estas malplena. Skribu ion por plenigi ĝin!", "empty_column.direct": "Vi ankoraŭ ne havas privatan mencion. Kiam vi sendos aŭ ricevos iun, tiu aperos ĉi tie.", "empty_column.domain_blocks": "Ankoraŭ neniu domajno estas blokita.", "empty_column.explore_statuses": "Nenio tendencas nun. Rekontrolu poste!", - "empty_column.favourited_statuses": "Vi ankoraŭ ne havas stelumitan afiŝon.", - "empty_column.favourites": "Ankoraŭ neniu stelumis tiun afiŝon.", + "empty_column.favourited_statuses": "Vi ankoraŭ ne havas plej ŝatatajn afiŝojn. Kiam vi ŝatatas unu, ĝi aperos ĉi tie.", + "empty_column.favourites": "Neniu ankoraŭ ŝatis ĉi tiun afiŝon. Kiam iu ŝatos ĝin, ili aperos ĉi tie.", "empty_column.follow_requests": "Vi ne ankoraŭ havas iun peton de sekvado. Kiam vi ricevos unu, ĝi aperos ĉi tie.", "empty_column.followed_tags": "Vi ankoraŭ ne sekvas iujn kradvortojn. Kiam vi faras, ili aperos ĉi tie.", "empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.", @@ -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.", @@ -274,7 +296,7 @@ "filter_modal.added.review_and_configure": "Por kontroli kaj pli modifi ĉi tiu filtrilkategorio, iru al la {settings_link}.", "filter_modal.added.review_and_configure_title": "Filtrilopcioj", "filter_modal.added.settings_link": "opciopaĝo", - "filter_modal.added.short_explanation": "Ĉi tiu mesaĝo aldonitas al la filtrilkategorio: {title}.", + "filter_modal.added.short_explanation": "Ĉi tiu afiŝo aldonitas al la filtrilkategorio: {title}.", "filter_modal.added.title": "Filtrilo aldonita!", "filter_modal.select_filter.context_mismatch": "ne kongruas la kuntekston", "filter_modal.select_filter.expired": "eksvalidiĝinta", @@ -282,17 +304,29 @@ "filter_modal.select_filter.search": "Serĉi aŭ krei", "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_modal.title.status": "Filtri afiŝ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", @@ -309,7 +343,7 @@ "hashtag.column_header.tag_mode.all": "kaj {additional}", "hashtag.column_header.tag_mode.any": "aŭ {additional}", "hashtag.column_header.tag_mode.none": "sen {additional}", - "hashtag.column_settings.select.no_options_message": "Neniu sugesto trovita", + "hashtag.column_settings.select.no_options_message": "Neniuj sugestoj trovitaj", "hashtag.column_settings.select.placeholder": "Enmeti kradvortojn…", "hashtag.column_settings.tag_mode.all": "Ĉiuj", "hashtag.column_settings.tag_mode.any": "Iu ajn", @@ -317,10 +351,18 @@ "hashtag.column_settings.tag_toggle": "Aldoni pliajn etikedojn por ĉi tiu kolumno", "hashtag.counter_by_accounts": "{count, plural,one {{counter} partoprenanto} other {{counter} partoprenantoj}}", "hashtag.counter_by_uses": "{count, plural,one {{counter} afiŝo} other {{counter} afiŝoj}}", - "hashtag.counter_by_uses_today": "{count, plural,one {{counter} afiŝo} other {{counter} afiŝoj}} hodiau", + "hashtag.counter_by_uses_today": "{count, plural,one {{counter} afiŝo} other {{counter} afiŝoj}} hodiaŭ", "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,10 +370,21 @@ "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.follow": "Kun konto ĉe Mastodon, vi povas sekvi {name} por ricevi iliajn afiŝojn en via hejma fluo.", "interaction_modal.description.reblog": "Kun konto ĉe Mastodon, vi povas diskonigi ĉi tiun afiŝon, por ke viaj propraj sekvantoj vidu ĝin.", - "interaction_modal.description.reply": "Kun konto ĉe Mastodon, vi povos respondi al ĉi tiu mesaĝo.", + "interaction_modal.description.reply": "Kun konto ĉe Mastodon, vi povos respondi al ĉi tiu afiŝo.", "interaction_modal.login.action": "Prenu min hejmen", "interaction_modal.login.prompt": "Domajno de via hejma servilo, ekz. mastodon.social", "interaction_modal.no_account_yet": "Ĉu ne estas ĉe Mastodon?", @@ -346,48 +399,49 @@ "intervals.full.days": "{number, plural, one {# tago} other {# tagoj}}", "intervals.full.hours": "{number, plural, one {# horo} other {# horoj}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutoj}}", - "keyboard_shortcuts.back": "reveni", + "keyboard_shortcuts.back": "Reiru reen", "keyboard_shortcuts.blocked": "Malfermi la liston de blokitaj uzantoj", "keyboard_shortcuts.boost": "Diskonigi la mesaĝon", - "keyboard_shortcuts.column": "fokusi mesaĝon en unu el la kolumnoj", - "keyboard_shortcuts.compose": "enfokusigi la tekstujon", + "keyboard_shortcuts.column": "Fokusi kolumnon", + "keyboard_shortcuts.compose": "Enfokusigi la tekstaron", "keyboard_shortcuts.description": "Priskribo", "keyboard_shortcuts.direct": "por malfermi la kolumnon pri privataj mencioj", - "keyboard_shortcuts.down": "iri suben en la listo", - "keyboard_shortcuts.enter": "malfermi mesaĝon", + "keyboard_shortcuts.down": "Movu malsupren en la listo", + "keyboard_shortcuts.enter": "Malfermi afiŝon", "keyboard_shortcuts.favourite": "Stelumi afiŝon", "keyboard_shortcuts.favourites": "Malfermi la liston de la stelumoj", "keyboard_shortcuts.federated": "Malfermi la frataran templinion", - "keyboard_shortcuts.heading": "Klavaraj mallongigoj", + "keyboard_shortcuts.heading": "Fulmoklavoj", "keyboard_shortcuts.home": "Malfermi la hejman templinion", "keyboard_shortcuts.hotkey": "Rapidklavo", - "keyboard_shortcuts.legend": "montri ĉi tiun noton", - "keyboard_shortcuts.local": "Malfermi la lokan templinion", - "keyboard_shortcuts.mention": "mencii la aŭtoron", - "keyboard_shortcuts.muted": "malfermi la liston de silentigitaj uzantoj", - "keyboard_shortcuts.my_profile": "malfermi vian profilon", - "keyboard_shortcuts.notifications": "malfermi la kolumnon de sciigoj", - "keyboard_shortcuts.open_media": "Malfermi plurmedion", - "keyboard_shortcuts.pinned": "malfermi la liston de alpinglitaj mesaĝoj", - "keyboard_shortcuts.profile": "malfermi la profilon de la aŭtoro", - "keyboard_shortcuts.reply": "respondi", + "keyboard_shortcuts.legend": "Montru ĉi tiun legendon", + "keyboard_shortcuts.local": "Malfermu la lokan templinion", + "keyboard_shortcuts.mention": "Menciu aŭtoron", + "keyboard_shortcuts.muted": "Malfermu la liston de silentigitaj uzantoj", + "keyboard_shortcuts.my_profile": "Malfermu vian profilon", + "keyboard_shortcuts.notifications": "Malfermu la sciigajn kolumnon", + "keyboard_shortcuts.open_media": "Malfermu plurmedion", + "keyboard_shortcuts.pinned": "Malfermu alpinglitajn afiŝojn-liston", + "keyboard_shortcuts.profile": "Malfermu la profilon de aŭtoro", + "keyboard_shortcuts.reply": "Respondu al afiŝo", "keyboard_shortcuts.requests": "Malfermi la liston de petoj por sekvado", - "keyboard_shortcuts.search": "enfokusigi la serĉilon", - "keyboard_shortcuts.spoilers": "Montri/kaŝi la kampon de averto de enhavo (\"CW\")", - "keyboard_shortcuts.start": "malfermi la kolumnon «por komenci»", - "keyboard_shortcuts.toggle_hidden": "Montri/kaŝi tekston malantaŭ la averto de enhavo (\"CW\")", + "keyboard_shortcuts.search": "Enfokusigi la serĉbreton", + "keyboard_shortcuts.spoilers": "Montri/kaŝi CW-kampon", + "keyboard_shortcuts.start": "Malfermu \"por komenci\" kolumnon", + "keyboard_shortcuts.toggle_hidden": "Montri/kaŝi tekston malantaŭ CW", "keyboard_shortcuts.toggle_sensitivity": "Montri/kaŝi plurmedion", - "keyboard_shortcuts.toot": "Krei novan mesaĝon", - "keyboard_shortcuts.unfocus": "malenfokusigi la tekstujon aŭ la serĉilon", - "keyboard_shortcuts.up": "iri supren en la listo", + "keyboard_shortcuts.toot": "Komencu novan afiŝon", + "keyboard_shortcuts.unfocus": "Senfokusigi verki tekstareon/serĉon", + "keyboard_shortcuts.up": "Movu 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,17 +461,24 @@ "loading_indicator.label": "Ŝargado…", "media_gallery.hide": "Kaŝi", "moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.", + "mute_modal.hide_from_notifications": "Kaŝi de sciigoj", + "mute_modal.hide_options": "Kaŝi agordojn", + "mute_modal.indefinite": "Ĝis mi malsilentas ilin", "mute_modal.show_options": "Montri agordojn", "mute_modal.they_can_mention_and_follow": "Ili povas mencii kaj sekvi vin, sed vi ne vidos ilin.", + "mute_modal.they_wont_know": "Ili ne scios, ke ili estas silentigitaj.", + "mute_modal.title": "Ĉu silentigi uzanton?", + "mute_modal.you_wont_see_mentions": "Vi ne vidos afiŝojn, kiuj mencias ilin.", + "mute_modal.you_wont_see_posts": "Ili ankoraŭ povas vidi viajn afiŝojn, sed vi ne vidos iliajn.", "navigation_bar.about": "Pri", "navigation_bar.administration": "Administrado", "navigation_bar.advanced_interface": "Malfermi altnivelan retpaĝan interfacon", "navigation_bar.blocks": "Blokitaj uzantoj", "navigation_bar.bookmarks": "Legosignoj", "navigation_bar.community_timeline": "Loka templinio", - "navigation_bar.compose": "Skribi novan mesaĝon", + "navigation_bar.compose": "Redakti novan afiŝon", "navigation_bar.direct": "Privataj mencioj", - "navigation_bar.discover": "Esplori", + "navigation_bar.discover": "Malkovri", "navigation_bar.domain_blocks": "Blokitaj domajnoj", "navigation_bar.explore": "Esplori", "navigation_bar.favourites": "Stelumoj", @@ -426,55 +487,101 @@ "navigation_bar.followed_tags": "Sekvataj kradvortoj", "navigation_bar.follows_and_followers": "Sekvatoj kaj sekvantoj", "navigation_bar.lists": "Listoj", - "navigation_bar.logout": "Adiaŭi", + "navigation_bar.logout": "Elsaluti", + "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", - "navigation_bar.pins": "Alpinglitaj mesaĝoj", + "navigation_bar.pins": "Alpinglitaj afiŝoj", "navigation_bar.preferences": "Preferoj", "navigation_bar.public_timeline": "Fratara templinio", "navigation_bar.search": "Serĉi", "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.mentioned_you": "{name} menciis vin", "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.group": "Grupo", "notifications.column_settings.mention": "Mencioj:", "notifications.column_settings.poll": "Balotenketaj rezultoj:", "notifications.column_settings.push": "Puŝsciigoj", "notifications.column_settings.reblog": "Diskonigoj:", "notifications.column_settings.show": "Montri en kolumno", "notifications.column_settings.sound": "Eligi sonon", - "notifications.column_settings.status": "Novaj mesaĝoj:", + "notifications.column_settings.status": "Novaj afiŝoj:", "notifications.column_settings.unread_notifications.category": "Nelegitaj sciigoj", "notifications.column_settings.unread_notifications.highlight": "Marki nelegitajn sciigojn", "notifications.column_settings.update": "Redaktoj:", "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,18 +592,33 @@ "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", "onboarding.action.back": "Prenu min reen", "onboarding.actions.back": "Prenu min reen", - "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", + "onboarding.actions.go_to_explore": "Konduku min al tendenco", + "onboarding.actions.go_to_home": "Konduku min al mia hejma fluo", "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", @@ -512,17 +634,17 @@ "onboarding.share.message": "Mi estas {username} en #Mastodon! Sekvu min ĉe {url}", "onboarding.share.next_steps": "Eblaj malantauaj paŝoj:", "onboarding.share.title": "Disvastigi vian profilon", - "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", - "onboarding.start.skip": "Want to skip right ahead?", + "onboarding.start.lead": "Vi nun estas parto de Mastodon, unika, malcentralizita socia amaskomunikilara platformo, kie vi—ne algoritmo—zorgas vian propran sperton. Ni komencu vin sur ĉi tiu nova socia limo:", + "onboarding.start.skip": "Ĉu vi ne bezonas helpon por komenci?", "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.follow_people.body": "Sekvi interesajn homojn estas pri kio Mastodonto temas.", + "onboarding.steps.follow_people.title": "Agordu vian hejman fluon", + "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", - "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", - "onboarding.steps.share_profile.title": "Share your profile", + "onboarding.steps.setup_profile.body": "Diskonigu viajn interagojn havante ampleksan profilon.", + "onboarding.steps.setup_profile.title": "Agordu vian profilon", + "onboarding.steps.share_profile.body": "Sciigu viajn amikojn kiel trovi vin sur Mastodon", + "onboarding.steps.share_profile.title": "Kunhavigu vian Mastodon-profilon", "onboarding.tips.2fa": "Ĉu vi scias? Vi povas sekurigi vian konton per efektivigi dufaktora autentigo en via kontoagordoj.", "onboarding.tips.accounts_from_other_servers": "Ĉu vi scias? Ĉar Mastodon estas sencentra, kelkaj profiloj kiujn vi trovi estas gastigitaj ĉe aliaj serviloj kiuj ne estas via.", "onboarding.tips.migration": "Ĉu vi scias? Se vi sentas ke {domain} ne estas bona servilelekto por vi en la estonteco, vi povas translokiĝi al alia servilo de Mastodon sen malgajni viajn sekvantojn.", @@ -540,13 +662,14 @@ "poll.votes": "{votes, plural, one {# voĉdono} other {# voĉdonoj}}", "poll_button.add_poll": "Aldoni balotenketon", "poll_button.remove_poll": "Forigi balotenketon", - "privacy.change": "Agordi mesaĝan privatecon", + "privacy.change": "Ŝanĝu afiŝan privatecon", "privacy.direct.long": "Ĉiuj menciitaj en la afiŝo", "privacy.direct.short": "Specifaj homoj", "privacy.private.long": "Nur viaj sekvantoj", "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 +689,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 +734,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,25 +768,32 @@ "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}", "status.admin_domain": "Malfermu moderigan interfacon por {domain}", - "status.admin_status": "Malfermi ĉi tiun mesaĝon en la kontrola interfaco", + "status.admin_status": "Malfermi ĉi tiun afiŝon en la kontrola interfaco", "status.block": "Bloki @{name}", "status.bookmark": "Aldoni al la legosignoj", "status.cancel_reblog_private": "Ne plu diskonigi", "status.cannot_reblog": "Ĉi tiun afiŝon ne eblas diskonigi", - "status.copy": "Kopii la ligilon al la mesaĝo", + "status.continued_thread": "Daŭrigis fadenon", + "status.copy": "Kopii la ligilon al la afiŝ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}", @@ -670,16 +805,18 @@ "status.more": "Pli", "status.mute": "Silentigi @{name}", "status.mute_conversation": "Silentigi konversacion", - "status.open": "Disvolvi la mesaĝon", + "status.open": "Pligrandigu ĉi tiun afiŝon", "status.pin": "Alpingli al la profilo", - "status.pinned": "Alpinglita mesaĝo", + "status.pinned": "Alpinglita afiŝo", "status.read_more": "Legi pli", "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", @@ -689,7 +826,7 @@ "status.show_less_all": "Montri malpli ĉiun", "status.show_more_all": "Montri pli ĉiun", "status.show_original": "Montru originalon", - "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", + "status.title.with_attachments": "{user} afiŝis {attachmentCount, plural, one {aldonaĵon} other {{attachmentCount} aldonaĵojn}}", "status.translate": "Traduki", "status.translated_from_with": "Tradukita el {lang} per {provider}", "status.uncached_media_warning": "Antaŭrigardo ne disponebla", @@ -712,11 +849,16 @@ "units.short.million": "{count}M", "units.short.thousand": "{count}K", "upload_area.title": "Altreni kaj lasi por alŝuti", - "upload_button.label": "Aldoni aŭdovidaĵon (JPEG, PNG, GIF, WebM, MP4, MOV)", + "upload_button.label": "Aldonu bildojn, filmeton aŭ sondosieron", "upload_error.limit": "Limo de dosiera alŝutado transpasita.", "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", @@ -730,17 +872,17 @@ "upload_modal.hint": "Klaku aŭ trenu la cirklon en la antaŭvidilo por elekti la fokuspunkton kiu ĉiam videblos en ĉiuj etigitaj bildoj.", "upload_modal.preparing_ocr": "Preparante OSR…", "upload_modal.preview_label": "Antaŭvido ({ratio})", - "upload_progress.label": "Alŝutado…", + "upload_progress.label": "Alŝutante...", "upload_progress.processing": "Traktante…", "username.taken": "La uzantnomo estas jam posedita. Provu alion", - "video.close": "Fermi la videon", + "video.close": "Fermu la filmeton", "video.download": "Elŝuti dosieron", "video.exit_fullscreen": "Eksigi plenekrana", "video.expand": "Pligrandigi la videon", "video.fullscreen": "Igi plenekrana", - "video.hide": "Kaŝi la videon", + "video.hide": "Kaŝu la filmeton", "video.mute": "Silentigi", - "video.pause": "Paŭzi", + "video.pause": "Paŭzigi", "video.play": "Ekigi", "video.unmute": "Malsilentigi" } diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 968b01babc28eb..2410c278a6122b 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.multiple": "Múltiples opciones", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.single": "Elegí una", + "compose_form.poll.single": "Opción única", "compose_form.poll.switch_to_multiple": "Cambiar encuesta para permitir opciones múltiples", "compose_form.poll.switch_to_single": "Cambiar encuesta para permitir una sola opción", "compose_form.poll.type": "Estilo", @@ -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.", @@ -247,7 +249,7 @@ "emoji_button.nature": "Naturaleza", "emoji_button.not_found": "No se encontraron emojis coincidentes", "emoji_button.objects": "Objetos", - "emoji_button.people": "Cuentas", + "emoji_button.people": "Gente", "emoji_button.recent": "Usados frecuentemente", "emoji_button.search": "Buscar...", "emoji_button.search_results": "Resultados de búsqueda", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} marcó tu mensaje como favorito", "notification.favourite.name_and_others_with_link": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}} marcaron tu mensaje como favorito", "notification.follow": "{name} te empezó a seguir", - "notification.follow.name_and_others": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}} te están siguiendo", + "notification.follow.name_and_others": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}} te están siguiendo", "notification.follow_request": "{name} solicitó seguirte", "notification.follow_request.name_and_others": "{name} y {count, plural, one {# cuenta más} other {# cuentas más}} solicitaron seguirte", "notification.label.mention": "Mención", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Respuesta privada", "notification.label.reply": "Respuesta", "notification.mention": "Mención", + "notification.mentioned_you": "{name} te mencionó", "notification.moderation-warning.learn_more": "Aprendé más", "notification.moderation_warning": "Recibiste una advertencia de moderación", "notification.moderation_warning.action_delete_statuses": "Se eliminaron algunos de tus mensajes.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", "notifications.column_settings.follow": "Nuevos seguidores:", "notifications.column_settings.follow_request": "Nuevas solicitudes de seguimiento:", + "notifications.column_settings.group": "Agrupar", "notifications.column_settings.mention": "Menciones:", "notifications.column_settings.poll": "Resultados de la encuesta:", "notifications.column_settings.push": "Notificaciones push", @@ -850,6 +854,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..2f9d1feb0139c2 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?", @@ -157,9 +158,9 @@ "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.multiple": "Selección múltiple", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.single": "Seleccione uno", - "compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones", - "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción", + "compose_form.poll.single": "Selección única", + "compose_form.poll.switch_to_multiple": "Cambiar la encuesta para permitir múltiples opciones", + "compose_form.poll.switch_to_single": "Cambiar la encuesta para permitir una única opción", "compose_form.poll.type": "Estilo", "compose_form.publish": "Publicación", "compose_form.publish_form": "Publicar", @@ -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", @@ -506,7 +508,7 @@ "notification.favourite": "{name} marcó como favorita tu publicación", "notification.favourite.name_and_others_with_link": "{name} y {count, plural, one {# otro} other {# otros}} marcaron tu publicación como favorita", "notification.follow": "{name} te empezó a seguir", - "notification.follow.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} te siguieron", + "notification.follow.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} te han seguido", "notification.follow_request": "{name} ha solicitado seguirte", "notification.follow_request.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} han solicitado seguirte", "notification.label.mention": "Mención", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Respuesta privada", "notification.label.reply": "Respuesta", "notification.mention": "Mención", + "notification.mentioned_you": "{name} te mencionó", "notification.moderation-warning.learn_more": "Saber más", "notification.moderation_warning": "Has recibido una advertencia de moderación", "notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", "notifications.column_settings.follow": "Nuevos seguidores:", "notifications.column_settings.follow_request": "Nuevas solicitudes de seguimiento:", + "notifications.column_settings.group": "Grupo", "notifications.column_settings.mention": "Menciones:", "notifications.column_settings.poll": "Resultados de la votación:", "notifications.column_settings.push": "Notificaciones push", @@ -641,7 +645,7 @@ "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", - "onboarding.tips.2fa": "¿Sabías que? Puedes proteger tu cuenta configurando la autenticación de dos factores en la configuración de su cuenta. Funciona con cualquier aplicación TOTP de su elección, ¡no necesitas número de teléfono!", + "onboarding.tips.2fa": "¿Sabías que? Puedes proteger tu cuenta configurando la autenticación de dos factores en los ajustes de su cuenta. Funciona con cualquier aplicación TOTP que elijas, ¡sin necesidad de número de teléfono!", "onboarding.tips.accounts_from_other_servers": "¿Sabías que? Como Mastodon es descentralizado, algunos perfiles que encuentras están alojados en servidores distintos del tuyo. Y sin embargo, ¡puedes interactuar con ellos! ¡Su servidor corresponde a la segunda mitad de su nombre de usuario!", "onboarding.tips.migration": "¿Sabías que? Si sientes que {domain} no es una gran elección de servidor para ti en el futuro, puedes moverte a otro servidor de Mastodon sin perder a tus seguidores. ¡Incluso puedes alojar tu propio servidor!", "onboarding.tips.verification": "¿Sabías que? Puedes verificar tu cuenta poniendo un enlace a tu perfil de Mastodon en su propio sitio web y añadiendo el sitio web a su perfil. ¡Sin necesidad de comisiones ni documentos!", @@ -850,6 +854,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 adjunto, pulsa la barra espaciadora o la tecla Intro. Mientras arrastras, usa las teclas de flecha para mover el archivo adjunto en cualquier dirección. Vuelve a pulsar la barra espaciadora o la tecla Intro para soltar el archivo adjunto en su nueva posición, o pulsa la tecla Escape para cancelar.", + "upload_form.drag_and_drop.on_drag_cancel": "Arrastre cancelado. El archivo adjunto {item} fue eliminado.", + "upload_form.drag_and_drop.on_drag_end": "El archivo adjunto {item} fue eliminado.", + "upload_form.drag_and_drop.on_drag_over": "El archivo adjunto {item} fue movido.", + "upload_form.drag_and_drop.on_drag_start": "Recogidos los archivos adjuntos {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..fa4159abce7710 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Duración de la encuesta", "compose_form.poll.multiple": "Selección múltiple", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.single": "Elige uno", + "compose_form.poll.single": "Opción única", "compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones", "compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción", "compose_form.poll.type": "Estilo", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} marcó como favorita tu publicación", "notification.favourite.name_and_others_with_link": "{name} y {count, plural, one {# más} other {# más}} marcaron tu publicación como favorita", "notification.follow": "{name} te empezó a seguir", - "notification.follow.name_and_others": "{name} y {count, plural, one {# más} other {# más}} te siguieron", + "notification.follow.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} te siguieron", "notification.follow_request": "{name} ha solicitado seguirte", "notification.follow_request.name_and_others": "{name} y {count, plural, one {# más} other {# más}} han solicitado seguirte", "notification.label.mention": "Mención", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Respuesta privada", "notification.label.reply": "Respuesta", "notification.mention": "Mención", + "notification.mentioned_you": "{name} te ha mencionado", "notification.moderation-warning.learn_more": "Saber más", "notification.moderation_warning": "Has recibido una advertencia de moderación", "notification.moderation_warning.action_delete_statuses": "Se han eliminado algunas de tus publicaciones.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", "notifications.column_settings.follow": "Nuevos seguidores:", "notifications.column_settings.follow_request": "Nuevas solicitudes de seguimiento:", + "notifications.column_settings.group": "Grupo", "notifications.column_settings.mention": "Menciones:", "notifications.column_settings.poll": "Resultados de la votación:", "notifications.column_settings.push": "Notificaciones push", @@ -637,7 +641,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 +854,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..3c58548eb77892 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Kiiruspiirang", "alert.unexpected.message": "Tekkis ootamatu viga.", "alert.unexpected.title": "Oih!", + "alt_text_badge.title": "Alternatiivtekst", "announcement.announcement": "Teadaanne", "attachments_list.unprocessed": "(töötlemata)", "audio.hide": "Peida audio", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Küsitluse kestus", "compose_form.poll.multiple": "Mitu vastust", "compose_form.poll.option_placeholder": "Valik {number}", - "compose_form.poll.single": "Vali üks", "compose_form.poll.switch_to_multiple": "Muuda küsitlust mitmikvaliku lubamiseks", "compose_form.poll.switch_to_single": "Muuda küsitlust ainult ühe valiku lubamiseks", "compose_form.poll.type": "Stiil", @@ -221,7 +221,8 @@ "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_will_lose_num_followers": "Sult kaob {followersCount, plural, one {{followersCountDisplay} jälgija} other {{followersCountDisplay} jälgijat}} ja {followingCount, plural, one {{followingCountDisplay} inimene} other {{followingCountDisplay} inimest}}, keda sa ise jälgid.", + "domain_block_modal.you_will_lose_relationships": "Sa kaotad kõik oma jälgijad ja inimesed, kes sind jälgivad sellest serverist.", "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,10 +433,10 @@ "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", + "lightbox.zoom_in": "Näita algsuuruses", + "lightbox.zoom_out": "Näita kõik", "limited_account_hint.action": "Näita profilli sellegipoolest", "limited_account_hint.title": "See profiil on peidetud {domain} moderaatorite poolt.", "link_preview.author": "{name} poolt", @@ -506,7 +507,6 @@ "notification.favourite": "{name} märkis su postituse lemmikuks", "notification.favourite.name_and_others_with_link": "{name} ja {count, plural, one {# veel} other {# teist}} märkis su postituse lemmikuks", "notification.follow": "{name} alustas su jälgimist", - "notification.follow.name_and_others": "{name} ja {count, plural, one {# veel} other {# teist}} hakkas sind jälgima", "notification.follow_request": "{name} soovib sind jälgida", "notification.follow_request.name_and_others": "{name} ja {count, plural, one {# veel} other {# teist}} taotles sinu jälgimist", "notification.label.mention": "Mainimine", @@ -514,6 +514,7 @@ "notification.label.private_reply": "Privaatne vastus", "notification.label.reply": "Vastus", "notification.mention": "Mainimine", + "notification.mentioned_you": "{name} mainis sind", "notification.moderation-warning.learn_more": "Vaata lisa", "notification.moderation_warning": "Said modereerimise hoiatuse", "notification.moderation_warning.action_delete_statuses": "Mõni su postitus on eemaldatud.", @@ -850,6 +851,11 @@ "upload_error.poll": "Küsitlustes pole faili üleslaadimine lubatud.", "upload_form.audio_description": "Kirjelda kuulmispuudega inimeste jaoks", "upload_form.description": "Kirjelda vaegnägijatele", + "upload_form.drag_and_drop.instructions": "Vajuta tühikut või enterit, et tõsta manus. Lohistamise ajal kasuta nooleklahve, et manust liigutada teatud suunas. Vajuta tühikut või enterit uuesti, et paigutada manus oma uuele kohale, või escape tühistamiseks.", + "upload_form.drag_and_drop.on_drag_cancel": "Lohistamine tühistati. Manus {item} on asetatud.", + "upload_form.drag_and_drop.on_drag_end": "Manus {item} on asetatud.", + "upload_form.drag_and_drop.on_drag_over": "Manus {item} on liigutatud.", + "upload_form.drag_and_drop.on_drag_start": "Tõstetud on manus {item}.", "upload_form.edit": "Muuda", "upload_form.thumbnail": "Muuda pisipilti", "upload_form.video_description": "Kirjelda kuulmis- või nägemispuudega inimeste jaoks", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index acdd27ce2bea5d..cd8fbeefbc44b1 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", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Inkestaren iraupena", "compose_form.poll.multiple": "Aukera aniza", "compose_form.poll.option_placeholder": "{number}. aukera", - "compose_form.poll.single": "Hautatu bat", "compose_form.poll.switch_to_multiple": "Aldatu inkesta hainbat aukera onartzeko", "compose_form.poll.switch_to_single": "Aldatu inkesta aukera bakarra onartzeko", "compose_form.poll.type": "Estiloa", @@ -221,7 +221,6 @@ "domain_block_modal.they_cant_follow": "Zerbitzari honetako inork ezin zaitu jarraitu.", "domain_block_modal.they_wont_know": "Ez dute jakingo blokeatuak izan direnik.", "domain_block_modal.title": "Domeinua blokeatu nahi duzu?", - "domain_block_modal.you_will_lose_followers": "Zerbitzari honetako jarraitzaile guztiak kenduko dira.", "domain_block_modal.you_wont_see_posts": "Ez dituzu zerbitzari honetako erabiltzaileen argitalpenik edota jakinarazpenik ikusiko.", "domain_pill.activitypub_lets_connect": "Mastodon-en ez ezik, beste sare sozialen aplikazioetako jendearekin konektatzea eta harremanetan jartzea uzten dizu.", "domain_pill.activitypub_like_language": "ActivityPub, Mastodon-ek beste sare sozialekin hitz egiteko erabiltzen duen hizkuntza bezalakoxea da.", @@ -268,7 +267,7 @@ "empty_column.follow_requests": "Ez duzu jarraitzeko eskaerarik oraindik. Baten bat jasotzen duzunean, hemen agertuko da.", "empty_column.followed_tags": "Oraindik ez duzu traolik jarraitzen. Egiterakoan, hemen agertuko dira.", "empty_column.hashtag": "Ez dago ezer traola honetan oraindik.", - "empty_column.home": "Zure hasierako denbora-lerroa hutsik dago! Ikusi {public} edo erabili bilaketa lehen urratsak eman eta beste batzuk aurkitzeko.", + "empty_column.home": "Zure hasierako denbora-lerroa hutsik dago! Jarraitu jende gehiago betetzeko.", "empty_column.list": "Ez dago ezer zerrenda honetan. Zerrenda honetako kideek bidalketa berriak argitaratzean, hemen agertuko dira.", "empty_column.lists": "Ez duzu zerrendarik oraindik. Baten bat sortzen duzunean hemen agertuko da.", "empty_column.mutes": "Ez duzu erabiltzailerik mututu oraindik.", @@ -432,8 +431,6 @@ "keyboard_shortcuts.unfocus": "testua konposatzeko area / bilaketatik fokua kentzea", "keyboard_shortcuts.up": "zerrendan gora mugitzea", "lightbox.close": "Itxi", - "lightbox.compress": "Konprimatu irudia ikusteko kaxa", - "lightbox.expand": "Zabaldu irudia ikusteko kaxa", "lightbox.next": "Hurrengoa", "lightbox.previous": "Aurrekoa", "limited_account_hint.action": "Erakutsi profila hala ere", @@ -506,7 +503,6 @@ "notification.favourite": "{name}(e)k zure bidalketa gogoko du", "notification.favourite.name_and_others_with_link": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} zure bidalketa gogoko dute", "notification.follow": "{name}(e)k jarraitzen dizu", - "notification.follow.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} jarraitu dizute", "notification.follow_request": "{name}(e)k zu jarraitzeko eskaera egin du", "notification.follow_request.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} zu jarraitzeko eskaera egin dute", "notification.label.mention": "Aipamena", @@ -599,7 +595,7 @@ "notifications.policy.filter_not_following_title": "Jarraitzen ez duzun jendea", "notifications.policy.filter_private_mentions_hint": "Iragazita, baldin eta zure aipamenaren erantzuna bada edo bidaltzailea jarraitzen baduzu", "notifications.policy.filter_private_mentions_title": "Eskatu gabeko aipamen pribatuak", - "notifications.policy.title": "Kudeatu honen jakinarazpaenak…", + "notifications.policy.title": "Kudeatu honen jakinarazpenak…", "notifications_permission_banner.enable": "Gaitu mahaigaineko jakinarazpenak", "notifications_permission_banner.how_to_control": "Mastodon irekita ez dagoenean jakinarazpenak jasotzeko, gaitu mahaigaineko jakinarazpenak. Mahaigaineko jakinarazpenak ze elkarrekintzak eragingo dituzten zehazki kontrolatu dezakezu goiko {icon} botoia erabiliz, gaituta daudenean.", "notifications_permission_banner.title": "Ez galdu ezer inoiz", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index fba8d902351362..6afdb537466f96 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": "نمی‌توانند نامتان را برده یا پی‌تان بگیرند.", @@ -156,7 +158,6 @@ "compose_form.poll.duration": "مدت نظرسنجی", "compose_form.poll.multiple": "چند گزینه‌ای", "compose_form.poll.option_placeholder": "گزینهٔ {number}", - "compose_form.poll.single": "گزینش یکی", "compose_form.poll.switch_to_multiple": "تغییر نظرسنجی برای اجازه به چندین گزینه", "compose_form.poll.switch_to_single": "تبدیل به نظرسنجی تک‌گزینه‌ای", "compose_form.poll.type": "سبک", @@ -220,8 +221,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": "خانهٔ رقمیش. جایی که همهٔ فرسته‌هایش می‌زیند.", @@ -369,6 +372,7 @@ "ignore_notifications_modal.new_accounts_title": "چشم‌پوشی از آگاهی‌های حساب‌های جدید؟", "ignore_notifications_modal.not_followers_title": "چشم‌پوشی از آگاهی‌های افرادی که پیتان نمی‌گیرند؟", "ignore_notifications_modal.not_following_title": "چشم‌پوشی از آگاهی‌های افرادی که پیشان نمی‌گیرید؟", + "ignore_notifications_modal.private_mentions_title": "چشم‌پوشی از نام‌بری‌های خصوصی ناخواسته؟", "interaction_modal.description.favourite": "با حسابی روی ماستودون می‌توانید این فرسته را برگزیده تا نگارنده بداند قدردانش هستید و برای آینده ذخیره‌اش می‌کنید.", "interaction_modal.description.follow": "با حسابی روی ماستودون می‌توانید {name} را برای دریافت فرسته‌هایش در خوراک خانگیتان دنبال کنید.", "interaction_modal.description.reblog": "با حسابی روی ماستودون می‌توانید این فرسته را با پی‌گیران خودتان هم‌رسانی کنید.", @@ -422,8 +426,6 @@ "keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جست‌وجو", "keyboard_shortcuts.up": "بالا بردن در سیاهه", "lightbox.close": "بستن", - "lightbox.compress": "فشرده‌سازی جعبهٔ نمایش تصویر", - "lightbox.expand": "گسترش جعبهٔ نمایش تصویر", "lightbox.next": "بعدی", "lightbox.previous": "قبلی", "limited_account_hint.action": "به هر روی نمایه نشان داده شود", @@ -492,7 +494,6 @@ "notification.favourite": "{name} فرسته‌تان را برگزید", "notification.favourite.name_and_others_with_link": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} فرسته‌تان را برگزیدند", "notification.follow": "‫{name}‬ پی‌گیرتان شد", - "notification.follow.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} پیتان گرفتند", "notification.follow_request": "{name} درخواست پی‌گیریتان را داد", "notification.follow_request.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} درخواست پی‌گیریتان را دادند", "notification.label.mention": "اشاره", @@ -552,7 +553,7 @@ "notifications.filter.all": "همه", "notifications.filter.boosts": "تقویت‌ها", "notifications.filter.favourites": "برگزیده‌ها", - "notifications.filter.follows": "پی‌گرفتگان", + "notifications.filter.follows": "پی‌گرفتن‌ها", "notifications.filter.mentions": "اشاره‌ها", "notifications.filter.polls": "نتایج نظرسنجی", "notifications.filter.statuses": "به‌روز رسانی‌ها از کسانی که پی‌گیرشانید", @@ -570,10 +571,14 @@ "notifications.policy.filter_hint": "فرستادن به صندوق آگاهی‌های پالوده", "notifications.policy.filter_limited_accounts_hint": "محدود شده به دست ناظم‌های کارساز", "notifications.policy.filter_limited_accounts_title": "حساب‌های مدیریت شده", + "notifications.policy.filter_new_accounts.hint": "ساخته شده در {days, plural, one {یک} other {#}} روز اخیر", "notifications.policy.filter_new_accounts_title": "حساب‌های جدید", + "notifications.policy.filter_not_followers_hint": "از جمله کسانی که کم‌تر از {days, plural, one {یک} other {#}} روز است پی‌تان می‌گیرند", "notifications.policy.filter_not_followers_title": "کسانی که شما را دنبال میکنند", - "notifications.policy.filter_not_following_hint": "", + "notifications.policy.filter_not_following_hint": "تا به صورت دستی تأییدشان کنید", "notifications.policy.filter_not_following_title": "کسانی که پی نمی‌گیرید", + "notifications.policy.filter_private_mentions_hint": "پالوده مگر این که به نام‌بری خودتان پاسخ داده یا پی‌گیر فرستنده باشید", + "notifications.policy.filter_private_mentions_title": "نام‌بری‌های خصوصی ناخواسته", "notifications.policy.title": "مدیریت آگاهی‌ها از…", "notifications_permission_banner.enable": "به کار انداختن آگاهی‌های میزکار", "notifications_permission_banner.how_to_control": "برای دریافت آگاهی‌ها هنگام باز نبودن ماستودون، آگاهی‌های میزکار را به کار بیندازید. پس از به کار افتادنشان می‌توانید گونه‌های دقیق برهم‌کنش‌هایی که آگاهی‌های میزکار تولید می‌کنند را از {icon} بالا واپایید.", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 681f5d5bb20a9a..717ea78559d713 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Äänestyksen kesto", "compose_form.poll.multiple": "Monivalinta", "compose_form.poll.option_placeholder": "Vaihtoehto {number}", - "compose_form.poll.single": "Valitse yksi", + "compose_form.poll.single": "Yksittäisvalinta", "compose_form.poll.switch_to_multiple": "Muuta äänestys monivalinnaksi", "compose_form.poll.switch_to_single": "Muuta äänestys yksittäisvalinnaksi", "compose_form.poll.type": "Tyyli", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} lisäsi julkaisusi suosikkeihinsa", "notification.favourite.name_and_others_with_link": "{name} ja {count, plural, one {# muu} other {# muuta}} lisäsivät julkaisusi suosikkeihinsa", "notification.follow": "{name} seurasi sinua", - "notification.follow.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} seurasivat sinua", + "notification.follow.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} seurasivat sinua", "notification.follow_request": "{name} on pyytänyt lupaa seurata sinua", "notification.follow_request.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} pyysivät saada seurata sinua", "notification.label.mention": "Maininta", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Yksityinen vastaus", "notification.label.reply": "Vastaus", "notification.mention": "Maininta", + "notification.mentioned_you": "{name} mainitsi sinut", "notification.moderation-warning.learn_more": "Lue lisää", "notification.moderation_warning": "Olet saanut moderointivaroituksen", "notification.moderation_warning.action_delete_statuses": "Julkaisujasi on poistettu.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Pikasuodatuspalkki", "notifications.column_settings.follow": "Uudet seuraajat:", "notifications.column_settings.follow_request": "Uudet seurantapyynnöt:", + "notifications.column_settings.group": "Ryhmitä", "notifications.column_settings.mention": "Maininnat:", "notifications.column_settings.poll": "Äänestyksen tulokset:", "notifications.column_settings.push": "Puskuilmoitukset", @@ -795,7 +799,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 +854,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..3822fbcf858e02 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", @@ -40,9 +46,11 @@ "account.media": "Medya", "account.mention": "Banggitin si @{name}", "account.moved_to": "Ipinahihiwatig ni {name} na ang kanilang bagong account ngayon ay:", + "account.no_bio": "Walang nakalaan na paglalarawan.", "account.open_original_page": "Buksan ang pinagmulang pahina", "account.report": "I-ulat si/ang @{name}", "account.requested_follow": "Hinihiling ni {name} na sundan ka", + "account.share": "Ibahagi ang profile ni @{name}", "account.show_reblogs": "Ipakita ang mga pagpapalakas mula sa/kay {name}", "account.unendorse": "Huwag itampok sa profile", "admin.dashboard.retention.cohort_size": "Mga bagong tagagamit", @@ -50,7 +58,11 @@ "audio.hide": "Itago ang tunog", "block_modal.show_less": "Magpakita ng mas kaunti", "block_modal.show_more": "Magpakita ng higit pa", + "block_modal.they_cant_mention": "Hindi sila makakabanggit sa iyo o sundan ka.", + "block_modal.they_will_know": "Makita nila na hinarangan sila.", "block_modal.title": "Harangan ang tagagamit?", + "block_modal.you_wont_see_mentions": "Hindi ka makakakita ng mga post na nagbanggit sa kanila.", + "boost_modal.combo": "Maari mong pindutin ang {combo} upang laktawan ito sa susunod na oras", "bundle_column_error.error.title": "Naku!", "bundle_column_error.network.body": "Nagkaroon ng kamalian habang sinusubukang i-karga ang pahinang ito. Maaaring dahil ito sa pansamantalang problema ng iyong koneksyon sa internet o ang server na ito.", "bundle_column_error.network.title": "Kamaliang network", @@ -101,10 +113,11 @@ "compose_form.direct_message_warning_learn_more": "Matuto pa", "compose_form.encryption_warning": "Ang mga post sa Mastodon ay hindi naka-encrypt nang dulo-dulo. Huwag magbahagi ng anumang sensitibong impormasyon sa Mastodon.", "compose_form.hashtag_warning": "Hindi maililista ang post na ito sa anumang hashtag dahil hindi ito nakapubliko. Mga nakapublikong post lamang ang mahahanap ayon sa hashtag.", + "compose_form.lock_disclaimer": "Hindi {locked} ang iyong account. Maaaring susundan ka ng sinuman upang tingnan ang iyong mga post na para sa mga tagasunod lamang.", + "compose_form.lock_disclaimer.lock": "nakakandado", "compose_form.placeholder": "Anong nangyari?", "compose_form.poll.duration": "Tagal ng botohan", "compose_form.poll.multiple": "Maraming pagpipilian", - "compose_form.poll.single": "Piliin ang isa", "compose_form.reply": "Tumugon", "compose_form.spoiler.marked": "Tanggalin ang babala sa nilalaman", "compose_form.spoiler.unmarked": "Idagdag ang babala sa nilalaman", @@ -117,6 +130,7 @@ "confirmations.edit.confirm": "Baguhin", "confirmations.reply.confirm": "Tumugon", "conversation.mark_as_read": "Markahan bilang nabasa na", + "conversation.open": "Tingnan ang pag-uusap", "copy_icon_button.copied": "Sinipi sa clipboard", "copypaste.copied": "Sinipi", "copypaste.copy_to_clipboard": "I-sipi sa clipboard", @@ -134,7 +148,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:", @@ -171,6 +184,7 @@ "empty_column.home": "Walang laman ang timeline ng tahanan mo! Sumunod sa marami pang tao para mapunan ito.", "empty_column.list": "Wala pang laman ang listahang ito. Kapag naglathala ng mga bagong post ang mga miyembro ng listahang ito, makikita iyon dito.", "empty_column.lists": "Wala ka pang mga listahan. Kapag gumawa ka ng isa, makikita yun dito.", + "errors.unexpected_crash.report_issue": "Iulat ang isyu", "explore.search_results": "Mga resulta ng paghahanap", "explore.suggested_follows": "Mga tao", "explore.title": "Tuklasin", @@ -182,6 +196,7 @@ "follow_request.authorize": "Tanggapin", "follow_request.reject": "Tanggihan", "follow_suggestions.dismiss": "Huwag nang ipakita muli", + "follow_suggestions.popular_suggestion": "Sikat na mungkahi", "follow_suggestions.popular_suggestion_longer": "Sikat sa {domain}", "follow_suggestions.view_all": "Tingnan lahat", "follow_suggestions.who_to_follow": "Sinong maaaring sundan", @@ -191,6 +206,7 @@ "generic.saved": "Nakaimbak", "hashtag.column_header.tag_mode.all": "at {additional}", "hashtag.column_header.tag_mode.any": "o {additional}", + "hashtag.column_settings.select.no_options_message": "Walang mungkahing nakita", "hashtag.column_settings.tag_mode.all": "Lahat ng nandito", "hashtag.column_settings.tag_mode.any": "Ilan dito", "hashtag.column_settings.tag_mode.none": "Wala dito", @@ -217,12 +233,15 @@ "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.edit.submit": "Baguhin ang pamagat", "lists.new.create": "Idagdag sa talaan", "lists.new.title_placeholder": "Bagong pangalan ng talaan", + "lists.replies_policy.none": "Walang simuman", "lists.replies_policy.title": "Ipakita ang mga tugon sa:", "lists.subheading": "Iyong mga talaan", "loading_indicator.label": "Kumakarga…", + "media_gallery.hide": "Itago", "mute_modal.hide_from_notifications": "Itago mula sa mga abiso", "navigation_bar.about": "Tungkol dito", "navigation_bar.blocks": "Nakaharang na mga tagagamit", @@ -238,11 +257,15 @@ "notification.admin.report": "Iniulat ni {name} si {target}", "notification.follow": "Sinundan ka ni {name}", "notification.follow_request": "Hinihiling ni {name} na sundan ka", + "notification.label.private_mention": "Palihim na banggit", + "notification.mentioned_you": "Binanggit ka ni {name}", + "notification.moderation-warning.learn_more": "Matuto nang higit pa", "notification.moderation_warning": "Mayroong kang natanggap na babala sa pagtitimpi", "notification.relationships_severance_event.learn_more": "Matuto nang higit pa", "notification_requests.accept": "Tanggapin", "notification_requests.notifications_from": "Mga abiso mula kay/sa {name}", "notifications.clear": "Burahin mga abiso", + "notifications.clear_title": "Linisin ang mga abiso?", "notifications.column_settings.admin.report": "Mga bagong ulat:", "notifications.column_settings.alert": "Mga abiso sa Desktop", "notifications.column_settings.favourite": "Mga paborito:", @@ -254,6 +277,8 @@ "notifications.filter.favourites": "Mga paborito", "notifications.filter.polls": "Resulta ng botohan", "notifications.mark_as_read": "Markahan lahat ng abiso bilang nabasa na", + "notifications.policy.accept": "Tanggapin", + "notifications.policy.accept_hint": "Ipakita sa mga abiso", "notifications.policy.filter_not_followers_title": "Mga taong hindi ka susundan", "notifications.policy.filter_not_following_title": "Mga taong hindi mo sinusundan", "onboarding.action.back": "Ibalik mo ako", @@ -270,6 +295,10 @@ "privacy.private.long": "Mga tagasunod mo lamang", "privacy.private.short": "Mga tagasunod", "privacy.public.long": "Sinumang nasa loob at labas ng Mastodon", + "privacy.public.short": "Pampubliko", + "privacy.unlisted.short": "Hindi nakalista", + "privacy_policy.last_updated": "Huling nabago noong {date}", + "recommended": "Inirekomenda", "regeneration_indicator.label": "Kumakarga…", "relative_time.days": "{number}a", "relative_time.full.days": "{number, plural, one {# araw} other {# na araw}} ang nakalipas", @@ -281,6 +310,7 @@ "relative_time.just_now": "ngayon", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", + "relative_time.today": "ngayon", "reply_indicator.cancel": "Ipagpaliban", "report.block": "Harangan", "report.categories.other": "Iba pa", @@ -288,9 +318,11 @@ "report.category.subtitle": "Piliin ang pinakamahusay na tugma", "report.category.title": "Sabihin mo sa amin kung anong nangyari sa {type} na ito", "report.close": "Tapos na", + "report.comment.title": "Mayroon pa bang dapat naming malaman?", "report.next": "Sunod", "report.placeholder": "Mga Karagdagang Puna", "report.reasons.dislike": "Hindi ko gusto ito", + "report.reasons.legal": "Labag ito sa batas", "report.reasons.violation": "Lumalabag ito sa mga panuntunan ng serbiro", "report.reasons.violation_description": "Alam mo na lumalabag ito sa mga partikular na panuntunan", "report.rules.title": "Aling mga patakaran ang nilabag?", @@ -337,5 +369,8 @@ "time_remaining.days": "{number, plural, one {# araw} other {# na araw}} ang natitira", "time_remaining.hours": "{number, plural, one {# oras} other {# na oras}} ang natitira", "time_remaining.minutes": "{number, plural, one {# minuto} other {# na minuto}} ang natitira", - "time_remaining.seconds": "{number, plural, one {# segundo} other {# na segundo}} ang natitira" + "time_remaining.seconds": "{number, plural, one {# segundo} other {# na segundo}} ang natitira", + "upload_modal.apply": "Ilapat", + "upload_modal.applying": "Nilalapat…", + "upload_modal.choose_image": "Pumili ng larawan" } diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index 793a75bb05a5f5..0e2bc88136921b 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óð", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Atkvøðugreiðslutíð", "compose_form.poll.multiple": "Fleiri valmøguleikar", "compose_form.poll.option_placeholder": "Valmøguleiki {number}", - "compose_form.poll.single": "Vel ein", + "compose_form.poll.single": "Einfalt val", "compose_form.poll.switch_to_multiple": "Broyt atkvøðugreiðslu til at loyva fleiri svarum", "compose_form.poll.switch_to_single": "Broyt atkvøðugreiðslu til einstakt svar", "compose_form.poll.type": "Stílur", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} dámdi postin hjá tær", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# annar/onnur} other {# onnur}} yndisfrámerktu postin hjá tær", "notification.follow": "{name} fylgdi tær", - "notification.follow.name_and_others": "{name} og {count, plural, one {# annar/onnur} other {# onnur}} fylgdu tær", + "notification.follow.name_and_others": "{name} og {count, plural, one {# annar/onnur} other {# onnur}} fylgdu tær", "notification.follow_request": "{name} biður um at fylgja tær", "notification.follow_request.name_and_others": "{name} og {count, plural, one {# annar/onnur} other {# onnur}} hava biðið um at fylgja tær", "notification.label.mention": "Umrøða", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Privat svar", "notification.label.reply": "Svara", "notification.mention": "Umrøð", + "notification.mentioned_you": "{name} nevndi teg", "notification.moderation-warning.learn_more": "Lær meira", "notification.moderation_warning": "Tú hevur móttikið eina umsjónarávaring", "notification.moderation_warning.action_delete_statuses": "Onkrir av tínum postum eru strikaðir.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Skjótfilturbjálki", "notifications.column_settings.follow": "Nýggir fylgjarar:", "notifications.column_settings.follow_request": "Nýggjar umbønir um at fylgja:", + "notifications.column_settings.group": "Bólkur", "notifications.column_settings.mention": "Umrøður:", "notifications.column_settings.poll": "Úrslit frá atkvøðugreiðslu:", "notifications.column_settings.push": "Trýstifráboðanir", @@ -850,6 +854,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..e73a3249cbd949 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -85,10 +85,11 @@ "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", - "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateurs non connectés.", + "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateur·rice·s non connecté·e·s.", "block_modal.show_less": "Afficher moins", "block_modal.show_more": "Afficher plus", "block_modal.they_cant_mention": "Il ne peut pas vous mentionner ou vous suivre.", @@ -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)", @@ -193,7 +194,7 @@ "confirmations.reply.title": "Remplacer le message ?", "confirmations.unfollow.confirm": "Ne plus suivre", "confirmations.unfollow.message": "Voulez-vous vraiment arrêter de suivre {name}?", - "confirmations.unfollow.title": "Se désabonner de l'utilisateur ?", + "confirmations.unfollow.title": "Se désabonner de l'utilisateur·rice ?", "content_warning.hide": "Masquer le message", "content_warning.show": "Afficher quand même", "conversation.delete": "Supprimer cette conversation", @@ -221,8 +222,9 @@ "domain_block_modal.they_cant_follow": "Personne de ce serveur ne peut vous suivre.", "domain_block_modal.they_wont_know": "Il ne saura pas qu'il a été bloqué.", "domain_block_modal.title": "Bloquer le domaine ?", - "domain_block_modal.you_will_lose_followers": "Tous vos abonnés de ce serveur seront supprimés.", - "domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.", + "domain_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 utilisateur·rice·s 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.", "domain_pill.server": "Serveur", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} a ajouté votre publication à ses favoris", "notification.favourite.name_and_others_with_link": "{name} et {count, plural, one {# autre} other {# autres}} ont mis votre message en favori", "notification.follow": "{name} vous suit", - "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont abonné à votre compte", + "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} vous suivent", "notification.follow_request": "{name} a demandé à vous suivre", "notification.follow_request.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} ont demandé à vous suivre", "notification.label.mention": "Mention", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Répondre en privé", "notification.label.reply": "Réponse", "notification.mention": "Mention", + "notification.mentioned_you": "{name} vous a mentionné·e", "notification.moderation-warning.learn_more": "En savoir plus", "notification.moderation_warning": "Vous avez reçu un avertissement de modération", "notification.moderation_warning.action_delete_statuses": "Certains de vos messages ont été supprimés.", @@ -540,12 +543,12 @@ "notification_requests.confirm_accept_multiple.message": "Vous êtes sur le point d'accepter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Êtes-vous sûr de vouloir continuer ?", "notification_requests.confirm_accept_multiple.title": "Accepter les requêtes de notification ?", "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Ignorer la requête} other {Ignorer les requêtes}}", - "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne serez plus en mesure d’{count, plural, one {y} other {y}} accéder facilement, ultérieurement. Êtes-vous sûr de vouloir continuer ?", + "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne pourrez plus {count, plural, one {y} other {y}} accéder facilement plus tard. Voulez-vous vraiment continuer ?", "notification_requests.confirm_dismiss_multiple.title": "Rejeter les requêtes de notification ?", "notification_requests.dismiss": "Rejeter", "notification_requests.dismiss_multiple": "{count, plural, one {Rejeter # requête …} other {Rejeter # requêtes …}}", "notification_requests.edit_selection": "Modifier", - "notification_requests.exit_selection": "Fait", + "notification_requests.exit_selection": "Terminé", "notification_requests.explainer_for_limited_account": "Les notifications en provenance de ce compte ont été filtrées car le compte a été limité par un modérateur.", "notification_requests.explainer_for_limited_remote_account": "Les notifications en provenance de ce compte ont été filtrées car le compte ou le serveur dont il est issu a été limité par un modérateur.", "notification_requests.maximize": "Agrandir", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barre de filtre rapide", "notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e⋅s:", "notifications.column_settings.follow_request": "Nouvelles demandes d’abonnement:", + "notifications.column_settings.group": "Grouper", "notifications.column_settings.mention": "Mentions:", "notifications.column_settings.poll": "Résultats des sondages:", "notifications.column_settings.push": "Notifications push", @@ -850,6 +854,8 @@ "upload_error.poll": "L’envoi de fichiers n’est pas autorisé avec les sondages.", "upload_form.audio_description": "Décrire pour les personnes ayant des difficultés d’audition", "upload_form.description": "Décrire pour les malvoyants", + "upload_form.drag_and_drop.instructions": "Pour choisir un média joint, appuyez sur la touche espace ou entrée. Tout en faisant glisser, utilisez les touches fléchées pour déplacer le fichier média dans une direction donnée. Appuyez à nouveau sur la touche espace ou entrée pour déposer le fichier média dans sa nouvelle position, ou appuyez sur la touche Echap pour annuler.", + "upload_form.drag_and_drop.on_drag_cancel": "Le glissement a été annulé. La pièce jointe {item} n'a pas été ajoutée.", "upload_form.edit": "Modifier", "upload_form.thumbnail": "Changer la vignette", "upload_form.video_description": "Décrire pour les personnes ayant des problèmes de vue ou d'audition", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index e73ddf734f1b5e..319316272be590 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -79,16 +79,17 @@ "admin.dashboard.retention.cohort_size": "Nouveaux comptes", "admin.impact_report.instance_accounts": "Profils de comptes que cela supprimerait", "admin.impact_report.instance_followers": "Abonnées que nos utilisateurs perdraient", - "admin.impact_report.instance_follows": "Abonnées que leurs utilisateurs perdraient", + "admin.impact_report.instance_follows": "Abonné·e·s que leurs utilisateur·rice·s perdraient", "admin.impact_report.title": "Résumé de l'impact", "alert.rate_limited.message": "Veuillez réessayer après {retry_time, time, medium}.", "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", - "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateurs non connectés.", + "block_modal.remote_users_caveat": "Nous allons demander au serveur {domain} de respecter votre décision. Cependant, ce respect n'est pas garanti, car certains serveurs peuvent gérer différemment les blocages. Les messages publics peuvent rester visibles par les utilisateur·rice·s non connecté·e·s.", "block_modal.show_less": "Afficher moins", "block_modal.show_more": "Afficher plus", "block_modal.they_cant_mention": "Il ne peut pas vous mentionner ou vous suivre.", @@ -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)", @@ -193,7 +194,7 @@ "confirmations.reply.title": "Remplacer le message ?", "confirmations.unfollow.confirm": "Ne plus suivre", "confirmations.unfollow.message": "Voulez-vous vraiment vous désabonner de {name} ?", - "confirmations.unfollow.title": "Se désabonner de l'utilisateur ?", + "confirmations.unfollow.title": "Se désabonner de l'utilisateur·rice ?", "content_warning.hide": "Masquer le message", "content_warning.show": "Afficher quand même", "conversation.delete": "Supprimer la conversation", @@ -221,8 +222,9 @@ "domain_block_modal.they_cant_follow": "Personne de ce serveur ne peut vous suivre.", "domain_block_modal.they_wont_know": "Il ne saura pas qu'il a été bloqué.", "domain_block_modal.title": "Bloquer le domaine ?", - "domain_block_modal.you_will_lose_followers": "Tous vos abonnés de ce serveur seront supprimés.", - "domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.", + "domain_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 utilisateur·rice·s 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.", "domain_pill.server": "Serveur", @@ -260,7 +262,7 @@ "empty_column.blocks": "Vous n’avez bloqué aucun compte pour le moment.", "empty_column.bookmarked_statuses": "Vous n'avez pas de message en marque-page. Lorsque vous en ajouterez un, il apparaîtra ici.", "empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !", - "empty_column.direct": "Vous n'avez pas encore de mentions privées. Quand vous en envoyez ou en recevez, elles apparaîtront ici.", + "empty_column.direct": "Vous n'avez pas encore de mentions privées. Quand vous en enverrez ou recevrez, elles apparaîtront ici.", "empty_column.domain_blocks": "Il n’y a aucun domaine bloqué pour le moment.", "empty_column.explore_statuses": "Rien n'est en tendance pour le moment. Revenez plus tard !", "empty_column.favourited_statuses": "Vous n’avez pas encore de message en favori. Lorsque vous en ajouterez un, il apparaîtra ici.", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} a ajouté votre message à ses favoris", "notification.favourite.name_and_others_with_link": "{name} et {count, plural, one {# autre} other {# autres}} ont mis votre message en favori", "notification.follow": "{name} vous suit", - "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} se sont abonné à votre compte", + "notification.follow.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} vous suivent", "notification.follow_request": "{name} a demandé à vous suivre", "notification.follow_request.name_and_others": "{name} et {count, plural, one {# autre} other {# autres}} ont demandé à vous suivre", "notification.label.mention": "Mention", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Répondre en privé", "notification.label.reply": "Réponse", "notification.mention": "Mention", + "notification.mentioned_you": "{name} vous a mentionné·e", "notification.moderation-warning.learn_more": "En savoir plus", "notification.moderation_warning": "Vous avez reçu un avertissement de modération", "notification.moderation_warning.action_delete_statuses": "Certains de vos messages ont été supprimés.", @@ -540,12 +543,12 @@ "notification_requests.confirm_accept_multiple.message": "Vous êtes sur le point d'accepter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Êtes-vous sûr de vouloir continuer ?", "notification_requests.confirm_accept_multiple.title": "Accepter les requêtes de notification ?", "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Ignorer la requête} other {Ignorer les requêtes}}", - "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne serez plus en mesure d’{count, plural, one {y} other {y}} accéder facilement, ultérieurement. Êtes-vous sûr de vouloir continuer ?", + "notification_requests.confirm_dismiss_multiple.message": "Vous êtes sur le point de rejeter {count, plural, one {une requête de notification} other {# requêtes de notification}}. Vous ne pourrez plus {count, plural, one {y} other {y}} accéder facilement plus tard. Voulez-vous vraiment continuer ?", "notification_requests.confirm_dismiss_multiple.title": "Rejeter les requêtes de notification ?", "notification_requests.dismiss": "Rejeter", "notification_requests.dismiss_multiple": "{count, plural, one {Rejeter # requête …} other {Rejeter # requêtes …}}", "notification_requests.edit_selection": "Modifier", - "notification_requests.exit_selection": "Fait", + "notification_requests.exit_selection": "Terminé", "notification_requests.explainer_for_limited_account": "Les notifications en provenance de ce compte ont été filtrées car le compte a été limité par un modérateur.", "notification_requests.explainer_for_limited_remote_account": "Les notifications en provenance de ce compte ont été filtrées car le compte ou le serveur dont il est issu a été limité par un modérateur.", "notification_requests.maximize": "Agrandir", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barre de filtre rapide", "notifications.column_settings.follow": "Nouveaux·elles abonné·e·s :", "notifications.column_settings.follow_request": "Nouvelles demandes d’abonnement :", + "notifications.column_settings.group": "Grouper", "notifications.column_settings.mention": "Mentions :", "notifications.column_settings.poll": "Résultats des sondages :", "notifications.column_settings.push": "Notifications push", @@ -850,6 +854,8 @@ "upload_error.poll": "L’envoi de fichiers n’est pas autorisé avec les sondages.", "upload_form.audio_description": "Décrire pour les personnes ayant des difficultés d’audition", "upload_form.description": "Décrire pour les malvoyant·e·s", + "upload_form.drag_and_drop.instructions": "Pour choisir un média joint, appuyez sur la touche espace ou entrée. Tout en faisant glisser, utilisez les touches fléchées pour déplacer le fichier média dans une direction donnée. Appuyez à nouveau sur la touche espace ou entrée pour déposer le fichier média dans sa nouvelle position, ou appuyez sur la touche Echap pour annuler.", + "upload_form.drag_and_drop.on_drag_cancel": "Le glissement a été annulé. La pièce jointe {item} n'a pas été ajoutée.", "upload_form.edit": "Modifier", "upload_form.thumbnail": "Changer la vignette", "upload_form.video_description": "Décrire pour les personnes ayant des problèmes de vue ou d'audition", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index 2443692133af18..0790a0dc574fd5 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Dataferkear beheind", "alert.unexpected.message": "Der is in ûnferwachte flater bard.", "alert.unexpected.title": "Oepsy!", + "alt_text_badge.title": "Alternative tekst", "announcement.announcement": "Oankundiging", "attachments_list.unprocessed": "(net ferwurke)", "audio.hide": "Audio ferstopje", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Doer fan de enkête", "compose_form.poll.multiple": "Mearkar", "compose_form.poll.option_placeholder": "Opsje {number}", - "compose_form.poll.single": "Kies ien", "compose_form.poll.switch_to_multiple": "Enkête wizigje om meardere karren ta te stean", "compose_form.poll.switch_to_single": "Enkête wizigje om in inkelde kar ta te stean", "compose_form.poll.type": "Styl", @@ -221,7 +221,8 @@ "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_will_lose_num_followers": "Jo ferlieze {followersCount, plural, one {{followersCountDisplay} folger} other {{followersCountDisplay} folgers}} en {followingCount, plural, one {{followingCountDisplay} persoan dy’t jo folgje} other {{followingCountDisplay} persoanen dy’t jo folgje}}.", + "domain_block_modal.you_will_lose_relationships": "Jo ferlieze alle folgers en minsken dy’t jo folgje fan dizze server.", "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,10 +433,10 @@ "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", + "lightbox.zoom_in": "Oarspronklike grutte toane", + "lightbox.zoom_out": "Passend toane", "limited_account_hint.action": "Profyl dochs besjen", "limited_account_hint.title": "Dit profyl is troch de behearders fan {domain} ferstoppe.", "link_preview.author": "Troch {name}", @@ -457,6 +458,7 @@ "lists.subheading": "Jo listen", "load_pending": "{count, plural, one {# nij item} other {# nije items}}", "loading_indicator.label": "Lade…", + "media_gallery.hide": "Ferstopje", "moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.", "mute_modal.hide_from_notifications": "Meldingen ferstopje", "mute_modal.hide_options": "Opsjes ferstopje", @@ -505,7 +507,6 @@ "notification.favourite": "{name} hat jo berjocht as favoryt markearre", "notification.favourite.name_and_others_with_link": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe jo berjocht as favoryt markearre", "notification.follow": "{name} folget dy", - "notification.follow.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe jo folge", "notification.follow_request": "{name} hat dy in folchfersyk stjoerd", "notification.follow_request.name_and_others": "{name} en {count, plural, one {# oar} other {# oaren}} hawwe frege om jo te folgjen", "notification.label.mention": "Fermelding", @@ -513,6 +514,7 @@ "notification.label.private_reply": "Priveereaksje", "notification.label.reply": "Beäntwurdzje", "notification.mention": "Fermelding", + "notification.mentioned_you": "{name} hat dy fermeld", "notification.moderation-warning.learn_more": "Mear ynfo", "notification.moderation_warning": "Jo hawwe in moderaasje-warskôging ûntfongen", "notification.moderation_warning.action_delete_statuses": "Guon fan jo berjochten binne fuortsmiten.", @@ -777,6 +779,7 @@ "status.bookmark": "Blêdwizer tafoegje", "status.cancel_reblog_private": "Net langer booste", "status.cannot_reblog": "Dit berjocht kin net boost wurde", + "status.continued_thread": "Ferfolgje it petear", "status.copy": "Copy link to status", "status.delete": "Fuortsmite", "status.detailed_status": "Detaillearre petearoersjoch", @@ -785,6 +788,7 @@ "status.edit": "Bewurkje", "status.edited": "Lêst bywurke op {date}", "status.edited_x_times": "{count, plural, one {{count} kear} other {{count} kearen}} bewurke", + "status.embed": "Koade om op te nimmen", "status.favourite": "Favoryt", "status.favourites": "{count, plural, one {favoryt} other {favoriten}}", "status.filter": "Dit berjocht filterje", @@ -809,6 +813,7 @@ "status.reblogs.empty": "Net ien hat dit berjocht noch boost. Wannear’t ien dit docht, falt dat hjir te sjen.", "status.redraft": "Fuortsmite en opnij opstelle", "status.remove_bookmark": "Blêdwizer fuortsmite", + "status.replied_in_thread": "Antwurde yn petear", "status.replied_to": "Antwurde op {name}", "status.reply": "Beäntwurdzje", "status.replyAll": "Alle beäntwurdzje", @@ -846,6 +851,11 @@ "upload_error.poll": "It opladen fan bestannen is yn enkêten net tastien.", "upload_form.audio_description": "Describe for people with hearing loss", "upload_form.description": "Describe for the visually impaired", + "upload_form.drag_and_drop.instructions": "Druk op spaasje of Enter om in mediabylage op te pakken. Bruk de pylktoetsen om de bylage yn in bepaalde rjochting te ferpleatsen. Druk opnij op de spaasjebalke of Enter om de mediabylage op de nije posysje te pleatsen, of druk op Esc om te annulearjen.", + "upload_form.drag_and_drop.on_drag_cancel": "Slepen is annulearre. Mediabylage {item} is net ferpleatst.", + "upload_form.drag_and_drop.on_drag_end": "Mediabylage {item} is net ferpleatst.", + "upload_form.drag_and_drop.on_drag_over": "Mediabylage {item} is ferpleatst.", + "upload_form.drag_and_drop.on_drag_start": "Mediabylage {item} is oppakt.", "upload_form.edit": "Bewurkje", "upload_form.thumbnail": "Miniatuerôfbylding wizigje", "upload_form.video_description": "Describe for people with hearing loss or visual impairment", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 11da6b64e94d31..81b93816ea08a3 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Achar suirbhéanna", "compose_form.poll.multiple": "Ilrogha", "compose_form.poll.option_placeholder": "Rogha {number}", - "compose_form.poll.single": "Roghnaigh ceann amháin", + "compose_form.poll.single": "Rogha aonair", "compose_form.poll.switch_to_multiple": "Athraigh suirbhé chun cead a thabhairt do ilrogha", "compose_form.poll.switch_to_single": "Athraigh suirbhé chun cead a thabhairt do rogha amháin", "compose_form.poll.type": "Stíl", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "Is fearr le {name} do phostáil", "notification.favourite.name_and_others_with_link": "{name} agus {count, plural, one {# duine eile} other {# daoine eile}} thaitin le do phost", "notification.follow": "Lean {name} thú", - "notification.follow.name_and_others": "{name} agus {count, plural, one {# duine eile} other {# daoine eile}} a lean tú", + "notification.follow.name_and_others": "{name} agus {count, plural, one {# other} two {# eile} few {# eile} many {# eile} other {# others}} lean tú", "notification.follow_request": "D'iarr {name} ort do chuntas a leanúint", "notification.follow_request.name_and_others": "{name} agus {count, plural, one {# duine eile} other {# daoine eile}} iarratas a dhéanamh chun tú a leanúint", "notification.label.mention": "Luaigh", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Freagra príobháideach", "notification.label.reply": "Freagra", "notification.mention": "Luaigh", + "notification.mentioned_you": "Luaigh {name} tú", "notification.moderation-warning.learn_more": "Foghlaim níos mó", "notification.moderation_warning": "Tá rabhadh modhnóireachta faighte agat", "notification.moderation_warning.action_delete_statuses": "Baineadh cuid de do phostálacha.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra scagairí tapa", "notifications.column_settings.follow": "Leantóirí nua:", "notifications.column_settings.follow_request": "Iarratais leanúnaí nua:", + "notifications.column_settings.group": "Grúpa", "notifications.column_settings.mention": "Tráchtanna:", "notifications.column_settings.poll": "Torthaí suirbhéanna:", "notifications.column_settings.push": "Brúfhógraí", @@ -850,6 +854,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..a9da2cd5ec4b55 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Cuingeachadh ùine", "alert.unexpected.message": "Thachair mearachd ris nach robh dùil.", "alert.unexpected.title": "Oich!", + "alt_text_badge.title": "Roghainn teacsa", "announcement.announcement": "Brath-fios", "attachments_list.unprocessed": "(gun phròiseasadh)", "audio.hide": "Falaich an fhuaim", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Faide a’ chunntais", "compose_form.poll.multiple": "Iomadh-roghainn", "compose_form.poll.option_placeholder": "Roghainn {number}", - "compose_form.poll.single": "Aonan", "compose_form.poll.switch_to_multiple": "Atharraich an cunntas-bheachd ach an gabh iomadh roghainn a thaghadh", "compose_form.poll.switch_to_single": "Atharraich an cunntas-bheachd gus nach gabh ach aon roghainn a thaghadh", "compose_form.poll.type": "Stoidhle", @@ -221,7 +221,8 @@ "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_will_lose_num_followers": "Caillidh tu {followersCount, plural, one {{followersCountDisplay} neach-leantainn} two {{followersCountDisplay} luchd-leantainn} few {{followersCountDisplay} luchd-leantainn} other {{followersCountDisplay} luchd-leantainn}} ’s {followingCount, plural, one {{followingCountDisplay} neach a tha thu a’ leantainn} two {{followingCountDisplay} daoine a tha thu a’ leantainn} few {{followingCountDisplay} daoine a tha thu a’ leantainn} other {{followingCountDisplay} daoine a tha thu a’ leantainn}}.", + "domain_block_modal.you_will_lose_relationships": "Caillidh tu a h-uile luchd-leantainn ’s neach a leanas tu air an fhrithealaiche seo.", "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.", @@ -331,7 +332,7 @@ "footer.about": "Mu dhèidhinn", "footer.directory": "Eòlaire nam pròifil", "footer.get_app": "Faigh an aplacaid", - "footer.invite": "Thoir cuireadh do dhaoine", + "footer.invite": "Thoir cuireadh", "footer.keyboard_shortcuts": "Ath-ghoiridean a’ mheur-chlàir", "footer.privacy_policy": "Poileasaidh prìobhaideachd", "footer.source_code": "Seall am bun-tùs", @@ -432,10 +433,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}", @@ -506,7 +507,6 @@ "notification.favourite": "Is annsa le {name} am post agad", "notification.favourite.name_and_others_with_link": "Is annsa le {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} am post agad", "notification.follow": "Tha {name} ’gad leantainn a-nis", - "notification.follow.name_and_others": "Lean {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} thu", "notification.follow_request": "Dh’iarr {name} ’gad leantainn", "notification.follow_request.name_and_others": "Dh’iarr {name} ’s {count, plural, one {# eile} two {# eile} few {# eile} other {# eile}} ’gad leantainn", "notification.label.mention": "Iomradh", @@ -514,6 +514,7 @@ "notification.label.private_reply": "Freagairt phrìobhaideach", "notification.label.reply": "Freagairt", "notification.mention": "Iomradh", + "notification.mentioned_you": "Thug {name} iomradh ort", "notification.moderation-warning.learn_more": "Barrachd fiosrachaidh", "notification.moderation_warning": "Fhuair thu rabhadh on mhaorsainneachd", "notification.moderation_warning.action_delete_statuses": "Chaidh cuid dhe na postaichean agad a thoirt air falbh.", @@ -850,6 +851,11 @@ "upload_error.poll": "Chan fhaod thu faidhle a luchdadh suas an cois cunntais-bheachd.", "upload_form.audio_description": "Mìnich e dhan fheadhainn le èisteachd bheag", "upload_form.description": "Mìnich e dhan fheadhainn le cion-lèirsinne", + "upload_form.drag_and_drop.instructions": "Airson ceanglachan meadhain a thogail, brùth air space no enter. Fhad ’ a bhios tu ’ga shlaodadh, cleachd na h-iuchraichean-saighde airson an ceanglachan meadhain a ghluasad gu comhair sam bith. Brùth air space no enter a-rithist airson an ceanglachen meadhain a leigeil às air an ionad ùr aige no brùth air escape airson sgur dheth.", + "upload_form.drag_and_drop.on_drag_cancel": "Chaidh sgur dhen t-slaodadh. Chaidh an ceanglachan meadhain {item} a leigeil às.", + "upload_form.drag_and_drop.on_drag_end": "Chaidh an ceanglachan meadhain {item} a leigeil às.", + "upload_form.drag_and_drop.on_drag_over": "Chaidh an ceanglachan meadhain {item} a ghluasad.", + "upload_form.drag_and_drop.on_drag_start": "Chaidh an ceanglachan meadhain {item} a thogail.", "upload_form.edit": "Deasaich", "upload_form.thumbnail": "Atharraich an dealbhag", "upload_form.video_description": "Mìnich e dhan fheadhainn le èisteachd bheag no cion-lèirsinne", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index d35bcd8cf5b2ab..5e40b0e4290769 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Duración da enquisa", "compose_form.poll.multiple": "Escolla múltiple", "compose_form.poll.option_placeholder": "Opción {number}", - "compose_form.poll.single": "Elixe unha", + "compose_form.poll.single": "Opción única", "compose_form.poll.switch_to_multiple": "Mudar a enquisa para permitir múltiples escollas", "compose_form.poll.switch_to_single": "Mudar a enquisa para permitir unha soa opción", "compose_form.poll.type": "Estilo", @@ -192,7 +193,7 @@ "confirmations.reply.message": "Ao responder sobrescribirás a mensaxe que estás a compor. Tes a certeza de que queres continuar?", "confirmations.reply.title": "Editar a publicación?", "confirmations.unfollow.confirm": "Deixar de seguir", - "confirmations.unfollow.message": "Desexas deixar de seguir a {name}?", + "confirmations.unfollow.message": "Tes certeza de querer deixar de seguir a {name}?", "confirmations.unfollow.title": "Deixar de seguir á usuaria?", "content_warning.hide": "Agochar publicación", "content_warning.show": "Mostrar igualmente", @@ -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.", @@ -506,7 +508,7 @@ "notification.favourite": "{name} marcou como favorita a túa publicación", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# máis} other {# máis}} favoreceron a túa publicación", "notification.follow": "{name} comezou a seguirte", - "notification.follow.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} seguíronte", + "notification.follow.name_and_others": "{name} e {count, plural, one {# mais} other {# mais}} seguíronte", "notification.follow_request": "{name} solicitou seguirte", "notification.follow_request.name_and_others": "{name} e {count, plural, one {# máis} other {# máis}} solicitaron seguirte", "notification.label.mention": "Mención", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Resposta privada", "notification.label.reply": "Resposta", "notification.mention": "Mención", + "notification.mentioned_you": "{name} mencionoute", "notification.moderation-warning.learn_more": "Saber máis", "notification.moderation_warning": "Recibiches unha advertencia da moderación", "notification.moderation_warning.action_delete_statuses": "Algunha das túas publicacións foron eliminadas.", @@ -527,7 +530,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", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtrado rápido", "notifications.column_settings.follow": "Novas seguidoras:", "notifications.column_settings.follow_request": "Novas peticións de seguimento:", + "notifications.column_settings.group": "Agrupar", "notifications.column_settings.mention": "Mencións:", "notifications.column_settings.poll": "Resultados da enquisa:", "notifications.column_settings.push": "Notificacións emerxentes", @@ -850,6 +854,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..be1dde65280554 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -1,5 +1,5 @@ { - "about.blocks": "שרתים שנחסמו על ידי המנהלים", + "about.blocks": "שרתים מוגבלים", "about.contact": "יצירת קשר:", "about.disclaimer": "מסטודון היא תוכנת קוד פתוח חינמית וסימן מסחרי של Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "הסיבה אינה זמינה", @@ -34,9 +34,9 @@ "account.follow_back": "לעקוב בחזרה", "account.followers": "עוקבים", "account.followers.empty": "אף אחד לא עוקב אחר המשתמש הזה עדיין.", - "account.followers_counter": "{count, plural,one {עוקב אחד} other {{count} עוקבים}}", + "account.followers_counter": "{count, plural,one {עוקב אחד} other {{counter} עוקבים}}", "account.following": "נעקבים", - "account.following_counter": "{count, plural,one {עוקב אחרי {count}}other {עוקב אחרי {count}}}", + "account.following_counter": "{count, plural,one {עוקב אחרי {count}}other {עוקב אחרי {counter}}}", "account.follows.empty": "משתמש זה עדיין לא עוקב אחרי אף אחד.", "account.go_to_profile": "מעבר לפרופיל", "account.hide_reblogs": "להסתיר הידהודים מאת @{name}", @@ -62,7 +62,7 @@ "account.requested_follow": "{name} ביקשו לעקוב אחריך", "account.share": "שתף את הפרופיל של @{name}", "account.show_reblogs": "הצג הדהודים מאת @{name}", - "account.statuses_counter": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{count} הודעות} other {{count} הודעות}}", + "account.statuses_counter": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}}", "account.unblock": "להסיר חסימה ל- @{name}", "account.unblock_domain": "הסירי את החסימה של קהילת {domain}", "account.unblock_short": "הסר חסימה", @@ -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": "השתק", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "משך הסקר", "compose_form.poll.multiple": "בחירה מרובה", "compose_form.poll.option_placeholder": "אפשרות {number}", - "compose_form.poll.single": "נא לבחור", + "compose_form.poll.single": "בחירה יחידה", "compose_form.poll.switch_to_multiple": "אפשרו בחירה מרובה בסקר", "compose_form.poll.switch_to_single": "אפשרו בחירה בודדת בסקר", "compose_form.poll.type": "סוג משאל", @@ -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 {יאבד לך עוקב אחד}other {יאבדו לך {followersCountDisplay} עוקבים}} {followingCount, plural,one {ונעקב אחד}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": "אקטיביטיפאב היא למעשה השפה בה מסטודון מדבר עם רשתות חברתיות אחרות.", @@ -347,9 +349,9 @@ "hashtag.column_settings.tag_mode.any": "לפחות אחד מאלה", "hashtag.column_settings.tag_mode.none": "אף אחד מאלה", "hashtag.column_settings.tag_toggle": "כלול תגיות נוספות בטור זה", - "hashtag.counter_by_accounts": "{count, plural,one{{count} משתתף.ת}other{{count} משתתפיםות}}", - "hashtag.counter_by_uses": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{count} הודעות} other {{count} הודעות}}", - "hashtag.counter_by_uses_today": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{count} הודעות} other {{count} הודעות}} היום", + "hashtag.counter_by_accounts": "{count, plural,one{{count} משתתף.ת}other{{counter} משתתפיםות}}", + "hashtag.counter_by_uses": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}}", + "hashtag.counter_by_uses_today": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}} היום", "hashtag.follow": "לעקוב אחרי תגית", "hashtag.unfollow": "להפסיק לעקוב אחרי תגית", "hashtags.and_other": "…{count, plural,other {ועוד #}}", @@ -432,15 +434,15 @@ "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}", "link_preview.more_from_author": "עוד מאת {name}", - "link_preview.shares": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{count} הודעות} other {{count} הודעות}}", + "link_preview.shares": "{count, plural, one {הודעה אחת} two {הודעותיים} many {{counter} הודעות} other {{counter} הודעות}}", "lists.account.add": "הוסף לרשימה", "lists.account.remove": "הסר מרשימה", "lists.delete": "מחיקת רשימה", @@ -506,7 +508,7 @@ "notification.favourite": "הודעתך חובבה על ידי {name}", "notification.favourite.name_and_others_with_link": "{name} ועוד {count, plural,one {אחד נוסף}other {# נוספים}} חיבבו את הודעתך", "notification.follow": "{name} במעקב אחרייך", - "notification.follow.name_and_others": "{name} ועוד {count, plural,one {אחד אחר}other {# אחרים}} עקבו אחריך", + "notification.follow.name_and_others": "{name} ועוד {count, plural,one {מישהו} other {# אחרים}} החלו לעקוב אחריך", "notification.follow_request": "{name} ביקשו לעקוב אחריך", "notification.follow_request.name_and_others": "{name} ועוד {count, plural,one {אחד אחר}other {# אחרים}} ביקשו לעקוב אחריך", "notification.label.mention": "אזכור", @@ -514,6 +516,7 @@ "notification.label.private_reply": "תשובה בפרטי", "notification.label.reply": "תשובה", "notification.mention": "אזכור", + "notification.mentioned_you": "אוזכרת על ידי {name}", "notification.moderation-warning.learn_more": "למידע נוסף", "notification.moderation_warning": "קיבלת אזהרה מצוות ניהול התוכן", "notification.moderation_warning.action_delete_statuses": "חלק מהודעותיך הוסרו.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "שורת סינון מהיר", "notifications.column_settings.follow": "עוקבים חדשים:", "notifications.column_settings.follow_request": "בקשות מעקב חדשות:", + "notifications.column_settings.group": "קבוצה", "notifications.column_settings.mention": "פניות:", "notifications.column_settings.poll": "תוצאות סקר:", "notifications.column_settings.push": "התראות בדחיפה", @@ -838,7 +842,7 @@ "time_remaining.minutes": "נותרו {number, plural, one {# דקה} other {# דקות}}", "time_remaining.moments": "רגעים נותרו", "time_remaining.seconds": "נותרו {number, plural, one {# שניה} other {# שניות}}", - "trends.counter_by_accounts": "{count, plural, one {אדם אחד} other {{count} א.נשים}} {days, plural, one {מאז אתמול} two {ביומיים האחרונים} other {במשך {days} הימים האחרונים}}", + "trends.counter_by_accounts": "{count, plural, one {אדם אחד} other {{counter} א.נשים}} {days, plural, one {מאז אתמול} two {ביומיים האחרונים} other {במשך {days} הימים האחרונים}}", "trends.trending_now": "נושאים חמים", "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.", "units.short.billion": "{count} מליארד", @@ -850,6 +854,11 @@ "upload_error.poll": "לא ניתן להעלות קובץ עם סקר.", "upload_form.audio_description": "תאר/י עבור לקויי שמיעה", "upload_form.description": "תיאור לכבדי ראיה", + "upload_form.drag_and_drop.instructions": "כדי לבחור קובץ מוצמד, יש ללחוץ על מקש רווח או אנטר. בעת הגרירה, השתמשו במקשי החיצים כדי להזיז את הקובץ המוצמד בכל כיוון. לחצו רווח או אנטר בשנית כדי לעזוב את הקובץ במקומו החדש, או לחצו אסקייפ לביטול.", + "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/hi.json b/app/javascript/mastodon/locales/hi.json index 58b04a20cd363f..e0de4c84525ac1 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -151,7 +151,6 @@ "compose_form.poll.duration": "चुनाव की अवधि", "compose_form.poll.multiple": "बहुविकल्पी", "compose_form.poll.option_placeholder": "विकल्प {number}", - "compose_form.poll.single": "कोई एक चुनें", "compose_form.poll.switch_to_multiple": "कई विकल्पों की अनुमति देने के लिए पोल बदलें", "compose_form.poll.switch_to_single": "एक ही विकल्प के लिए अनुमति देने के लिए पोल बदलें", "compose_form.poll.type": "स्टाइल", @@ -349,8 +348,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..a6bd621a485f22 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Adatforgalom korlátozva", "alert.unexpected.message": "Váratlan hiba történt.", "alert.unexpected.title": "Hoppá!", + "alt_text_badge.title": "Helyettesítő szöveg", "announcement.announcement": "Közlemény", "attachments_list.unprocessed": "(feldolgozatlan)", "audio.hide": "Hang elrejtése", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Szavazás időtartama", "compose_form.poll.multiple": "Több lehetőség", "compose_form.poll.option_placeholder": "Válasz {number}", - "compose_form.poll.single": "Egyetlen válasz", + "compose_form.poll.single": "Feleletválasztós", "compose_form.poll.switch_to_multiple": "Szavazás megváltoztatása több választásosra", "compose_form.poll.switch_to_single": "Szavazás megváltoztatása egyetlen választásosra", "compose_form.poll.type": "Stílus", @@ -221,7 +222,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 +434,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", @@ -506,7 +508,7 @@ "notification.favourite": "{name} kedvencnek jelölte a bejegyzésedet", "notification.favourite.name_and_others_with_link": "{name} és {count, plural, one {# másik} other {# másik}} kedvencnek jelölte a bejegyzésedet", "notification.follow": "{name} követ téged", - "notification.follow.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} követni kezdett", + "notification.follow.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} követni kezdett", "notification.follow_request": "{name} követni szeretne téged", "notification.follow_request.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} kérte, hogy követhessen", "notification.label.mention": "Említés", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Privát válasz", "notification.label.reply": "Válasz", "notification.mention": "Említés", + "notification.mentioned_you": "{name} megemlített", "notification.moderation-warning.learn_more": "További információ", "notification.moderation_warning": "Moderációs figyelmeztetést kaptál", "notification.moderation_warning.action_delete_statuses": "Néhány bejegyzésedet eltávolították.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Gyorsszűrő sáv", "notifications.column_settings.follow": "Új követők:", "notifications.column_settings.follow_request": "Új követési kérések:", + "notifications.column_settings.group": "Csoportosítás", "notifications.column_settings.mention": "Megemlítések:", "notifications.column_settings.poll": "Szavazási eredmények:", "notifications.column_settings.push": "Leküldéses értesítések", @@ -850,6 +854,11 @@ "upload_error.poll": "Szavazásnál nem lehet fájlt feltölteni.", "upload_form.audio_description": "Leírás siket vagy hallássérült emberek számára", "upload_form.description": "Leírás vak vagy gyengénlátó emberek számára", + "upload_form.drag_and_drop.instructions": "Egy médiamelléklet kiválasztásához nyomj Szóközt vagy Entert. Húzás közben használd a nyílgombokat a médiamelléklet adott irányba történő mozgatásához. A médiamelléklet új pozícióba helyezéséhez nyomd meg a Szóközt vagy az Entert, vagy a megszakításhoz nyomd meg az Esc gombot.", + "upload_form.drag_and_drop.on_drag_cancel": "Az áthúzás megszakítva. A(z) {item} médiamelléklet el lett dobva.", + "upload_form.drag_and_drop.on_drag_end": "A(z) {item} médiamelléklet el lett dobva.", + "upload_form.drag_and_drop.on_drag_over": "A(z) {item} médiamelléklet át lett helyezve.", + "upload_form.drag_and_drop.on_drag_start": "A(z) {item} médiamelléklet fel lett véve.", "upload_form.edit": "Szerkesztés", "upload_form.thumbnail": "Bélyegkép megváltoztatása", "upload_form.video_description": "Leírás siket, hallássérült, vak vagy gyengénlátó emberek számára", 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..58e978cd146ec7 100644 --- a/app/javascript/mastodon/locales/ia.json +++ b/app/javascript/mastodon/locales/ia.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Excesso de requestas", "alert.unexpected.message": "Un error inexpectate ha occurrite.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Texto alt", "announcement.announcement": "Annuncio", "attachments_list.unprocessed": "(non processate)", "audio.hide": "Celar audio", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Durata del sondage", "compose_form.poll.multiple": "Selection multiple", "compose_form.poll.option_placeholder": "Option {number}", - "compose_form.poll.single": "Seliger un", "compose_form.poll.switch_to_multiple": "Cambiar le sondage pro permitter selectiones multiple", "compose_form.poll.switch_to_single": "Cambiar le sondage pro permitter selection singule", "compose_form.poll.type": "Stilo", @@ -221,7 +221,8 @@ "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_will_lose_num_followers": "Tu perdera {followersCount, plural, one {{followersCountDisplay} sequace} other {{followersCountDisplay} sequaces}} e {followingCount, plural, one {{followingCountDisplay} persona que tu seque} other {{followingCountDisplay} personas que tu seque}}.", + "domain_block_modal.you_will_lose_relationships": "Tu perdera tote le sequaces e le personas que tu seque ab iste servitor.", "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.", @@ -304,6 +305,7 @@ "filter_modal.select_filter.title": "Filtrar iste message", "filter_modal.title.status": "Filtrar un message", "filter_warning.matches_filter": "Corresponde al filtro “{title}”", + "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nemo} one {un persona} other {# personas}} que tu pote cognoscer", "filtered_notifications_banner.title": "Notificationes filtrate", "firehose.all": "Toto", "firehose.local": "Iste servitor", @@ -352,6 +354,9 @@ "hashtag.follow": "Sequer hashtag", "hashtag.unfollow": "Non sequer plus le hashtag", "hashtags.and_other": "…e {count, plural, one {}other {# plus}}", + "hints.profiles.followers_may_be_missing": "Le sequaces pro iste profilo pote mancar.", + "hints.profiles.follows_may_be_missing": "Sequites pro iste profilo pote mancar.", + "hints.profiles.posts_may_be_missing": "Alcun messages ab iste profilo pote mancar.", "hints.profiles.see_more_followers": "Vider plus de sequitores sur {domain}", "hints.profiles.see_more_follows": "Vider plus de sequites sur {domain}", "hints.profiles.see_more_posts": "Vider plus de messages sur {domain}", @@ -364,6 +369,11 @@ "home.pending_critical_update.link": "Vider actualisationes", "home.pending_critical_update.title": "Actualisation de securitate critic disponibile!", "home.show_announcements": "Monstrar annuncios", + "ignore_notifications_modal.disclaimer": "Mastodon non pote informar le usatores que tu ha ignorate lor avisos. Ignorar avisos non stoppara le messages mesme de esser inviate.", + "ignore_notifications_modal.filter_instead": "Filtrar in vice", + "ignore_notifications_modal.filter_to_act_users": "Tu ancora potera acceptar, rejectar, o reportar usatores", + "ignore_notifications_modal.filter_to_avoid_confusion": "Filtrar adjuta evitar confusion potential", + "ignore_notifications_modal.filter_to_review_separately": "Tu pote revider avisos filtrate separatemente", "ignore_notifications_modal.ignore": "Ignorar le notificationes", "ignore_notifications_modal.limited_accounts_title": "Ignorar le notificationes de contos moderate?", "ignore_notifications_modal.new_accounts_title": "Ignorar le notificationes de nove contos?", @@ -423,10 +433,10 @@ "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", + "lightbox.zoom_in": "Aggrandir a dimension actual", + "lightbox.zoom_out": "Aggrandir pro adaptar", "limited_account_hint.action": "Monstrar profilo in omne caso", "limited_account_hint.title": "Iste profilo ha essite celate per le moderatores de {domain}.", "link_preview.author": "Per {name}", @@ -493,14 +503,18 @@ "notification.admin.report_statuses": "{name} ha reportate {target} pro {category}", "notification.admin.report_statuses_other": "{name} ha reportate {target}", "notification.admin.sign_up": "{name} se ha inscribite", + "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# altere usator} other {altere # usatores}} se inscribeva", "notification.favourite": "{name} ha marcate tu message como favorite", + "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# altere} other {# alteres}} favoriva tu message", "notification.follow": "{name} te ha sequite", "notification.follow_request": "{name} ha requestate de sequer te", + "notification.follow_request.name_and_others": "{name} e {count, plural, one {# altere} other {# alteres}} ha demandate de sequer te", "notification.label.mention": "Mention", "notification.label.private_mention": "Mention private", "notification.label.private_reply": "Responsa private", "notification.label.reply": "Responder", "notification.mention": "Mention", + "notification.mentioned_you": "{name} te mentionava", "notification.moderation-warning.learn_more": "Apprender plus", "notification.moderation_warning": "Tu ha recipite un advertimento de moderation", "notification.moderation_warning.action_delete_statuses": "Alcunes de tu messages ha essite removite.", @@ -513,6 +527,7 @@ "notification.own_poll": "Tu sondage ha finite", "notification.poll": "Un sondage in le qual tu ha votate ha finite", "notification.reblog": "{name} ha impulsate tu message", + "notification.reblog.name_and_others_with_link": "{name} e {count, plural, one {# altere} other {# alteres}} promoveva tu message", "notification.relationships_severance_event": "Connexiones perdite con {name}", "notification.relationships_severance_event.account_suspension": "Un administrator de {from} ha suspendiute {target}. Isto significa que tu non pote plus reciper actualisationes de iste persona o interager con ille.", "notification.relationships_severance_event.domain_block": "Un administrator de {from} ha blocate {target}, includente {followersCount} de tu sequitores e {followingCount, plural, one {# conto} other {# contos}} que tu seque.", @@ -521,11 +536,21 @@ "notification.status": "{name} ha justo ora publicate", "notification.update": "{name} ha modificate un message", "notification_requests.accept": "Acceptar", + "notification_requests.accept_multiple": "{count, plural, one {Accepta # requesta…} other {Accepta # requestas…}}", + "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accepta requesta} other {Accepta requestas}}", + "notification_requests.confirm_accept_multiple.message": "Tu acceptara {count, plural, one {un requesta de aviso} other {# requestas de aviso}}. Desira tu vermente continuar?", "notification_requests.confirm_accept_multiple.title": "Acceptar petitiones de notification?", + "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Rejectar requesta} other {Rejectar requestas}}", + "notification_requests.confirm_dismiss_multiple.message": "Tu rejectara {count, plural, one {un requesta de aviso} other {# requestas de aviso}}. Tu non potera facilemente acceder {count, plural, one {lo} other {los}} ancora. Desira tu vermente continuar?", "notification_requests.confirm_dismiss_multiple.title": "Dimitter petitiones de notification?", "notification_requests.dismiss": "Clauder", + "notification_requests.dismiss_multiple": "{count, plural, one {Rejectar # requesta…} other {Rejectar # requestas…}}", "notification_requests.edit_selection": "Modificar", "notification_requests.exit_selection": "Facite", + "notification_requests.explainer_for_limited_account": "Le avisos ab iste conto ha essite filtrate perque le conto ha essite limitate per un moderator.", + "notification_requests.explainer_for_limited_remote_account": "Le avisos ab iste conto ha essite filtrate perque le conto o su servitor ha essite limitate per un moderator.", + "notification_requests.maximize": "Maximisar", + "notification_requests.minimize_banner": "Minimisar le bandiera del avisos filtrate", "notification_requests.notifications_from": "Notificationes de {name}", "notification_requests.title": "Notificationes filtrate", "notification_requests.view": "Vider notificationes", @@ -565,8 +590,11 @@ "notifications.permission_required": "Le notificationes de scriptorio es indisponibile perque le permission necessari non ha essite concedite.", "notifications.policy.accept": "Acceptar", "notifications.policy.accept_hint": "Monstrar in le notificationes", + "notifications.policy.drop": "Ignorar", + "notifications.policy.drop_hint": "Inviar al nihil, pro jammais esser vidite ancora", "notifications.policy.filter": "Filtrar", "notifications.policy.filter_hint": "Inviar al cassa de notificationes filtrate", + "notifications.policy.filter_limited_accounts_hint": "Limitate per moderatores de servitor", "notifications.policy.filter_limited_accounts_title": "Contos moderate", "notifications.policy.filter_new_accounts.hint": "Create in le ultime {days, plural, one {die} other {# dies}}", "notifications.policy.filter_new_accounts_title": "Nove contos", @@ -703,6 +731,7 @@ "report.unfollow_explanation": "Tu seque iste conto. Pro non plus vider su messages in tu fluxo de initio, cessa de sequer lo.", "report_notification.attached_statuses": "{count, plural, one {{count} message} other {{count} messages}} annexate", "report_notification.categories.legal": "Juridic", + "report_notification.categories.legal_sentence": "contento illegal", "report_notification.categories.other": "Alteres", "report_notification.categories.other_sentence": "alteres", "report_notification.categories.spam": "Spam", @@ -750,6 +779,7 @@ "status.bookmark": "Adder al marcapaginas", "status.cancel_reblog_private": "Disfacer impulso", "status.cannot_reblog": "Iste message non pote esser impulsate", + "status.continued_thread": "Argumento continuitate", "status.copy": "Copiar ligamine a message", "status.delete": "Deler", "status.detailed_status": "Vista detaliate del conversation", @@ -758,6 +788,7 @@ "status.edit": "Modificar", "status.edited": "Ultime modification le {date}", "status.edited_x_times": "Modificate {count, plural, one {{count} vice} other {{count} vices}}", + "status.embed": "Obtener codice incorporate", "status.favourite": "Adder al favorites", "status.favourites": "{count, plural, one {favorite} other {favorites}}", "status.filter": "Filtrar iste message", @@ -820,6 +851,11 @@ "upload_error.poll": "Incargamento de files non permittite con sondages.", "upload_form.audio_description": "Describe lo pro le gente con difficultates auditive", "upload_form.description": "Describe lo pro le gente con difficultates visual", + "upload_form.drag_and_drop.instructions": "Pro colliger un annexo de medios, pressar Spatio o Inviar. Trahente lo, usar le claves flecha pro mover le annexo de medios in ulle direction date. De novo pressar Spatio o Inviar pro deponer le annexo de medios in su nove position, o pressar Escappar pro cancellar.", + "upload_form.drag_and_drop.on_drag_cancel": "Le extraction era cancellate. Le annexo de medios {item} era deponite.", + "upload_form.drag_and_drop.on_drag_end": "Le annexo de medios {item} era deponite.", + "upload_form.drag_and_drop.on_drag_over": "Le annexo de medios {item} era movite.", + "upload_form.drag_and_drop.on_drag_start": "Annexo de medios {item} colligite.", "upload_form.edit": "Modificar", "upload_form.thumbnail": "Cambiar le miniatura", "upload_form.video_description": "Describe lo pro le gente con difficultates auditive o visual", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 687c32c1b155cf..085705714e3ebb 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -155,7 +155,6 @@ "compose_form.poll.duration": "Durasi japat", "compose_form.poll.multiple": "Pilihan ganda", "compose_form.poll.option_placeholder": "Opsi {number}", - "compose_form.poll.single": "Pilih Satu", "compose_form.poll.switch_to_multiple": "Ubah japat menjadi pilihan ganda", "compose_form.poll.switch_to_single": "Ubah japat menjadi pilihan tunggal", "compose_form.poll.type": "Gaya", @@ -219,7 +218,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 +379,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..f58cf1c71c7452 100644 --- a/app/javascript/mastodon/locales/ie.json +++ b/app/javascript/mastodon/locales/ie.json @@ -151,7 +151,6 @@ "compose_form.poll.duration": "Duration del balotation", "compose_form.poll.multiple": "Selection multiplic", "compose_form.poll.option_placeholder": "Option {number}", - "compose_form.poll.single": "Selecter un", "compose_form.poll.switch_to_multiple": "Changea li balotation por permisser multiplic selectiones", "compose_form.poll.switch_to_single": "Changea li balotation por permisser un singul selection", "compose_form.poll.type": "Stil", @@ -206,7 +205,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 +394,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/ig.json b/app/javascript/mastodon/locales/ig.json index 8a8d043a6b0089..b8b0f1084df117 100644 --- a/app/javascript/mastodon/locales/ig.json +++ b/app/javascript/mastodon/locales/ig.json @@ -33,7 +33,6 @@ "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.", "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", "compose_form.placeholder": "What is on your mind?", - "compose_form.poll.single": "Họrọ otu", "compose_form.publish_form": "Publish", "compose_form.reply": "Zaa", "compose_form.spoiler.marked": "Text is hidden behind warning", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index bb0a86ac2bbec9..21a8a084e75f3b 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,46 @@ "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.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 +215,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 +273,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 +304,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 +354,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 +369,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 +433,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 +458,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 +487,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 +498,70 @@ "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_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 +587,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 +641,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 +659,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 +685,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 +730,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 +764,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 +778,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 +808,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 +850,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..a6f85304cdf1a5 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Með takmörkum", "alert.unexpected.message": "Upp kom óvænt villa.", "alert.unexpected.title": "Úbbs!", + "alt_text_badge.title": "Hjálpartexti mynda", "announcement.announcement": "Auglýsing", "attachments_list.unprocessed": "(óunnið)", "audio.hide": "Fela hljóð", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Tímalengd könnunar", "compose_form.poll.multiple": "Margir valkostir", "compose_form.poll.option_placeholder": "Valkostur {number}", - "compose_form.poll.single": "Veldu eitt", + "compose_form.poll.single": "Eitt val", "compose_form.poll.switch_to_multiple": "Breyta könnun svo hægt sé að hafa marga valkosti", "compose_form.poll.switch_to_single": "Breyta könnun svo hægt sé að hafa einn stakan valkost", "compose_form.poll.type": "Stíll", @@ -221,7 +222,8 @@ "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_will_lose_num_followers": "Þú munt missa {followersCount, plural, one {{followersCountDisplay} fylgjanda} other {{followersCountDisplay} fylgjendur}} og {followingCount, plural, one {{followingCountDisplay} aðila sem þú fylgist með} other {{followingCountDisplay} aðila sem þú fylgist með}}.", + "domain_block_modal.you_will_lose_relationships": "Þú munt missa alla fylgjendur og þá sem þú fylgist með á þessum netþjóni.", "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,10 +434,10 @@ "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", + "lightbox.zoom_in": "Renna að raunstærð", + "lightbox.zoom_out": "Renna að svo passi", "limited_account_hint.action": "Birta notandasniðið samt", "limited_account_hint.title": "Þetta notandasnið hefur verið falið af umsjónarmönnum {domain}.", "link_preview.author": "Frá {name}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} setti færsluna þína í eftirlæti", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# í viðbót hefur} other {# í viðbót hafa}} sett færsluna þína í eftirlæti", "notification.follow": "{name} fylgist með þér", - "notification.follow.name_and_others": "{name} og {count, plural, one {# í viðbót fylgdist} other {# í viðbót fylgdust}} með þér", + "notification.follow.name_and_others": "{name} og {count, plural, one {# í viðbót fylgdist} other {# í viðbót fylgdust}} með þér", "notification.follow_request": "{name} hefur beðið um að fylgjast með þér", "notification.follow_request.name_and_others": "{name} og {count, plural, one {# í viðbót hefur} other {# í viðbót hafa}} beðið um að fylgjast með þér", "notification.label.mention": "Minnst á", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Einkasvar", "notification.label.reply": "Svara", "notification.mention": "Minnst á", + "notification.mentioned_you": "{name} minntist á þig", "notification.moderation-warning.learn_more": "Kanna nánar", "notification.moderation_warning": "Þú hefur fengið aðvörun frá umsjónarmanni", "notification.moderation_warning.action_delete_statuses": "Sumar færslurnar þínar hafa verið fjarlægðar.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Skyndisíustika", "notifications.column_settings.follow": "Nýir fylgjendur:", "notifications.column_settings.follow_request": "Nýjar beiðnir um að fylgjast með:", + "notifications.column_settings.group": "Hópur", "notifications.column_settings.mention": "Tilvísanir:", "notifications.column_settings.poll": "Niðurstöður könnunar:", "notifications.column_settings.push": "Ýti-tilkynningar", @@ -850,6 +854,11 @@ "upload_error.poll": "Innsending skráa er ekki leyfð í könnunum.", "upload_form.audio_description": "Lýstu þessu fyrir heyrnarskerta", "upload_form.description": "Lýstu þessu fyrir sjónskerta", + "upload_form.drag_and_drop.instructions": "Til að taka í myndefnisviðhengi skaltu ýta á bilslána eða Enter. Til að draga geturðu notað örvalyklana til að færa viðhengið í samsvarandi áttir. Ýttu aftur á bilslána eða Enter til að sleppa viðhenginu á nýja staðinn, eða ýttu á Escape til að hætta við.", + "upload_form.drag_and_drop.on_drag_cancel": "Hætt var við að draga. Myndefnisviðhenginu {item} var sleppt.", + "upload_form.drag_and_drop.on_drag_end": "Myndefnisviðhenginu {item} var sleppt.", + "upload_form.drag_and_drop.on_drag_over": "Myndefnisviðhengið {item} var fært.", + "upload_form.drag_and_drop.on_drag_start": "Tók í myndefnisviðhengið {item}.", "upload_form.edit": "Breyta", "upload_form.thumbnail": "Skipta um smámynd", "upload_form.video_description": "Lýstu þessu fyrir fólk sem heyrir illa eða er með skerta sjón", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 97518c586268a9..44040cc716a7fb 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Durata del sondaggio", "compose_form.poll.multiple": "Scelta multipla", "compose_form.poll.option_placeholder": "Opzione {number}", - "compose_form.poll.single": "Scegli uno", + "compose_form.poll.single": "Scelta singola", "compose_form.poll.switch_to_multiple": "Modifica il sondaggio per consentire scelte multiple", "compose_form.poll.switch_to_single": "Modifica il sondaggio per consentire una singola scelta", "compose_form.poll.type": "Stile", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} ha aggiunto il tuo post ai preferiti", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# altro} other {altri #}} hanno aggiunto il tuo post ai preferiti", "notification.follow": "{name} ha iniziato a seguirti", - "notification.follow.name_and_others": "{name} e {count, plural, one {# altro} other {altri #}} hanno iniziato a seguirti", + "notification.follow.name_and_others": "{name} e {count, plural, one {# altro} other {altri #}} hanno iniziato a seguirti", "notification.follow_request": "{name} ha richiesto di seguirti", "notification.follow_request.name_and_others": "{name} e {count, plural, one {# altro} other {altri #}} hanno richiesto di seguirti", "notification.label.mention": "Menziona", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Rispondi in privato", "notification.label.reply": "Rispondi", "notification.mention": "Menziona", + "notification.mentioned_you": "{name} ti ha menzionato", "notification.moderation-warning.learn_more": "Scopri di più", "notification.moderation_warning": "Hai ricevuto un avviso di moderazione", "notification.moderation_warning.action_delete_statuses": "Alcuni dei tuoi post sono stati rimossi.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra del filtro veloce", "notifications.column_settings.follow": "Nuovi seguaci:", "notifications.column_settings.follow_request": "Nuove richieste di seguirti:", + "notifications.column_settings.group": "Gruppo", "notifications.column_settings.mention": "Menzioni:", "notifications.column_settings.poll": "Risultati del sondaggio:", "notifications.column_settings.push": "Notifiche push", @@ -850,6 +854,11 @@ "upload_error.poll": "Caricamento del file non consentito con i sondaggi.", "upload_form.audio_description": "Descrizione per persone con deficit uditivi", "upload_form.description": "Descrizione per ipovedenti", + "upload_form.drag_and_drop.instructions": "Per selezionare un allegato multimediale, premi Spazio o Invio. Mentre trascini, usa i tasti con le frecce per spostare l'allegato multimediale in una qualsiasi direzione. Premi di nuovo Spazio o Invio per rilasciare l'allegato multimediale nella sua nuova posizione, oppure premi Esc per annullare.", + "upload_form.drag_and_drop.on_drag_cancel": "Il trascinamento è stato annullato. L'allegato multimediale {item} è stato eliminato.", + "upload_form.drag_and_drop.on_drag_end": "L'allegato multimediale {item} è stato eliminato.", + "upload_form.drag_and_drop.on_drag_over": "L'allegato multimediale {item} è stato spostato.", + "upload_form.drag_and_drop.on_drag_start": "L'allegato multimediale {item} è stato ricevuto.", "upload_form.edit": "Modifica", "upload_form.thumbnail": "Cambia la miniatura", "upload_form.video_description": "Descrizione per persone con deficit uditivi o ipovedenti", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 38492a73612b16..9aea55ec3f4c82 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.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": "音声を閉じる", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "アンケート期間", "compose_form.poll.multiple": "複数選択", "compose_form.poll.option_placeholder": "項目{number}", - "compose_form.poll.single": "単一選択", "compose_form.poll.switch_to_multiple": "複数選択に変更", "compose_form.poll.switch_to_single": "単一選択に変更", "compose_form.poll.type": "スタイル", @@ -221,7 +221,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": "「{followingCount, plural, other {{followingCountDisplay}フォロー}}」、「{followersCount, plural, other {{followersCountDisplay}フォロワー}}」を失うことになります。", + "domain_block_modal.you_will_lose_relationships": "このサーバーにいるすべてのフォローとフォロワーを失うことになります。", "domain_block_modal.you_wont_see_posts": "このサーバーのユーザーからの投稿や通知が閲覧できなくなります。", "domain_pill.activitypub_lets_connect": "Mastodonからほかのソーシャルアプリのユーザーへ、そのまた別のアプリのユーザーへと、それぞれが互いにつながり関わり合うことをこのActivityPubの仕組みが実現しています。", "domain_pill.activitypub_like_language": "ActivityPubとは、Mastodonがほかのサーバーと会話をするときにしゃべる「言葉」のようなものです。", @@ -432,10 +433,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 +458,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": "オプションを閉じる", @@ -505,7 +507,6 @@ "notification.favourite": "{name}さんがお気に入りしました", "notification.favourite.name_and_others_with_link": "{name}さんほか{count, plural, other {#人}}がお気に入りしました", "notification.follow": "{name}さんにフォローされました", - "notification.follow.name_and_others": "{name}さんほか{count, plural, other {#人}}にフォローされました", "notification.follow_request": "{name}さんがあなたにフォローリクエストしました", "notification.follow_request.name_and_others": "{name}さんほか{count, plural, other {#人}}があなたにフォローリクエストしました", "notification.label.mention": "メンション", @@ -513,6 +514,7 @@ "notification.label.private_reply": "非公開の返信", "notification.label.reply": "返信", "notification.mention": "メンション", + "notification.mentioned_you": "{name} さんがあなたに返信しました", "notification.moderation-warning.learn_more": "さらに詳しく", "notification.moderation_warning": "管理者から警告が来ています", "notification.moderation_warning.action_delete_statuses": "あなたによるいくつかの投稿が削除されました。", @@ -777,6 +779,7 @@ "status.bookmark": "ブックマーク", "status.cancel_reblog_private": "ブースト解除", "status.cannot_reblog": "この投稿はブーストできません", + "status.continued_thread": "続きのスレッド", "status.copy": "投稿へのリンクをコピー", "status.delete": "削除", "status.detailed_status": "詳細な会話ビュー", @@ -785,6 +788,7 @@ "status.edit": "編集", "status.edited": "最終更新日 {date}", "status.edited_x_times": "{count}回編集", + "status.embed": "埋め込みコードを取得", "status.favourite": "お気に入り", "status.favourites": "{count, plural, one {お気に入り} other {お気に入り}}", "status.filter": "この投稿をフィルターする", @@ -809,6 +813,7 @@ "status.reblogs.empty": "まだ誰もブーストしていません。ブーストされるとここに表示されます。", "status.redraft": "削除して下書きに戻す", "status.remove_bookmark": "ブックマークを削除", + "status.replied_in_thread": "ほかのユーザーへ", "status.replied_to": "{name}さんへの返信", "status.reply": "返信", "status.replyAll": "全員に返信", @@ -846,6 +851,11 @@ "upload_error.poll": "アンケートではファイルをアップロードできません。", "upload_form.audio_description": "聴き取りが難しいユーザーへの説明", "upload_form.description": "視覚的に閲覧が難しいユーザーへの説明", + "upload_form.drag_and_drop.instructions": "メディア添付ファイルを選択するには、スペースキーまたはエンターキーを押してください。ドラッグ中は、矢印キーを使ってメディア添付ファイルを任意の方向に移動できます。再度スペースキーまたはエンターキーを押すと新しい位置にメディア添付ファイルをドロップできます。キャンセルするにはエスケープキーを押してください。", + "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/kab.json b/app/javascript/mastodon/locales/kab.json index 822fb59e6f85f8..9cf94f26062bb0 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -1,5 +1,5 @@ { - "about.blocks": "Ulac agbur", + "about.blocks": "Iqeddacen yettwaɛassen", "about.contact": "Anermis:", "about.disclaimer": "Mastodon d aseɣẓan ilelli, d aseɣẓan n uɣbalu yeldin, d tnezzut n Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Ulac taɣẓint", @@ -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", @@ -135,7 +137,6 @@ "compose_form.poll.duration": "Tanzagt n tefrant", "compose_form.poll.multiple": "Aṭas n ufran", "compose_form.poll.option_placeholder": "Taxtiṛt {number}", - "compose_form.poll.single": "Fren yiwen", "compose_form.poll.type": "Aɣanib", "compose_form.publish": "Suffeɣ", "compose_form.publish_form": "Tasuffeɣt tamaynut", @@ -190,7 +191,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ḍ", @@ -276,6 +277,8 @@ "hashtag.counter_by_uses_today": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}} assa", "hashtag.follow": "Ḍfeṛ ahacṭag", "hashtags.and_other": "…d {count, plural, one {}other {# nniḍen}}", + "hints.threads.replies_may_be_missing": "Tiririyin d-yusan deg iqeddacen nniḍen, yezmer ur d-ddant ara.", + "hints.threads.see_more": "Wali ugar n tririt deg {domain}", "home.column_settings.show_reblogs": "Ssken-d beṭṭu", "home.column_settings.show_replies": "Ssken-d tiririyin", "home.hide_announcements": "Ffer ulɣuyen", @@ -332,8 +335,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 +357,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", @@ -550,6 +551,7 @@ "report_notification.attached_statuses": "{count, plural, one {{count} n tsuffeɣt} other {{count} n tsuffiɣin}} ttwaqnent", "report_notification.categories.legal": "Azerfan", "report_notification.categories.other": "Ayen nniḍen", + "report_notification.categories.other_sentence": "ayen nniḍen", "report_notification.categories.spam": "Aspam", "report_notification.categories.spam_sentence": "aspam", "report_notification.open": "Ldi aneqqis", @@ -584,12 +586,15 @@ "status.bookmark": "Creḍ", "status.cancel_reblog_private": "Sefsex beṭṭu", "status.cannot_reblog": "Tasuffeɣt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen", + "status.continued_thread": "Asqerdec yettkemmil", "status.copy": "Nɣel assaɣ ɣer tasuffeɣt", "status.delete": "Kkes", "status.direct": "Bder-d @{name} weḥd-s", "status.direct_indicator": "Abdar uslig", "status.edit": "Ẓreg", + "status.edited": "Taẓrigt taneggarut {date}", "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", @@ -613,9 +618,10 @@ "status.reblogs.empty": "Ula yiwen ur yebḍi tajewwiqt-agi ar tura. Ticki yebḍa-tt yiwen, ad d-iban da.", "status.redraft": "Kkes tɛiwdeḍ tira", "status.remove_bookmark": "Kkes tacreḍt", + "status.replied_in_thread": "Y·t·erra-d deg usqerdec", "status.replied_to": "Y·terra-yas i {name}", "status.reply": "Err", - "status.replyAll": "Err i lxiḍ", + "status.replyAll": "Err i wesqerdec", "status.report": "Cetki ɣef @{name}", "status.sensitive_warning": "Agbur amḥulfu", "status.share": "Bḍu", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index cf2082e105d42f..6b1dc6b365dda1 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": "액티비티펍은 마스토돈이 다른 소셜 네트워크와 대화할 때 쓰는 언어 같은 것입니다.", @@ -315,7 +317,7 @@ "follow_suggestions.curated_suggestion": "스태프의 추천", "follow_suggestions.dismiss": "다시 보지 않기", "follow_suggestions.featured_longer": "{domain} 팀이 손수 고름", - "follow_suggestions.friends_of_friends_longer": "내가 팔로우 하는 사람들 사이에서 인기", + "follow_suggestions.friends_of_friends_longer": "내가 팔로우한 사람들 사이에서 인기", "follow_suggestions.hints.featured": "이 프로필은 {domain} 팀이 손수 선택했습니다.", "follow_suggestions.hints.friends_of_friends": "이 프로필은 내가 팔로우 하는 사람들에게서 유명합니다.", "follow_suggestions.hints.most_followed": "이 프로필은 {domain}에서 가장 많이 팔로우 된 사람들 중 하나입니다.", @@ -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}", @@ -497,7 +499,7 @@ "navigation_bar.security": "보안", "not_signed_in_indicator.not_signed_in": "이 정보에 접근하려면 로그인을 해야 합니다.", "notification.admin.report": "{name} 님이 {target}를 신고했습니다", - "notification.admin.report_account": "{name} 님이 {target}의 게시물 {count, plural, other {# 개}}를 {category}로 신고했습니다", + "notification.admin.report_account": "{name} 님이 {target}의 게시물 {count, plural, other {# 개}}를 {category} 사유로 신고했습니다", "notification.admin.report_account_other": "{name} 님이 {target}의 게시물 {count, plural, other {# 개}}를 신고했습니다", "notification.admin.report_statuses": "{name} 님이 {target}을 {category}로 신고했습니다", "notification.admin.report_statuses_other": "{name} 님이 {target}을 신고했습니다", @@ -506,7 +508,7 @@ "notification.favourite": "{name} 님이 내 게시물을 좋아합니다", "notification.favourite.name_and_others_with_link": "{name} 외 {count, plural, other {# 명}}이 내 게시물을 좋아합니다", "notification.follow": "{name} 님이 나를 팔로우했습니다", - "notification.follow.name_and_others": "{name} 외 {count, plural, other {# 명}}이 날 팔로우 했습니다", + "notification.follow.name_and_others": "{name} 외 {count, plural, other {# 명}}이 날 팔로우했습니다", "notification.follow_request": "{name} 님이 팔로우 요청을 보냈습니다", "notification.follow_request.name_and_others": "{name} 외 {count, plural, other {# 명}}이 나에게 팔로우 요청을 보냈습니다", "notification.label.mention": "멘션", @@ -514,6 +516,7 @@ "notification.label.private_reply": "개인 답글", "notification.label.reply": "답글", "notification.mention": "멘션", + "notification.mentioned_you": "{name} 님의 멘션", "notification.moderation-warning.learn_more": "더 알아보기", "notification.moderation_warning": "중재 경고를 받았습니다", "notification.moderation_warning.action_delete_statuses": "게시물 몇 개가 삭제되었습니다.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "빠른 필터 막대", "notifications.column_settings.follow": "새 팔로워:", "notifications.column_settings.follow_request": "새 팔로우 요청:", + "notifications.column_settings.group": "그룹화", "notifications.column_settings.mention": "멘션:", "notifications.column_settings.poll": "설문 결과:", "notifications.column_settings.push": "푸시 알림", @@ -850,6 +854,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..147546c9773146 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", @@ -82,6 +85,7 @@ "alert.rate_limited.title": "Trafiko limitado", "alert.unexpected.message": "Afito un yerro no asperado.", "alert.unexpected.title": "Atyo!", + "alt_text_badge.title": "Teksto alternativo", "announcement.announcement": "Pregon", "attachments_list.unprocessed": "(no prosesado)", "audio.hide": "Eskonde audio", @@ -151,7 +155,6 @@ "compose_form.poll.duration": "Durasion de anketa", "compose_form.poll.multiple": "Multiples opsyones", "compose_form.poll.option_placeholder": "Opsyon {number}", - "compose_form.poll.single": "Eskoje uno", "compose_form.poll.switch_to_multiple": "Troka anketa para permeter a eskojer mas ke una opsyon", "compose_form.poll.switch_to_single": "Troka anketa para permeter a eskojer solo una opsyon", "compose_form.poll.type": "Estilo", @@ -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:", @@ -332,6 +334,11 @@ "hashtag.follow": "Sige etiketa", "hashtag.unfollow": "Desige etiketa", "hashtags.and_other": "…i {count, plural, one {}other {# mas}}", + "hints.profiles.see_more_followers": "Ve mas suivantes en {domain}", + "hints.profiles.see_more_follows": "Ve mas segidos en {domain}", + "hints.profiles.see_more_posts": "Ve mas puvlikasyones en {domain}", + "hints.threads.replies_may_be_missing": "Puede mankar repuestas de otros sirvidores.", + "hints.threads.see_more": "Ve mas repuestas en {domain}", "home.column_settings.show_reblogs": "Amostra repartajasyones", "home.column_settings.show_replies": "Amostra repuestas", "home.hide_announcements": "Eskonde pregones", @@ -340,6 +347,10 @@ "home.pending_critical_update.title": "Aktualizasyon de seguridad kritika esta desponivle!", "home.show_announcements": "Amostra pregones", "ignore_notifications_modal.ignore": "Inyora avizos", + "ignore_notifications_modal.limited_accounts_title": "Inyorar avizos de kuentos moderados?", + "ignore_notifications_modal.new_accounts_title": "Inyorar avizos de kuentos muevos?", + "ignore_notifications_modal.not_followers_title": "Inyorar avizos de personas a las kualas no te sigen?", + "ignore_notifications_modal.not_following_title": "Inyorar avizos de personas a las kualas no siges?", "interaction_modal.description.favourite": "Kon un kuento en Mastodon, puedes markar esta publikasyon komo favorita para ke el autor sepa ke te plaze i para guadrarla para dempues.", "interaction_modal.description.follow": "Kon un kuento en Mastodon, puedes segir a {name} para risivir sus publikasyones en tu linya temporal prinsipala.", "interaction_modal.description.reblog": "Kon un kuento en Mastodon, puedes repartajar esta publikasyon para amostrarla a tus suivantes.", @@ -393,8 +404,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 +427,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", @@ -464,6 +474,7 @@ "notification.label.private_mention": "Enmentadura privada", "notification.label.reply": "Arisponde", "notification.mention": "Enmenta", + "notification.mentioned_you": "{name} te enmento", "notification.moderation-warning.learn_more": "Ambezate mas", "notification.moderation_warning.action_disable": "Tu kuento tiene sido inkapasitado.", "notification.moderation_warning.action_mark_statuses_as_sensitive": "Algunas de tus publikasyones tienen sido markadas komo sensivles.", @@ -481,6 +492,7 @@ "notification_requests.dismiss": "Kita", "notification_requests.edit_selection": "Edita", "notification_requests.exit_selection": "Fecho", + "notification_requests.maximize": "Maksimizar", "notification_requests.notifications_from": "Avizos de {name}", "notification_requests.title": "Avizos filtrados", "notification_requests.view": "Amostra avizos", @@ -495,6 +507,7 @@ "notifications.column_settings.filter_bar.category": "Vara de filtrado rapido", "notifications.column_settings.follow": "Muevos suivantes:", "notifications.column_settings.follow_request": "Muevas solisitudes de segimiento:", + "notifications.column_settings.group": "Grupo", "notifications.column_settings.mention": "Enmentaduras:", "notifications.column_settings.poll": "Rizultados de anketas:", "notifications.column_settings.push": "Avizos arrepushados", @@ -522,6 +535,7 @@ "notifications.policy.accept_hint": "Amostra en avizos", "notifications.policy.drop": "Inyora", "notifications.policy.filter": "Filtra", + "notifications.policy.filter_limited_accounts_title": "Kuentos moderados", "notifications.policy.filter_new_accounts.hint": "Kriyadas durante {days, plural, one {el ultimo diya} other {los ultimos # diyas}}", "notifications.policy.filter_new_accounts_title": "Muevos kuentos", "notifications.policy.filter_not_followers_title": "Personas ke te no sigen", @@ -654,6 +668,7 @@ "report.unfollow_explanation": "Estas sigiendo este kuento. Para no ver sus publikasyones en tu linya de tiempo, puedes deshar de segirlo.", "report_notification.attached_statuses": "{count, plural, one {{count} publikasyon} other {{count} publikasyones}} atadas", "report_notification.categories.legal": "Legal", + "report_notification.categories.legal_sentence": "kontenido ilegal", "report_notification.categories.other": "Otros", "report_notification.categories.other_sentence": "otros", "report_notification.categories.spam": "Spam", @@ -728,6 +743,7 @@ "status.reblogs.empty": "Ainda nadie tiene repartajado esta publikasyon. Kuando algien lo aga, se amostrara aki.", "status.redraft": "Efasa i eskrive de muevo", "status.remove_bookmark": "Kita markador", + "status.replied_in_thread": "Arispondo en filo", "status.replied_to": "Arispondio a {name}", "status.reply": "Arisponde", "status.replyAll": "Arisponde al filo", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 5a510f5b96c986..60d0acf7a1007e 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!", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Apklausos trukmė", "compose_form.poll.multiple": "Keli pasirinkimai", "compose_form.poll.option_placeholder": "{number} parinktis", - "compose_form.poll.single": "Pasirinkti vieną", "compose_form.poll.switch_to_multiple": "Keisti apklausą, kad būtų leidžiama pasirinkti kelis pasirinkimus", "compose_form.poll.switch_to_single": "Keisti apklausą, kad būtų leidžiama pasirinkti vieną pasirinkimą", "compose_form.poll.type": "Stilius", @@ -221,7 +221,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 +433,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}", @@ -504,6 +505,7 @@ "notification.admin.sign_up": "{name} užsiregistravo", "notification.favourite": "{name} pamėgo tavo įrašą", "notification.follow": "{name} seka tave", + "notification.follow.name_and_others": "{name} ir {count, plural, one {# kitas} few {# kiti} many {# kito} other {# kitų}} seka tave", "notification.follow_request": "{name} paprašė tave sekti", "notification.label.mention": "Paminėjimas", "notification.label.private_mention": "Privatus paminėjimas", @@ -557,6 +559,7 @@ "notifications.column_settings.filter_bar.category": "Spartaus filtro juosta", "notifications.column_settings.follow": "Nauji sekėjai:", "notifications.column_settings.follow_request": "Nauji sekimo prašymai:", + "notifications.column_settings.group": "Grupė", "notifications.column_settings.mention": "Paminėjimai:", "notifications.column_settings.poll": "Balsavimo rezultatai:", "notifications.column_settings.push": "Tiesioginiai pranešimai", @@ -766,7 +769,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 +841,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..7d325c057d3d32 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -153,7 +153,6 @@ "compose_form.poll.duration": "Aptaujas ilgums", "compose_form.poll.multiple": "Vairākas izvēles iespējas", "compose_form.poll.option_placeholder": "Izvēle {number}", - "compose_form.poll.single": "Jāizvēlas viens", "compose_form.poll.switch_to_multiple": "Mainīt aptaujas veidu, lai atļautu vairākas izvēles", "compose_form.poll.switch_to_single": "Mainīt aptaujas veidu, lai atļautu vienu izvēli", "compose_form.poll.type": "Stils", @@ -215,7 +214,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 +383,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/ml.json b/app/javascript/mastodon/locales/ml.json index 5ed6f219db5ae0..b7a2ad2a3f002a 100644 --- a/app/javascript/mastodon/locales/ml.json +++ b/app/javascript/mastodon/locales/ml.json @@ -5,19 +5,25 @@ "about.domain_blocks.silenced.title": "പരിമിതമായത്", "about.domain_blocks.suspended.title": "താൽക്കാലികമായി നിർത്തിവെച്ചിരിക്കുന്നു", "about.rules": "സെർവ്വർ നിയമങ്ങൾ", + "account.account_note_header": "സ്വകാര്യ കുറിപ്പു്", "account.add_or_remove_from_list": "പട്ടികയിൽ ചേർക്കുകയോ/മാറ്റുകയോ ചെയ്യുക", "account.badges.bot": "റോബോട്ട്", "account.badges.group": "ഗ്രൂപ്പ്", "account.block": "@{name} -നെ തടയുക", "account.block_domain": "{domain} എന്ന മേഖല തടയുക", + "account.block_short": "തടസ്സപെടുത്തുക", "account.blocked": "തടഞ്ഞു", "account.cancel_follow_request": "Withdraw follow request", + "account.copy": "രൂപരേഖയിന്റെ വിലാസം പകർത്തുക", + "account.direct": "സ്വകാരൃമായിട്ടു് @{name}-ന് സൂചനപിക്കുക", "account.disable_notifications": "@{name} പോസ്റ്റുചെയ്യുന്നത് എന്നെ അറിയിക്കുന്നത് നിർത്തുക", "account.domain_blocked": "മേഖല തടഞ്ഞു", "account.edit_profile": "പ്രൊഫൈൽ തിരുത്തുക", "account.enable_notifications": "@{name} പോസ്റ്റ് ചെയ്യുമ്പോൾ എന്നെ അറിയിക്കുക", "account.endorse": "പ്രൊഫൈലിൽ പ്രകടമാക്കുക", + "account.featured_tags.last_status_never": "എഴുത്തുകളില്ല", "account.follow": "പിന്തുടരുക", + "account.follow_back": "തിരിച്ചു പിന്തുടരുക", "account.followers": "പിന്തുടരുന്നവർ", "account.followers.empty": "ഈ ഉപയോക്താവിനെ ആരും ഇതുവരെ പിന്തുടരുന്നില്ല.", "account.following": "പിന്തുടരുന്നു", @@ -31,7 +37,11 @@ "account.media": "മീഡിയ", "account.mention": "@{name} സൂചിപ്പിക്കുക", "account.mute": "@{name}-നെ(യെ) നിശ്ശബ്ദമാക്കൂ", + "account.mute_notifications_short": "അറിയിപ്പുകൾ മിണ്ടാതാക്കുക", + "account.mute_short": "മിണ്ടാതാക്കുക", "account.muted": "നിശ്ശബ്ദമാക്കിയിരിക്കുന്നു", + "account.no_bio": "വിവരണം നല്കുിയിട്ടില്ല.", + "account.open_original_page": "ആദ്യത്തു് താൾ തുറക്കുക", "account.posts": "പോസ്റ്റുകൾ", "account.posts_with_replies": "പോസ്റ്റുകളും മറുപടികളും", "account.report": "റിപ്പോർട്ട് ചെയ്യുക @{name}", @@ -52,10 +62,16 @@ "alert.rate_limited.title": "തോത് പരിമിതപ്പെടുത്തിയിരിക്കുന്നു", "alert.unexpected.message": "അപ്രതീക്ഷിതമായി എന്തോ സംഭവിച്ചു.", "alert.unexpected.title": "ശ്ശോ!", + "alt_text_badge.title": "പകരമായ വരി", "announcement.announcement": "അറിയിപ്പ്", "attachments_list.unprocessed": "(പ്രോസസ്സ് ചെയ്യാത്തത്)", "audio.hide": "ശബ്ദം ഒഴിവാക്കുക", + "block_modal.show_less": "കുറച്ചു് കാണിക്കുക", + "block_modal.show_more": "ഇനിയും കാണിക്കുക", + "block_modal.title": "ഉപയോക്താവിനു് തടസ്സപെടുത്തുക?", "boost_modal.combo": "അടുത്ത തവണ ഇത് ഒഴിവാക്കുവാൻ {combo} ഞെക്കാവുന്നതാണ്", + "bundle_column_error.copy_stacktrace": "പിഴരേഖ പകർത്തുക", + "bundle_column_error.error.title": "അയ്യോ!", "bundle_column_error.network.title": "നെറ്റ്‍വർക്ക് പിശക്", "bundle_column_error.retry": "വീണ്ടും ശ്രമിക്കുക", "bundle_column_error.return": "ഹോം പേജിലേക്ക് മടങ്ങാം", @@ -66,14 +82,16 @@ "closed_registrations.other_server_instructions": "Mastodon വികേന്ദ്രീകൃത സംവിധാനം ആയതിനാൽ, നിങ്ങൾക്ക് മറ്റൊരു സെർവറിൽ ഒരു അക്കൗണ്ട് ഉണ്ടാക്കിയും ഇതുമായി ആശയവിനിമയം നടത്താൻ സാധിക്കുന്നതാണ്.", "closed_registrations_modal.description": "{domain} ഇൽ ഇപ്പോൾ അക്കൗണ്ട് ഉണ്ടാക്കാൻ സാധിക്കുന്നതല്ല, Mastodon ഉപയോഗിക്കുന്നതിനായി നിങ്ങൾക്ക് {domain}-ൽ പ്രത്യേകമായി ഒരു അക്കൗണ്ട് ആവശ്യമില്ല എന്നത് ദയവായി ഓർക്കുക.", "closed_registrations_modal.find_another_server": "മറ്റൊരു സെർവർ കണ്ടെത്തുക", + "closed_registrations_modal.title": "മാസ്റ്റഡോണിൽ ചേർക്കൽ", "column.about": "അപ്ലിക്കേഷനെക്കുറിച്ച്", "column.blocks": "തടയപ്പെട്ട ഉപയോക്താക്കൾ", "column.bookmarks": "ബുക്ക്മാർക്കുകൾ", "column.community": "പ്രാദേശികമായ സമയരേഖ", "column.directory": "പ്രൊഫൈലുകൾ മറിച്ചുനോക്കുക", "column.domain_blocks": "മറയ്ക്കപ്പെട്ട മേഖലകൾ", + "column.favourites": "പ്രിയപ്പെട്ടതു്", "column.follow_requests": "പിന്തുടരാനുള്ള അഭ്യർത്ഥനകൾ", - "column.home": "ഹോം", + "column.home": "ആമുഖം", "column.lists": "പട്ടികകൾ", "column.mutes": "നിശബ്ദമാക്കപ്പെട്ട ഉപയോക്താക്കൾ", "column.notifications": "അറിയിപ്പുകൾ", @@ -89,27 +107,41 @@ "column_subheading.settings": "ക്രമീകരണങ്ങള്‍", "community.column_settings.local_only": "പ്രാദേശികം മാത്രം", "community.column_settings.media_only": "മാധ്യമങ്ങൾ മാത്രം", + "community.column_settings.remote_only": "വിദൂര മാത്രം", "compose.language.change": "ഭാഷ മാറ്റുക", "compose.language.search": "ഭാഷകൾ തിരയുക...", + "compose.published.open": "തുറക്കുക", "compose_form.direct_message_warning_learn_more": "കൂടുതൽ പഠിക്കുക", "compose_form.encryption_warning": "Mastodon-ലെ പോസ്റ്റുകൾ എൻഡ്-ടു-എൻഡ് എൻക്രിപ്റ്റ് ചെയ്തവയല്ല. അതിനാൽ Mastodon-ൽ പ്രധാനപ്പെട്ട വിവരങ്ങളൊന്നും പങ്കിടരുത്.", "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", "compose_form.lock_disclaimer.lock": "ലോക്കുചെയ്തു", "compose_form.placeholder": "നിങ്ങളുടെ മനസ്സിൽ എന്താണ്?", "compose_form.poll.duration": "തിരഞ്ഞെടുപ്പിന്റെ സമയദൈർഖ്യം", + "compose_form.poll.multiple": "ഒരുപാടു് സാധ്യതകൾ", + "compose_form.poll.option_placeholder": "സാധ്യത {number}", + "compose_form.poll.single": "ഒറ്റ സാധ്യത", "compose_form.poll.switch_to_multiple": "വോട്ടെടുപ്പിൽ ഒന്നിലധികം ചോയ്‌സുകൾ ഉൾപ്പെടുതുക", "compose_form.poll.switch_to_single": "വോട്ടെടുപ്പിൽ ഒരൊറ്റ ചോയ്‌സ്‌ മാത്രം ആക്കുക", + "compose_form.poll.type": "രീതി", + "compose_form.publish": "അയക്കുക", "compose_form.publish_form": "Publish", + "compose_form.reply": "മറുപടി", + "compose_form.save_changes": "കാലാനുസ്യതമാക്കുക", "compose_form.spoiler.marked": "എഴുത്ത് മുന്നറിയിപ്പിനാൽ മറച്ചിരിക്കുന്നു", "compose_form.spoiler.unmarked": "എഴുത്ത് മറയ്ക്കപ്പെട്ടിട്ടില്ല", "confirmation_modal.cancel": "റദ്ദാക്കുക", "confirmations.block.confirm": "തടയുക", "confirmations.delete.confirm": "മായ്ക്കുക", "confirmations.delete.message": "ഈ ടൂട്ട് ഇല്ലാതാക്കണം എന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ?", + "confirmations.delete.title": "എഴുത്തുൾ മായ്ക്കുക?", "confirmations.delete_list.confirm": "മായ്ക്കുക", "confirmations.delete_list.message": "ഈ പട്ടിക എന്നെന്നേക്കുമായി നീക്കം ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?", + "confirmations.delete_list.title": "പട്ടിക കളയുണോ?", + "confirmations.discard_edit_media.confirm": "കളയുക", + "confirmations.edit.confirm": "സംശോധിക്കുക", "confirmations.logout.confirm": "പുറത്തുകടക്കുക", "confirmations.logout.message": "നിങ്ങൾക്ക് ലോഗ് ഔട്ട് ചെയ്യണമെന്ന് ഉറപ്പാണോ?", + "confirmations.logout.title": "പുറത്തിറങ്ങുക?", "confirmations.mute.confirm": "നിശ്ശബ്ദമാക്കുക", "confirmations.redraft.confirm": "മായിച്ച് മാറ്റങ്ങൾ വരുത്തി വീണ്ടും എഴുതുക", "confirmations.reply.confirm": "മറുപടി", @@ -125,9 +157,12 @@ "directory.local": "{domain} ൽ നിന്ന് മാത്രം", "directory.new_arrivals": "പുതിയ വരവുകൾ", "directory.recently_active": "അടുത്തിടെയായി സജീവമായ", + "disabled_account_banner.account_settings": "ഇടപാടു് ക്രമീകരങ്ങൾ", "disabled_account_banner.text": "നിങ്ങളുടെ {disabledAccount} എന്ന അക്കൗണ്ട് ഇപ്പോൾ പ്രവർത്തനരഹിതമാണ്.", "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.title": "മേഖല തടസ്സപെടുത്തുക?", + "domain_pill.username": "ഉപയോക്തൃപേരു്", "embed.instructions": "ചുവടെയുള്ള കോഡ് പകർത്തിക്കൊണ്ട് നിങ്ങളുടെ വെബ്‌സൈറ്റിൽ ഈ ടൂട്ട് ഉൾച്ചേർക്കുക.", "embed.preview": "ഇത് ഇങ്ങനെ കാണപ്പെടും:", "emoji_button.activity": "പ്രവര്‍ത്തനം", @@ -158,10 +193,28 @@ "empty_column.notifications": "നിങ്ങൾക്ക് ഇതുവരെ ഒരു അറിയിപ്പുകളും ഇല്ല. മറ്റുള്ളവരുമായി ഇടപെട്ട് സംഭാഷണത്തിന് തുടക്കം കുറിക്കു.", "empty_column.public": "ഇവിടെ ഒന്നുമില്ലല്ലോ! ഇവിടെ നിറയ്ക്കാൻ എന്തെങ്കിലും പരസ്യമായി എഴുതുകയോ മറ്റ് ഉപഭോക്താക്കളെ പിന്തുടരുകയോ ചെയ്യുക", "errors.unexpected_crash.report_issue": "പ്രശ്നം അറിയിക്കുക", + "explore.search_results": "തിരയൽ ഫലങ്ങൾ", + "explore.suggested_follows": "ആൾക്കാർ", "explore.title": "പര്യവേക്ഷണം നടത്തുക", + "explore.trending_links": "വാര്‍ത്ത", + "explore.trending_statuses": "എഴുത്തുകൾ", + "explore.trending_tags": "ചർച്ചാവിഷയങ്ങൾ", + "filter_modal.added.review_and_configure_title": "അരിക്കൽ ക്രമീകരങ്ങൾ", "filter_modal.select_filter.prompt_new": "പുതിയ വിഭാഗം: {name}", + "filter_modal.select_filter.search": "തിരയുക അല്ലെങ്കിൽ നിർമാണിക്കുക", + "firehose.all": "എല്ലാം", "follow_request.authorize": "ചുമതലപ്പെടുത്തുക", "follow_request.reject": "നിരസിക്കുക", + "follow_suggestions.dismiss": "വീണ്ടും കാണിക്കരുതു്", + "follow_suggestions.view_all": "എല്ലാം കാണുക", + "follow_suggestions.who_to_follow": "ആരേ പിന്തുടരണം", + "followed_tags": "പിന്തുടരിയതു് ചർച്ചാവിഷയങ്ങൾ", + "footer.directory": "രൂപരേഖ നാമഗൃഹസൂചി", + "footer.get_app": "ഉപകരണം ലഭിക്കൂ", + "footer.invite": "ആളുകളെ ക്ഷണിക്കുക", + "footer.privacy_policy": "സ്വകാര്യത്തനയം", + "footer.source_code": "ഉറവിടസങ്കേതം കാണുക", + "footer.status": "അവസ്ഥ", "generic.saved": "സംരക്ഷിച്ചു", "getting_started.heading": "തുടക്കം കുറിക്കുക", "hashtag.column_header.tag_mode.all": "{additional} ഉം കൂടെ", @@ -173,11 +226,19 @@ "hashtag.column_settings.tag_mode.any": "ഇവയിലേതെങ്കിലും", "hashtag.column_settings.tag_mode.none": "ഇതിലൊന്നുമല്ല", "hashtag.column_settings.tag_toggle": "ഈ എഴുത്തുപംക്തിക്ക് കൂടുതൽ ഉപനാമങ്ങൾ ചേർക്കുക", + "hashtag.follow": "ചർച്ചാവിഷയം പിന്തുടരുക", + "hashtag.unfollow": "ചർച്ചാവിഷയം പിന്തുടരരുതു്", "home.column_settings.show_reblogs": "ബൂസ്റ്റുകൾ കാണിക്കുക", "home.column_settings.show_replies": "മറുപടികൾ കാണിക്കുക", "home.hide_announcements": "പ്രഖ്യാപനങ്ങൾ മറയ്‌ക്കുക", + "home.pending_critical_update.link": "പുതുകൾ കാണുക", "home.show_announcements": "പ്രഖ്യാപനങ്ങൾ കാണിക്കുക", + "interaction_modal.login.action": "ആമുഖം വരെ എടുത്തോണ്ടു് പോവുക", + "interaction_modal.login.prompt": "ആമുഖപ്രദാനിയുടെ മേഖലപേരു്. ഉദ: mastodon.social", + "interaction_modal.no_account_yet": "മാസ്റ്റഡോണിൽ ഇല്ലേ?", "interaction_modal.on_this_server": "ഈ സെർവറീൽ", + "interaction_modal.title.favourite": "പ്രിയപ്പെട്ട {name}-ന്റെ എഴുതു്", + "interaction_modal.title.follow": "{name}-െ പിന്തുടരുക", "keyboard_shortcuts.back": "തിരികെ പോകുക", "keyboard_shortcuts.blocked": "to open blocked users list", "keyboard_shortcuts.boost": "ബൂസ്റ്റ് ചെയ്യുക", @@ -189,7 +250,7 @@ "keyboard_shortcuts.enter": "ടൂട്ട് എടുക്കാൻ", "keyboard_shortcuts.federated": "to open federated timeline", "keyboard_shortcuts.heading": "കീബോർഡ് എളുപ്പവഴികൾ", - "keyboard_shortcuts.home": "ഹോം ടൈംലൈൻ തുറക്കുന്നതിന്", + "keyboard_shortcuts.home": "ആമുഖം സമയരേഖ തുറക്കുക", "keyboard_shortcuts.legend": "to display this legend", "keyboard_shortcuts.local": "പ്രാദേശിക സമയരേഖ തുറക്കാൻ", "keyboard_shortcuts.mention": "രചയിതാവിനെ സൂചിപ്പിക്കാൻ", @@ -212,45 +273,62 @@ "lightbox.close": "അടയ്ക്കുക", "lightbox.next": "അടുത്തത്", "lightbox.previous": "പുറകോട്ട്", + "limited_account_hint.action": "എന്നാലും രൂപരേഖ കാണിക്കുക", + "link_preview.author": "{name}-നിന്നു്", "lists.account.add": "പട്ടികയിലേക്ക് ചേർക്കുക", "lists.account.remove": "പട്ടികയിൽ നിന്ന് ഒഴിവാക്കുക", "lists.delete": "പട്ടിക ഒഴിവാക്കുക", "lists.edit": "പട്ടിക തിരുത്തുക", "lists.edit.submit": "തലക്കെട്ട് മാറ്റുക", + "lists.exclusive": "ഈ എഴുത്തുകൾ ആമുഖം നിന്നു് മറയ്ക്കുക", "lists.new.create": "പുതിയ പട്ടിക ചേർക്കുക", + "lists.new.title_placeholder": "പുതിയ പട്ടിക തലക്കെട്ടു്", "lists.replies_policy.none": "ആരുമില്ല", "lists.replies_policy.title": "ഇതിനുള്ള മറുപടികൾ കാണിക്കുക:", "lists.subheading": "എന്റെ പട്ടികകൾ", + "media_gallery.hide": "മറയ്ക്കുക", "navigation_bar.blocks": "തടയപ്പെട്ട ഉപയോക്താക്കൾ", "navigation_bar.bookmarks": "ബുക്ക്മാർക്കുകൾ", "navigation_bar.community_timeline": "പ്രാദേശിക സമയരേഖ", "navigation_bar.compose": "പുതിയ ടൂട്ട് എഴുതുക", "navigation_bar.discover": "കണ്ടെത്തുക", "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.explore": "ആരായുക", + "navigation_bar.favourites": "പ്രിയപ്പെട്ടതു്", "navigation_bar.follow_requests": "പിന്തുടരാനുള്ള അഭ്യർത്ഥനകൾ", "navigation_bar.lists": "ലിസ്റ്റുകൾ", "navigation_bar.logout": "ലോഗൗട്ട്", "navigation_bar.mutes": "നിശബ്ദമാക്കപ്പെട്ട ഉപയോക്താക്കൾ", + "navigation_bar.personal": "സ്വകാര്യ", "navigation_bar.pins": "Pinned toots", "navigation_bar.preferences": "ക്രമീകരണങ്ങൾ", + "navigation_bar.search": "തിരയുക", "navigation_bar.security": "സുരക്ഷ", "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", "notification.follow": "{name} നിങ്ങളെ പിന്തുടർന്നു", "notification.follow_request": "{name} നിങ്ങളെ പിന്തുടരാൻ അഭ്യർത്ഥിച്ചു", + "notification.label.reply": "മറുപടി", + "notification.moderation-warning.learn_more": "ഇനീം അറിയുക", + "notification.moderation_warning.action_silence": "താങ്ങളുടെ ഇടപാടു് പരിധിപെട്ടിരിക്കുന്നു.", "notification.own_poll": "നിങ്ങളുടെ പോൾ അവസാനിച്ചു", "notification.reblog": "{name} നിങ്ങളുടെ പോസ്റ്റ് ബൂസ്റ്റ് ചെയ്തു", "notification.status": "{name} ഇപ്പോൾ പോസ്റ്റുചെയ്‌തു", + "notification_requests.accept": "സ്വീകരിക്കുക", + "notification_requests.edit_selection": "പരിഷ്കരിക്കുക", "notifications.clear": "അറിയിപ്പ് മായ്ക്കുക", "notifications.clear_confirmation": "നിങ്ങളുടെ എല്ലാ അറിയിപ്പുകളും ശാശ്വതമായി മായ്‌ക്കണമെന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ?", "notifications.column_settings.alert": "ഡെസ്ക്ടോപ്പ് അറിയിപ്പുകൾ", "notifications.column_settings.follow": "പുതിയ പിന്തുടരുന്നവർ:", "notifications.column_settings.follow_request": "പുതിയ പിന്തുടരൽ അഭ്യർത്ഥനകൾ:", + "notifications.column_settings.group": "കൂട്ടം", "notifications.column_settings.mention": "സൂചനകൾ:", "notifications.column_settings.poll": "പോൾ ഫലങ്ങൾ:", "notifications.column_settings.push": "പുഷ് അറിയിപ്പുകൾ", "notifications.column_settings.reblog": "ബൂസ്റ്റുകൾ:", + "notifications.column_settings.show": "എഴുത്തുപംക്തിയിൽ കാണിക്കുക", "notifications.column_settings.sound": "ശബ്ദം പ്ലേ ചെയ്യുക", "notifications.column_settings.status": "പുതിയ ടൂട്ടുകൾ:", + "notifications.column_settings.update": "പരിഷ്കരണങ്ങൾ:", "notifications.filter.all": "എല്ലാം", "notifications.filter.boosts": "ബൂസ്റ്റുകൾ", "notifications.filter.follows": "പിന്തുടരുന്നു", @@ -260,15 +338,19 @@ "notifications.grant_permission": "അനുമതി നൽകുക.", "notifications.group": "{count} അറിയിപ്പുകൾ", "notifications.mark_as_read": "എല്ലാ അറിയിപ്പുകളും വായിച്ചതായി അടയാളപ്പെടുത്തുക", + "notifications.policy.filter": "അരിക്കൽ", + "notifications.policy.filter_new_accounts_title": "പുതിയ ഇടപാടുകൾ", + "notifications.policy.filter_not_followers_title": "താങ്ങളെ പിന്തുടരാത്തതു് ആൾക്കാർ", "notifications_permission_banner.enable": "ഡെസ്ക്ടോപ്പ് അറിയിപ്പുകൾ പ്രാപ്തമാക്കുക", "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", - "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.actions.go_to_home": "ആമുഖത്താൾ വരെ പോവ്വുക", + "onboarding.follows.lead": "", + "onboarding.follows.title": "താങ്ങളുടെ ആമുഖത്താളിന് വ്യക്തിപരമാക്കുക", + "onboarding.share.title": "താങ്ങളുടെ രൂപരേഖ പങ്കിടുക", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.skip": "Want to skip right ahead?", "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.follow_people.title": "താങ്ങളുടെ ആമുഖത്താളിന് വ്യക്തിപരമാക്കുക", "onboarding.steps.publish_status.body": "Say hello to the world.", "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", @@ -277,22 +359,32 @@ "picture_in_picture.restore": "തിരികെ വയ്ക്കുക", "poll.closed": "അടച്ചു", "poll.refresh": "പുതുക്കുക", + "poll.reveal": "ഫലങ്ങൾ കാണുക", "poll.vote": "വോട്ട് ചെയ്യുക", "poll.voted": "ഈ ഉത്തരത്തിനായി നിങ്ങൾ വോട്ട് ചെയ്തു", "poll_button.add_poll": "ഒരു പോൾ ചേർക്കുക", "poll_button.remove_poll": "പോൾ നീക്കംചെയ്യുക", "privacy.change": "ടൂട്ട് സ്വകാര്യത ക്രമീകരിക്കുക", + "privacy.private.long": "താങ്ങളെ പിന്തുടരുന്നവർ മാത്രം", + "privacy.private.short": "പിന്തുടരുന്നവർ", "privacy.public.short": "എല്ലാവര്‍ക്കും", + "privacy_policy.title": "സ്വകാര്യത്തനയം", "refresh": "പുതുക്കുക", "regeneration_indicator.label": "ലഭ്യമാക്കുന്നു…", - "regeneration_indicator.sublabel": "നിങ്ങളുടെ ഹോം ഫീഡ് തയാറാക്കുന്നു!", + "regeneration_indicator.sublabel": "നിങ്ങളുടെ താങ്ങളുടെ ആമുഖത്താളിന് തയാറാക്കുന്നു!", "relative_time.days": "{number}ദിവസം", + "relative_time.full.just_now": "ഇപ്പോൾതന്നെ", "relative_time.hours": "{number}മണി", "relative_time.just_now": "ഇപ്പോൾ", "relative_time.today": "ഇന്ന്", "reply_indicator.cancel": "റദ്ദാക്കുക", + "report.block": "തടസ്സപെടുത്തുക", + "report.category.title_account": "രൂപരേഖ", + "report.close": "ചെയ്തു", "report.forward_hint": "ഈ അക്കൗണ്ട് മറ്റൊരു സെർവറിൽ നിന്നാണ്. റിപ്പോർട്ടിന്റെ അജ്ഞാത പകർപ്പ് അവിടെ അയയ്ക്കണോ?", + "report.next": "അടുത്തതു്", "report.placeholder": "കൂടുതൽ അഭിപ്രായങ്ങൾ", + "report.reasons.spam": "ഇതു് പാഴടക്കമാണു്", "report.submit": "സമർപ്പിക്കുക", "report.target": "Report {target}", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", @@ -327,7 +419,7 @@ "status.share": "പങ്കിടുക", "status.show_more_all": "എല്ലാവർക്കുമായി കൂടുതൽ കാണിക്കുക", "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", - "tabs_bar.home": "ഹോം", + "tabs_bar.home": "ആമുഖം", "tabs_bar.notifications": "അറിയിപ്പുകൾ", "time_remaining.days": "{number, plural, one {# ദിവസം} other {# ദിവസങ്ങൾ}} ബാക്കി", "time_remaining.hours": "{number, plural, one {# മണിക്കൂർ} other {# മണിക്കൂർ}} ശേഷിക്കുന്നു", @@ -351,7 +443,7 @@ "upload_modal.preview_label": "പൂര്‍വ്വദൃശ്യം({ratio})", "upload_progress.label": "Uploading…", "video.close": "വീഡിയോ അടയ്ക്കുക", - "video.download": "ഫയൽ ഡൌൺലോഡ് ചെയ്യുക", + "video.download": "ഫയൽ ഇറക്കുവയ്ക്കുക", "video.exit_fullscreen": "പൂർണ്ണ സ്ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക", "video.expand": "വീഡിയോ വികസപ്പിക്കൂ", "video.fullscreen": "പൂർണ്ണ സ്ക്രീൻ", 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..9dea73139798cf 100644 --- a/app/javascript/mastodon/locales/ms.json +++ b/app/javascript/mastodon/locales/ms.json @@ -36,6 +36,7 @@ "account.followers.empty": "Belum ada yang mengikuti pengguna ini.", "account.followers_counter": "{count, plural, one {{counter} Diikuti} other {{counter} Diikuti}}", "account.following": "Mengikuti", + "account.following_counter": "{count, plural, other {{counter} following}}", "account.follows.empty": "Pengguna ini belum mengikuti sesiapa.", "account.go_to_profile": "Pergi ke profil", "account.hide_reblogs": "Sembunyikan galakan daripada @{name}", @@ -61,6 +62,7 @@ "account.requested_follow": "{name} has requested to follow you", "account.share": "Kongsi profil @{name}", "account.show_reblogs": "Tunjukkan galakan daripada @{name}", + "account.statuses_counter": "{count, plural, other {{counter} siaran}}", "account.unblock": "Nyahsekat @{name}", "account.unblock_domain": "Nyahsekat domain {domain}", "account.unblock_short": "Nyahsekat", @@ -145,7 +147,6 @@ "compose_form.poll.duration": "Tempoh undian", "compose_form.poll.multiple": "Pelbagai pilihan", "compose_form.poll.option_placeholder": "Pilihan {number}", - "compose_form.poll.single": "Pilih satu", "compose_form.poll.switch_to_multiple": "Ubah kepada membenarkan aneka undian", "compose_form.poll.switch_to_single": "Ubah kepada undian pilihan tunggal", "compose_form.poll.type": "Gaya", @@ -360,8 +361,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..8df1fc4d1f6f68 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}", @@ -457,7 +459,7 @@ "lists.subheading": "Jouw lijsten", "load_pending": "{count, plural, one {# nieuw item} other {# nieuwe items}}", "loading_indicator.label": "Laden…", - "media_gallery.hide": "Verbergen", + "media_gallery.hide": "Verberg", "moved_to_account_banner.text": "Omdat je naar {movedToAccount} bent verhuisd is jouw account {disabledAccount} momenteel uitgeschakeld.", "mute_modal.hide_from_notifications": "Onder meldingen verbergen", "mute_modal.hide_options": "Opties verbergen", @@ -502,22 +504,23 @@ "notification.admin.report_statuses": "{name} rapporteerde {target} voor {category}", "notification.admin.report_statuses_other": "{name} rapporteerde {target}", "notification.admin.sign_up": "{name} heeft zich geregistreerd", - "notification.admin.sign_up.name_and_others": "{name} en {count, plural, one {# ander} other {# anderen}} hebben zich geregistreerd", + "notification.admin.sign_up.name_and_others": "{name} en {count, plural, one {# ander persoon} other {# andere personen}} hebben zich geregistreerd", "notification.favourite": "{name} markeerde jouw bericht als favoriet", - "notification.favourite.name_and_others_with_link": "{name} en {count, plural, one {# ander} other {# anderen}} hebben jouw bericht als favoriet gemarkeerd", + "notification.favourite.name_and_others_with_link": "{name} en {count, plural, one {# ander persoon} other {# andere personen}} hebben jouw bericht als favoriet gemarkeerd", "notification.follow": "{name} volgt jou nu", - "notification.follow.name_and_others": "{name} en {count, plural, one {# ander} other {# anderen}} hebben je gevolgd", + "notification.follow.name_and_others": "{name} en {count, plural, one {# ander persoon} other {# andere personen}} volgen jou nou", "notification.follow_request": "{name} wil jou graag volgen", - "notification.follow_request.name_and_others": "{name} en {count, plural, one {# ander} other {# anderen}} hebben gevraagd om je te volgen", + "notification.follow_request.name_and_others": "{name} en {count, plural, one {# ander persoon} other {# andere personen}} hebben gevraagd om je te volgen", "notification.label.mention": "Vermelding", "notification.label.private_mention": "Privébericht", "notification.label.private_reply": "Privéreactie", "notification.label.reply": "Reactie", "notification.mention": "Vermelding", + "notification.mentioned_you": "Je bent vermeld door {name}", "notification.moderation-warning.learn_more": "Meer informatie", "notification.moderation_warning": "Je hebt een moderatie-waarschuwing ontvangen", "notification.moderation_warning.action_delete_statuses": "Sommige van je berichten zijn verwijderd.", - "notification.moderation_warning.action_disable": "Je account is uitgeschakeld.", + "notification.moderation_warning.action_disable": "Jouw account is uitgeschakeld.", "notification.moderation_warning.action_mark_statuses_as_sensitive": "Sommige van je berichten zijn gemarkeerd als gevoelig.", "notification.moderation_warning.action_none": "Jouw account heeft een moderatie-waarschuwing ontvangen.", "notification.moderation_warning.action_sensitive": "Je berichten worden vanaf nu als gevoelig gemarkeerd.", @@ -526,14 +529,14 @@ "notification.own_poll": "Jouw peiling is beëindigd", "notification.poll": "Een peiling waaraan jij hebt meegedaan is beëindigd", "notification.reblog": "{name} boostte jouw bericht", - "notification.reblog.name_and_others_with_link": "{name} en {count, plural, one {# ander} other {# anderen}} hebben jouw bericht geboost", + "notification.reblog.name_and_others_with_link": "{name} en {count, plural, one {# ander persoon} other {# andere personen}} hebben jouw bericht geboost", "notification.relationships_severance_event": "Verloren verbindingen met {name}", "notification.relationships_severance_event.account_suspension": "Een beheerder van {from} heeft {target} geschorst, wat betekent dat je geen updates meer van hen kunt ontvangen of met hen kunt communiceren.", - "notification.relationships_severance_event.domain_block": "Een beheerder van {from} heeft {target} geblokkeerd, inclusief {followersCount} van jouw volgers en {followingCount, plural, one {# account} other {# accounts}} die jij volgt.", + "notification.relationships_severance_event.domain_block": "Een beheerder van {from} heeft {target} geblokkeerd, inclusief {followersCount} van jouw volgers en {followingCount, plural, one {# account} other {# accounts}} die je volgt.", "notification.relationships_severance_event.learn_more": "Meer informatie", - "notification.relationships_severance_event.user_domain_block": "Je hebt {target} geblokkeerd, waarmee je {followersCount} van je volgers en {followingCount, plural, one {# account} other {# accounts}} die jij volgt, bent verloren.", + "notification.relationships_severance_event.user_domain_block": "Je hebt {target} geblokkeerd, waarmee je {followersCount} van je volgers en {followingCount, plural, one {# account} other {# accounts}} die je volgt, bent verloren.", "notification.status": "{name} heeft zojuist een bericht geplaatst", - "notification.update": "{name} heeft een bericht bewerkt", + "notification.update": "{name} bewerkte een bericht", "notification_requests.accept": "Accepteren", "notification_requests.accept_multiple": "{count, plural, one {# verzoek accepteren…} other {# verzoeken accepteren…}}", "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Verzoek accepteren} other {Verzoeken accepteren}}", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Snelle filterbalk", "notifications.column_settings.follow": "Nieuwe volgers:", "notifications.column_settings.follow_request": "Nieuw volgverzoek:", + "notifications.column_settings.group": "Groeperen", "notifications.column_settings.mention": "Vermeldingen:", "notifications.column_settings.poll": "Peilingresultaten:", "notifications.column_settings.push": "Pushmeldingen", @@ -778,7 +782,7 @@ "status.bookmark": "Bladwijzer toevoegen", "status.cancel_reblog_private": "Niet langer boosten", "status.cannot_reblog": "Dit bericht kan niet geboost worden", - "status.continued_thread": "Vervolgt het gesprek", + "status.continued_thread": "Vervolg van gesprek", "status.copy": "Link naar bericht kopiëren", "status.delete": "Verwijderen", "status.detailed_status": "Uitgebreide gespreksweergave", @@ -850,6 +854,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..e2a6ac9c26fe0e 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Varigheit for rundspørjing", "compose_form.poll.multiple": "Fleirval", "compose_form.poll.option_placeholder": "Alternativ {number}", - "compose_form.poll.single": "Vel ein", + "compose_form.poll.single": "Eitt val", "compose_form.poll.switch_to_multiple": "Endre rundspørjinga til å tillate fleire val", "compose_form.poll.switch_to_single": "Endre rundspørjinga til å tillate berre eitt val", "compose_form.poll.type": "Stil", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} markerte innlegget ditt som favoritt", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# annan} other {# andre}} favorittmerka innlegget ditt", "notification.follow": "{name} fylgde deg", - "notification.follow.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} fylgde deg", + "notification.follow.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} fylgde deg", "notification.follow_request": "{name} har bedt om å fylgja deg", "notification.follow_request.name_and_others": "{name} og {count, plural, one {# annan} other {# andre}} har spurt om å fylgja deg", "notification.label.mention": "Omtale", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Privat svar", "notification.label.reply": "Svar", "notification.mention": "Omtale", + "notification.mentioned_you": "{name} nemnde deg", "notification.moderation-warning.learn_more": "Lær meir", "notification.moderation_warning": "Du har mottatt ei moderasjonsåtvaring", "notification.moderation_warning.action_delete_statuses": "Nokre av innlegga dine har blitt fjerna.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Snøggfilterline", "notifications.column_settings.follow": "Nye fylgjarar:", "notifications.column_settings.follow_request": "Ny fylgjarførespurnader:", + "notifications.column_settings.group": "Gruppe", "notifications.column_settings.mention": "Omtaler:", "notifications.column_settings.poll": "Røysteresultat:", "notifications.column_settings.push": "Pushvarsel", @@ -850,6 +854,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..b709fbea5e21a6 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -157,7 +157,6 @@ "compose_form.poll.duration": "Avstemningens varighet", "compose_form.poll.multiple": "Flervalg", "compose_form.poll.option_placeholder": "Valg {number}", - "compose_form.poll.single": "Velg en", "compose_form.poll.switch_to_multiple": "Endre avstemning til å tillate flere valg", "compose_form.poll.switch_to_single": "Endre avstemning til å tillate ett valg", "compose_form.poll.type": "Stil", @@ -221,7 +220,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 +430,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", @@ -505,6 +501,8 @@ "notification.reblog": "{name} fremhevet ditt innlegg", "notification.status": "{name} la nettopp ut", "notification.update": "{name} redigerte et innlegg", + "notification_requests.minimize_banner": "Minimer banneret for filtrerte varsler", + "notification_requests.view": "Vis varsler", "notifications.clear": "Fjern varsler", "notifications.clear_confirmation": "Er du sikker på at du vil fjerne alle dine varsler permanent?", "notifications.column_settings.admin.report": "Nye rapporter:", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 22193f82aa41e5..37687bc8444c9c 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -8,6 +8,7 @@ "about.not_available": "Aquesta informacion foguèt pas renduda disponibla sus aqueste servidor.", "about.powered_by": "Malhum social descentralizat propulsat per {mastodon}", "about.rules": "Règlas del servidor", + "account.account_note_header": "Nòta personala", "account.add_or_remove_from_list": "Ajustar o tirar de las listas", "account.badges.bot": "Robòt", "account.badges.group": "Grop", @@ -72,9 +73,12 @@ "alert.rate_limited.title": "Taus limitat", "alert.unexpected.message": "Una error s’es producha.", "alert.unexpected.title": "Ops !", + "alt_text_badge.title": "Tèxt alternatiu", "announcement.announcement": "Anóncia", "attachments_list.unprocessed": "(pas tractat)", "audio.hide": "Amagar àudio", + "block_modal.show_less": "Ne veire mens", + "block_modal.show_more": "Ne veire mai", "boost_modal.combo": "Podètz botar {combo} per passar aquò lo còp que ven", "bundle_column_error.copy_stacktrace": "Copiar senhalament d’avaria", "bundle_column_error.error.title": "Oh non !", @@ -128,9 +132,14 @@ "compose_form.poll.duration": "Durada del sondatge", "compose_form.poll.switch_to_multiple": "Cambiar lo sondatge per permetre de causidas multiplas", "compose_form.poll.switch_to_single": "Cambiar lo sondatge per permetre una sola causida", + "compose_form.poll.type": "Estil", + "compose_form.publish": "Publicar", "compose_form.publish_form": "Publicar", + "compose_form.reply": "Respondre", + "compose_form.save_changes": "Actualizar", "compose_form.spoiler.marked": "Lo tèxte es rescondut jos l’avertiment", "compose_form.spoiler.unmarked": "Lo tèxte es pas rescondut", + "compose_form.spoiler_placeholder": "Avertiment de contengut (opcional)", "confirmation_modal.cancel": "Anullar", "confirmations.block.confirm": "Blocar", "confirmations.delete.confirm": "Escafar", @@ -297,8 +306,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..21a1c365f02002 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Czas trwania głosowania", "compose_form.poll.multiple": "Wielokrotny wybór", "compose_form.poll.option_placeholder": "Opcja {number}", - "compose_form.poll.single": "Wybierz jedną", + "compose_form.poll.single": "Jednokrotny wybór", "compose_form.poll.switch_to_multiple": "Pozwól na wybranie wielu opcji", "compose_form.poll.switch_to_single": "Pozwól na wybranie tylko jednej opcji", "compose_form.poll.type": "Styl", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} dodaje Twój wpis do ulubionych", "notification.favourite.name_and_others_with_link": "{name} i {count, plural, one {# inna osoba polubiła twój wpis} few {# inne osoby polubiły twój wpis} other {# innych osób polubiło twój wpis}}", "notification.follow": "{name} obserwuje Cię", - "notification.follow.name_and_others": "{name} i {count, plural, one {# inna osoba cię zaobserwowała} few {# inne osoby cię zaobserwowały} other {# innych osób cię zaobserwowało}}", + "notification.follow.name_and_others": "{name} i {count, plural, one {# inna osoba cię zaobserwowała} few {# inne osoby cię zaobserwowały} other {# innych osób cię zaobserwowało}}", "notification.follow_request": "{name} chce cię zaobserwować", "notification.follow_request.name_and_others": "{name} i {count, plural, one {# inna osoba chce} few {# inne osoby chcą} other {# innych osób chce}} zaobserwować twój profil", "notification.label.mention": "Wzmianka", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Odpowiedź prywatna", "notification.label.reply": "Odpowiedź", "notification.mention": "Wzmianka", + "notification.mentioned_you": "{name} wspomniał(a) o Tobie", "notification.moderation-warning.learn_more": "Dowiedz się więcej", "notification.moderation_warning": "Otrzymałeś/-łaś ostrzeżenie moderacyjne", "notification.moderation_warning.action_delete_statuses": "Niektóre twoje wpisy zostały usunięte.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Szybkie filtrowanie", "notifications.column_settings.follow": "Nowi obserwujący:", "notifications.column_settings.follow_request": "Nowe prośby o możliwość obserwacji:", + "notifications.column_settings.group": "Grupuj", "notifications.column_settings.mention": "Wspomnienia:", "notifications.column_settings.poll": "Wyniki głosowania:", "notifications.column_settings.push": "Powiadomienia push", @@ -850,6 +854,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..f5b6481a837e36 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Duração da enquete", "compose_form.poll.multiple": "Múltipla escolha", "compose_form.poll.option_placeholder": "Opção {number}", - "compose_form.poll.single": "Escolha uma", + "compose_form.poll.single": "Única escolha", "compose_form.poll.switch_to_multiple": "Permitir múltiplas escolhas", "compose_form.poll.switch_to_single": "Opção única", "compose_form.poll.type": "Estilo", @@ -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,10 @@ "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", + "lightbox.zoom_out": "Zoom para ajustar", "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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} favoritou sua publicação", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# outro} other {# others}} favoritaram a publicação", "notification.follow": "{name} te seguiu", - "notification.follow.name_and_others": "{name} e {count, plural, one {# other} other {# outros}} seguiu você", + "notification.follow.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} seguiram você", "notification.follow_request": "{name} quer te seguir", "notification.follow_request.name_and_others": "{name} e {count, plural, one {# other} other {# outros}} pediu para seguir você", "notification.label.mention": "Menção", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Resposta privada", "notification.label.reply": "Resposta", "notification.mention": "Menção", + "notification.mentioned_you": "{name} te mencionou", "notification.moderation-warning.learn_more": "Aprender mais", "notification.moderation_warning": "Você recebeu um aviso de moderação", "notification.moderation_warning.action_delete_statuses": "Algumas das suas publicações foram removidas.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Barra de filtro rápido", "notifications.column_settings.follow": "Seguidores:", "notifications.column_settings.follow_request": "Seguidores pendentes:", + "notifications.column_settings.group": "Grupo", "notifications.column_settings.mention": "Menções:", "notifications.column_settings.poll": "Enquetes:", "notifications.column_settings.push": "Notificações push", @@ -812,7 +816,7 @@ "status.reblogs.empty": "Nada aqui. Quando alguém der boost, o usuário aparecerá aqui.", "status.redraft": "Excluir e rascunhar", "status.remove_bookmark": "Remover do Salvos", - "status.replied_in_thread": "Respondido na discussão", + "status.replied_in_thread": "Respondido na conversa", "status.replied_to": "Em resposta a {name}", "status.reply": "Responder", "status.replyAll": "Responder a conversa", @@ -850,6 +854,11 @@ "upload_error.poll": "Mídias não podem ser anexadas em toots com enquetes.", "upload_form.audio_description": "Descrever para deficientes auditivos", "upload_form.description": "Descrever para deficientes visuais", + "upload_form.drag_and_drop.instructions": "Para pegar um anexo de mídia, pressione espaço ou enter. Enquanto arrastar, use as setas do teclado para mover o anexo de mídia em qualquer direção. Pressione espaço ou insira novamente para soltar o anexo de mídia em sua nova posição, ou pressione escape para cancelar.", + "upload_form.drag_and_drop.on_drag_cancel": "O arrastamento foi cancelado. O anexo da mídia {item} foi descartado.", + "upload_form.drag_and_drop.on_drag_end": "O anexo {item} foi removido.", + "upload_form.drag_and_drop.on_drag_over": "O anexo de mídia {item} foi movido.", + "upload_form.drag_and_drop.on_drag_start": "Foi coletado o anexo de mídia {item}.", "upload_form.edit": "Editar", "upload_form.thumbnail": "Alterar miniatura", "upload_form.video_description": "Descrever para deficientes auditivos ou visuais", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index ed4bb9ba010a6d..fe18444ce10dc4 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -157,7 +157,6 @@ "compose_form.poll.duration": "Duração da sondagem", "compose_form.poll.multiple": "Escolha múltipla", "compose_form.poll.option_placeholder": "Opção {number}", - "compose_form.poll.single": "Escolha uma", "compose_form.poll.switch_to_multiple": "Alterar a sondagem para permitir várias respostas", "compose_form.poll.switch_to_single": "Alterar a sondagem para permitir uma única resposta", "compose_form.poll.type": "Estilo", @@ -221,7 +220,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 +430,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", @@ -506,7 +502,6 @@ "notification.favourite": "{name} assinalou a sua publicação como favorita", "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {# outro} other {# outros}} assinalou a sua publicação como favorita", "notification.follow": "{name} começou a seguir-te", - "notification.follow.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} começaram a segui-lo", "notification.follow_request": "{name} pediu para segui-lo", "notification.follow_request.name_and_others": "{name} e {count, plural, one {# outro} other {# outros}} pediram para segui-lo", "notification.label.mention": "Menção", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index 73b8140de65845..96f9eac2b3ccd7 100644 --- a/app/javascript/mastodon/locales/ro.json +++ b/app/javascript/mastodon/locales/ro.json @@ -138,7 +138,6 @@ "compose_form.poll.duration": "Durata sondajului", "compose_form.poll.multiple": "Alegeri multiple", "compose_form.poll.option_placeholder": "Opțiune {number}", - "compose_form.poll.single": "Alegeți unul", "compose_form.poll.switch_to_multiple": "Modifică sondajul pentru a permite mai multe opțiuni", "compose_form.poll.switch_to_single": "Modifică sondajul pentru a permite o singură opțiune", "compose_form.poll.type": "Stil", @@ -334,8 +333,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..46463be76f5f4b 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -34,7 +34,7 @@ "account.follow_back": "Подписаться в ответ", "account.followers": "Подписчики", "account.followers.empty": "На этого пользователя пока никто не подписан.", - "account.followers_counter": "{count, plural, one {{counter} последователя} other {{counter} последователей}}", + "account.followers_counter": "{count, plural, one {{counter} подписчик} few {{counter} подписчика} other {{counter} подписчиков}}", "account.following": "Подписки", "account.following_counter": "{count, plural, one {{counter} последующий} other {{counter} последующие}}", "account.follows.empty": "Этот пользователь пока ни на кого не подписался.", @@ -62,6 +62,7 @@ "account.requested_follow": "{name} отправил(а) вам запрос на подписку", "account.share": "Поделиться профилем @{name}", "account.show_reblogs": "Показывать продвижения от @{name}", + "account.statuses_counter": "{count, plural, one {# пост} few {# поста} many {# постов} other {# постов}}", "account.unblock": "Разблокировать @{name}", "account.unblock_domain": "Разблокировать {domain}", "account.unblock_short": "Разблокировать", @@ -77,13 +78,14 @@ "admin.dashboard.retention.cohort": "Месяц регистрации", "admin.dashboard.retention.cohort_size": "Новые пользователи", "admin.impact_report.instance_accounts": "Профили учетных записей, которые будут удалены", - "admin.impact_report.instance_followers": "Последователи, которых потеряют наши пользователи", - "admin.impact_report.instance_follows": "Последователи, которых потеряют наши пользователи", + "admin.impact_report.instance_followers": "Подписчики, которых потеряют наши пользователи", + "admin.impact_report.instance_follows": "Подписчики, которых потеряют их пользователи", "admin.impact_report.title": "Резюме воздействия", "alert.rate_limited.message": "Пожалуйста, повторите после {retry_time, time, medium}.", "alert.rate_limited.title": "Ограничение количества запросов", "alert.unexpected.message": "Произошла непредвиденная ошибка.", "alert.unexpected.title": "Упс!", + "alt_text_badge.title": "Альтернативный текст", "announcement.announcement": "Объявление", "attachments_list.unprocessed": "(не обработан)", "audio.hide": "Скрыть аудио", @@ -156,7 +158,6 @@ "compose_form.poll.duration": "Продолжительность опроса", "compose_form.poll.multiple": "Несколько вариантов ответа", "compose_form.poll.option_placeholder": "Вариант {number}", - "compose_form.poll.single": "Выберите один", "compose_form.poll.switch_to_multiple": "Разрешить выбор нескольких вариантов", "compose_form.poll.switch_to_single": "Переключить в режим выбора одного ответа", "compose_form.poll.type": "Стиль", @@ -220,7 +221,7 @@ "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": "Это позволяет вам общаться и взаимодействовать с людьми не только на Mastodon, но и в различных социальных приложениях.", "domain_pill.activitypub_like_language": "ActivityPub как язык Mastodon говорит с другими социальными сетями.", @@ -352,7 +353,7 @@ "hashtag.follow": "Подписаться на новые посты", "hashtag.unfollow": "Отписаться", "hashtags.and_other": "...и {count, plural, other {# ещё}}", - "hints.profiles.followers_may_be_missing": "Последователи для этого профиля могут отсутствовать.", + "hints.profiles.followers_may_be_missing": "Подписчики у этого профиля могут отсутствовать.", "hints.profiles.follows_may_be_missing": "Фолловеры для этого профиля могут отсутствовать.", "hints.profiles.posts_may_be_missing": "Некоторые сообщения из этого профиля могут отсутствовать.", "hints.profiles.see_more_followers": "Посмотреть больше подписчиков на {domain}", @@ -431,10 +432,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}", @@ -506,12 +507,13 @@ "notification.favourite.name_and_others_with_link": "{name} и {count, plural, one {# другие} other {# другие}} отдали предпочтение вашему посту", "notification.follow": "{name} подписался (-лась) на вас", "notification.follow_request": "{name} отправил запрос на подписку", - "notification.follow_request.name_and_others": "{name} и {count, plural, one {# другие} other {# другие}} последовали за тобой", + "notification.follow_request.name_and_others": "{name} и ещё {count, plural, one {#} other {# других}} подписались на вас", "notification.label.mention": "Упоминание", "notification.label.private_mention": "Частное упоминание", "notification.label.private_reply": "Частный ответ", "notification.label.reply": "Ответить", "notification.mention": "Упоминание", + "notification.mentioned_you": "{name} упомянул(а) вас", "notification.moderation-warning.learn_more": "Узнать больше", "notification.moderation_warning": "Вы получили предупреждение от модерации", "notification.moderation_warning.action_delete_statuses": "Некоторые из ваших публикаций были удалены.", @@ -635,7 +637,7 @@ "onboarding.steps.share_profile.title": "Поделитесь вашим профилем", "onboarding.tips.2fa": "Знаете ли вы? Вы можете защитить свой аккаунт, настроив двухфакторную аутентификацию в настройках аккаунта. Она работает с любым приложением TOTP по вашему выбору, номер телефона не требуется!", "onboarding.tips.accounts_from_other_servers": "Знали ли вы? Поскольку Mastodon децентрализован, некоторые профили, с которыми вы столкнетесь, будут размещены на серверах, отличных от вашего. И все же вы можете взаимодействовать с ними без проблем! Их сервер находится во второй половине имени пользователя!", - "onboarding.tips.migration": "Знаете ли вы? Если вы чувствуете, что {domain} не подходит вам в качестве сервера в будущем, вы можете переехать на другой сервер Mastodon без потери своих последователей. Вы даже можете разместить свой собственный сервер!", + "onboarding.tips.migration": "Знаете ли вы? Если вы чувствуете, что {domain} не подходит вам в качестве сервера в будущем, вы можете переехать на другой сервер Mastodon без потери своих подписчиков. Вы даже можете разместить свой собственный сервер!", "onboarding.tips.verification": "Знали ли вы? Вы можете подтвердить свою учетную запись, разместив ссылку на свой профиль Mastodon на собственном сайте и добавив сайт в свой профиль. Никаких сборов или документов не требуется!", "password_confirmation.exceeds_maxlength": "Срок подтверждения пароля превышает максимальную длину пароля", "password_confirmation.mismatching": "Введенные пароли не совпадают.", @@ -728,6 +730,7 @@ "report_notification.categories.spam": "Спам", "report_notification.categories.spam_sentence": "спам", "report_notification.categories.violation": "Нарушение правил", + "report_notification.categories.violation_sentence": "нарушение правила", "report_notification.open": "Открыть жалобу", "search.no_recent_searches": "Недавние запросы отсутствуют", "search.placeholder": "Поиск", @@ -757,7 +760,7 @@ "server_banner.administered_by": "Управляется:", "server_banner.is_one_of_many": "{domain} - это один из многих независимых серверов Mastodon, которые вы можете использовать для участия в fediverse.", "server_banner.server_stats": "Статистика сервера:", - "sign_in_banner.create_account": "Создать учётную запись", + "sign_in_banner.create_account": "Зарегистрироваться", "sign_in_banner.follow_anyone": "Следите за любым человеком в федеральной вселенной и смотрите все в хронологическом порядке. Никаких алгоритмов, рекламы или клик бейта.", "sign_in_banner.mastodon_is": "Mastodon - лучший способ быть в курсе всего происходящего.", "sign_in_banner.sign_in": "Войти", @@ -839,6 +842,10 @@ "upload_error.poll": "К опросам нельзя прикреплять файлы.", "upload_form.audio_description": "Опишите аудиофайл для людей с нарушением слуха", "upload_form.description": "Добавьте описание для людей с нарушениями зрения:", + "upload_form.drag_and_drop.instructions": "Чтобы подобрать прикрепленный файл, нажмите \"Пробел\" (Space) или \"Ввод\" (Enter). При перетаскивании используйте клавиши со стрелками, чтобы переместить прикрепленные файлы в любом направлении. Нажмите \"Пробел\" (Space) или \"Ввод\" (Enter) еще раз, чтобы переместить вложение в новое место, или нажмите кнопку \"Выйти\" (Escape), чтобы отменить.", + "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.edit": "Изменить", "upload_form.thumbnail": "Изменить обложку", "upload_form.video_description": "Опишите видео для людей с нарушением слуха или зрения", diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json index 02d1c005cfb078..b55d5e7a7d9974 100644 --- a/app/javascript/mastodon/locales/ry.json +++ b/app/javascript/mastodon/locales/ry.json @@ -140,7 +140,6 @@ "compose_form.poll.duration": "Трывалость убзвідованя", "compose_form.poll.multiple": "Дакулько варіантув", "compose_form.poll.option_placeholder": "Варіант {number}", - "compose_form.poll.single": "Уберіт єден", "compose_form.poll.switch_to_multiple": "Змінити убзвідованя обы поволити дакулько варіантув", "compose_form.poll.switch_to_single": "Змінити убзвідованя обы поволити лишек єден варіант", "compose_form.poll.type": "Стіл", 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..71bcaef7abe9e9 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Màssimu de rechestas barigadu", "alert.unexpected.message": "Ddoe est istada una faddina.", "alert.unexpected.title": "Oh!", + "alt_text_badge.title": "Testu alternativu", "announcement.announcement": "Annùntziu", "attachments_list.unprocessed": "(non protzessadu)", "audio.hide": "Cua s'àudio", @@ -97,6 +98,8 @@ "block_modal.title": "Boles blocare s'utente?", "block_modal.you_wont_see_mentions": "No as a bìdere is publicatziones chi mèntovent custa persone.", "boost_modal.combo": "Podes incarcare {combo} pro brincare custu sa borta chi benit", + "boost_modal.reblog": "Boles potentziare sa publicatzione?", + "boost_modal.undo_reblog": "Boles tzessare de potentziare sa publicatzione?", "bundle_column_error.copy_stacktrace": "Còpia s'informe de faddina", "bundle_column_error.error.body": "Sa pàgina pedida non faghiat a dda renderizare. Diat pòdere èssere pro neghe de una faddina in su còdighe nostru, o de unu problema de cumpatibilidade de su navigadore.", "bundle_column_error.error.title": "Oh, no!", @@ -104,11 +107,15 @@ "bundle_column_error.network.title": "Faddina de connessione", "bundle_column_error.retry": "Torra·bi a proare", "bundle_column_error.return": "Torra a sa pàgina printzipale", + "bundle_column_error.routing.body": "Impossìbile agatare sa pàgina rechesta. Seguru chi s'URL in sa barra de indiritzos est curretu?", "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "Serra", "bundle_modal_error.message": "Faddina in su carrigamentu de custu cumponente.", "bundle_modal_error.retry": "Torra·bi a proare", + "closed_registrations.other_server_instructions": "Dae chi Mastodon est detzentralizadu, podes creare unu contu in un'àteru serbidore e interagire cun custu.", + "closed_registrations_modal.description": "Sa creatzione de contos in {domain} no est possìbile in custu momentu, però tene in cunsideru chi non tenes bisòngiu de unu contu ispetzìficu in {domain} pro impreare Mastodon.", "closed_registrations_modal.find_another_server": "Agata un'àteru serbidore", + "closed_registrations_modal.title": "Su registru a Mastodon", "column.about": "Informatziones", "column.blocks": "Persones blocadas", "column.bookmarks": "Sinnalibros", @@ -142,6 +149,7 @@ "compose.published.open": "Aberi", "compose.saved.body": "Publicatzione sarvada.", "compose_form.direct_message_warning_learn_more": "Àteras informatziones", + "compose_form.encryption_warning": "Is publicatziones a Mastodon no sunt critografados a nodu terminale. Non cumpartzas informatziones delicadas in Mastodon.", "compose_form.hashtag_warning": "Custa publicatzione no at a èssere ammustrada in peruna eticheta, dae chi no est pùblica. Isceti is publicatziones pùblicas podent èssere chircadas cun etichetas.", "compose_form.lock_disclaimer": "Su contu tuo no est {locked}. Cale si siat persone ti podet sighire pro bìdere is messàgios tuos chi imbies a sa gente chi ti sighit.", "compose_form.lock_disclaimer.lock": "blocadu", @@ -149,7 +157,6 @@ "compose_form.poll.duration": "Longària de su sondàgiu", "compose_form.poll.multiple": "Sèberu mùltiplu", "compose_form.poll.option_placeholder": "Optzione {number}", - "compose_form.poll.single": "Sèbera·nde una", "compose_form.poll.switch_to_multiple": "Muda su sondàgiu pro permìtere multi-optziones", "compose_form.poll.switch_to_single": "Muda su sondàgiu pro permìtere un'optzione isceti", "compose_form.poll.type": "Istile", @@ -171,15 +178,23 @@ "confirmations.discard_edit_media.confirm": "Iscarta", "confirmations.discard_edit_media.message": "Tenes modìficas non sarvadas a is descritziones o a is anteprimas de is cuntenutos, ddas boles iscartare su matessi?", "confirmations.edit.confirm": "Modìfica", + "confirmations.edit.message": "Modifichende immoe as a subrascrìere su messàgiu chi ses iscriende. Seguru chi boles sighire?", + "confirmations.edit.title": "Boles subraiscrìere sa publicatzione?", "confirmations.logout.confirm": "Essi·nche", "confirmations.logout.message": "Seguru chi boles essire?", + "confirmations.logout.title": "Boles serrare sa sessione?", "confirmations.mute.confirm": "A sa muda", "confirmations.redraft.confirm": "Cantzella e torra a fàghere", "confirmations.redraft.message": "Seguru chi boles cantzellare e torrare a fàghere custa publicatzione? As a pèrdere is preferidos e is cumpartziduras, e is rispostas a su messàgiu originale ant a abarrare òrfanas.", + "confirmations.redraft.title": "Boles cantzellare e torrare a iscrìere sa publicatzione?", "confirmations.reply.confirm": "Risponde", "confirmations.reply.message": "Rispondende immoe as a subrascrìere su messàgiu chi ses iscriende. Seguru chi boles sighire?", + "confirmations.reply.title": "Boles subraiscrìere sa publicatzione?", "confirmations.unfollow.confirm": "Non sigas prus", "confirmations.unfollow.message": "Seguru chi non boles sighire prus a {name}?", + "confirmations.unfollow.title": "Boles tzessare de sighire s'utente?", + "content_warning.hide": "Cua sa publicatzione", + "content_warning.show": "Ammustra·dda su pròpiu", "conversation.delete": "Cantzella arresonada", "conversation.mark_as_read": "Signala comente lèghidu", "conversation.open": "Ammustra arresonada", @@ -193,7 +208,10 @@ "directory.recently_active": "Cun atividade dae pagu", "disabled_account_banner.account_settings": "Cunfiguratziones de su contu", "disabled_account_banner.text": "Su contu tuo {disabledAccount} no est ativu.", + "dismissable_banner.community_timeline": "Custas sunt is publicatziones pùblicas prus reghentes dae gente cun contu in {domain}.", "dismissable_banner.dismiss": "Iscarta", + "dismissable_banner.explore_links": "Custas sunt is istòrias de noas prus cumpartzidas in sa rete oe. Is istòrias prus noas publicadas dae gente prus diversa ant a èssere priorizadas.", + "dismissable_banner.explore_statuses": "Custas sunt publicatziones dae sa rete detzentralizada chi sunt retzende atentzione oe. Is publicatziones prus noas cun prus cumpartziduras e preferèntzias ant a èssere priorizadas.", "domain_block_modal.block": "Bloca su serbidore", "domain_block_modal.block_account_instead": "Bloca imbetzes a @{name}", "domain_block_modal.they_can_interact_with_old_posts": "Is persones de custu serbidore podent ancora interagire cun is publicatziones betzas tuas.", @@ -207,6 +225,7 @@ "domain_pill.their_handle": "S'identificadore suo:", "domain_pill.their_server": "Sa domo digitale sua, in ue istant totu is publicatziones suas.", "domain_pill.username": "Nòmine de utente", + "domain_pill.whats_in_a_handle": "Ite est un'identificadore?", "domain_pill.your_handle": "S'identificadore tuo:", "domain_pill.your_server": "Sa domo digitale tua, in ue istant totu is publicatziones tuas. Custa non t'agradat? Tràmuda serbidore in cale si siat momentu e bati·ti fintzas in fatu is sighidores tuos.", "domain_pill.your_username": "S'identificadore ùnicu tuo in custu serbidore. Si podent agatare utentes cun su matessi nòmine de utente in àteros serbidores.", @@ -254,6 +273,7 @@ "explore.trending_links": "Noas", "explore.trending_statuses": "Publicatziones", "explore.trending_tags": "Etichetas", + "filter_modal.added.context_mismatch_title": "Su cuntestu non currispondet.", "filter_modal.added.expired_title": "Filtru iscadidu.", "filter_modal.added.review_and_configure_title": "Cunfiguratziones de filtru", "filter_modal.added.settings_link": "pàgina de cunfiguratzione", @@ -277,7 +297,13 @@ "follow_suggestions.featured_longer": "Seberadu a manu dae s'iscuadra de {domain}", "follow_suggestions.friends_of_friends_longer": "Populare intre persones chi sighis", "follow_suggestions.hints.featured": "Custu profilu est istadu seberadu a manu dae s'iscuadra {domain}.", + "follow_suggestions.personalized_suggestion": "Cussìgiu personalizadu", + "follow_suggestions.popular_suggestion": "Cussìgiu populare", + "follow_suggestions.popular_suggestion_longer": "Populare a {domain}", + "follow_suggestions.similar_to_recently_followed_longer": "Profilos sìmiles a is chi as sighidu de reghente", "follow_suggestions.view_all": "Ammustra totu", + "follow_suggestions.who_to_follow": "Chie sighire", + "followed_tags": "Etichetas sighidas", "footer.about": "Informatziones", "footer.directory": "Diretòriu de profilos", "footer.get_app": "Otene s'aplicatzione", @@ -302,6 +328,11 @@ "hashtag.counter_by_uses_today": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}} oe", "hashtag.follow": "Sighi su hashtag", "hashtag.unfollow": "Non sigas prus s'eticheta", + "hashtags.and_other": "… e {count, plural, one {un'àteru} other {àteros #}}", + "hints.profiles.posts_may_be_missing": "Podet èssere chi ammanchent tzertas publicatziones de custu profilu.", + "hints.profiles.see_more_posts": "Bide prus publicatziones a {domain}", + "hints.threads.replies_may_be_missing": "Podet èssere chi ammanchent rispostas dae àteros serbidores.", + "hints.threads.see_more": "Bide prus rispostas a {domain}", "home.column_settings.show_reblogs": "Ammustra is cumpartziduras", "home.column_settings.show_replies": "Ammustra rispostas", "home.hide_announcements": "Cua annùntzios", @@ -309,7 +340,14 @@ "home.pending_critical_update.link": "Ammustra is atualizatziones", "home.pending_critical_update.title": "Atualizatzione de seguresa crìtica a disponimentu.", "home.show_announcements": "Ammustra annùntzios", + "ignore_notifications_modal.disclaimer": "Mastodon non podet informare is utentes chi as innioradu is notìficas issoro. Inniorare notìficas no at a evitare chi s'imbient is messàgios.", + "ignore_notifications_modal.filter_instead": "Opuru filtra", + "ignore_notifications_modal.filter_to_act_users": "As a pòdere ancora atzetare, refudare o sinnalare a utentes", + "ignore_notifications_modal.filter_to_avoid_confusion": "Filtrare agiudat a evitare possìbiles confusiones", "interaction_modal.description.reply": "Podes rispòndere a custa publicatzione cun unu contu de Mastodon.", + "interaction_modal.login.action": "Torra a sa pàgina printzipale", + "interaction_modal.login.prompt": "Su domìniu de su serbidore domèsticu tuo, pro esempru mastodon.social", + "interaction_modal.no_account_yet": "Non ses in Mastodon?", "interaction_modal.on_this_server": "In custu serbidore", "interaction_modal.title.follow": "Sighi a {name}", "interaction_modal.title.reply": "Risponde a sa publicatzione de {name}", @@ -350,16 +388,16 @@ "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}.", + "link_preview.shares": "{count, plural, one {{counter} publicatzione} other {{counter} publicatziones}}", "lists.account.add": "Agiunghe a sa lista", "lists.account.remove": "Boga dae sa lista", "lists.delete": "Cantzella sa lista", "lists.edit": "Modìfica sa lista", "lists.edit.submit": "Muda su tìtulu", + "lists.exclusive": "Cua custas publicatziones dae sa pàgina printzipale", "lists.new.create": "Agiunghe lista", "lists.new.title_placeholder": "Tìtulu de sa lista noa", "lists.replies_policy.followed": "Cale si siat persone chi sighis", @@ -370,7 +408,20 @@ "lists.subheading": "Is listas tuas", "load_pending": "{count, plural, one {# elementu nou} other {# elementos noos}}", "loading_indicator.label": "Carrighende…", + "media_gallery.hide": "Cua", + "moved_to_account_banner.text": "Su contu tuo {disabledAccount} est disativadu in custu momentu ca est istadu tramudadu a {movedToAccount}.", + "mute_modal.hide_from_notifications": "Cua dae is notìficas", + "mute_modal.hide_options": "Cua is optziones", + "mute_modal.indefinite": "Fintzas a cando no apo a torrare a ativare is notìficas", + "mute_modal.show_options": "Ammustra is optziones", + "mute_modal.they_can_mention_and_follow": "Ti podent mentovare e sighire, però no ddos as a bìdere.", + "mute_modal.they_wont_know": "No ant a ischire chi ddos as postu a sa muda.", + "mute_modal.title": "Boles pònnere a custu contu a sa muda?", + "mute_modal.you_wont_see_mentions": "No as a bìdere is publicatziones chi mèntovent a custa persone.", + "mute_modal.you_wont_see_posts": "At a pòdere bìdere is publicatziones tuas, però tue no as a bìdere cussas suas.", "navigation_bar.about": "Informatziones", + "navigation_bar.administration": "Amministratzione", + "navigation_bar.advanced_interface": "Aberi s'interfache web avantzada", "navigation_bar.blocks": "Persones blocadas", "navigation_bar.bookmarks": "Sinnalibros", "navigation_bar.community_timeline": "Lìnia de tempus locale", @@ -382,10 +433,13 @@ "navigation_bar.favourites": "Preferidos", "navigation_bar.filters": "Faeddos a sa muda", "navigation_bar.follow_requests": "Rechestas de sighidura", + "navigation_bar.followed_tags": "Etichetas sighidas", "navigation_bar.follows_and_followers": "Gente chi sighis e sighiduras", "navigation_bar.lists": "Listas", "navigation_bar.logout": "Essi", + "navigation_bar.moderation": "Moderatzione", "navigation_bar.mutes": "Persones a sa muda", + "navigation_bar.opened_in_classic_interface": "Publicatziones, contos e àteras pàginas ispetzìficas sunt abertas in manera predefinida in s'interfache web clàssica.", "navigation_bar.personal": "Informatziones personales", "navigation_bar.pins": "Publicatziones apicadas", "navigation_bar.preferences": "Preferèntzias", @@ -393,10 +447,23 @@ "navigation_bar.search": "Chirca", "navigation_bar.security": "Seguresa", "not_signed_in_indicator.not_signed_in": "Ti depes identificare pro atzèdere a custa resursa.", + "notification.admin.report": "{name} at sinnaladu a {target}", + "notification.admin.report_account": "{name} at sinnaladu {count, plural, one {una publicatzione} other {# publicatziones}} dae {target} pro {category}", + "notification.admin.report_account_other": "{name} at sinnaladu {count, plural, one {una publicatzione} other {# publicatziones}} dae {target}", + "notification.admin.report_statuses": "{name} at sinnaladu a {target} pro {category}", + "notification.admin.report_statuses_other": "{name} at sinnaladu a {target}", "notification.admin.sign_up": "{name} at aderidu", + "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {un'àtera persone} other {àteras # persones}} si sunt registradas", "notification.favourite": "{name} at marcadu comente a preferidu s'istadu tuo", + "notification.favourite.name_and_others_with_link": "{name} e {count, plural, one {un'àtera persone} other {àteras # persones}} ant marcadu sa publicatzione tua comente preferida", "notification.follow": "{name} ti sighit", "notification.follow_request": "{name} at dimandadu de ti sighire", + "notification.follow_request.name_and_others": "{name} e {count, plural, one {un'àtera persone} other {àteras # persones}} ant pedidu de ti sighire", + "notification.label.mention": "Mèntovu", + "notification.label.private_mention": "Mèntovu privadu", + "notification.label.private_reply": "Risposta privada", + "notification.label.reply": "Risposta", + "notification.mention": "Mèntovu", "notification.moderation-warning.learn_more": "Àteras informatziones", "notification.moderation_warning": "T'ant imbiadu un'avisu de moderatzione", "notification.moderation_warning.action_delete_statuses": "Unas cantas de is publicatziones tuas sunt istadas cantzelladas.", @@ -409,12 +476,30 @@ "notification.own_poll": "Sondàgiu acabbadu", "notification.poll": "Unu sondàgiu in su chi as votadu est acabbadu", "notification.reblog": "{name} at cumpartzidu sa publicatzione tua", + "notification.reblog.name_and_others_with_link": "{name} e {count, plural, one {un'àtera persone} other {àteras # persones}} ant potentziadu sa publicatzione tua", "notification.relationships_severance_event": "Connessiones pèrdidas cun {name}", + "notification.relationships_severance_event.account_suspension": "S'amministratzione de {from} at suspèndidu a {target}; custu bolet nàrrere chi non podes prus retzire atualizatziones dae in cue o interagire cun cussos contos.", + "notification.relationships_severance_event.domain_block": "S'amministratzione de {from} at blocadu a {target}, incluende {followersCount} sighiduras tuas e {followingCount, plural, one {un'àteru contu} other {àteros # contos}} chi sighis.", "notification.relationships_severance_event.learn_more": "Àteras informatziones", + "notification.relationships_severance_event.user_domain_block": "As blocadu a {target}, bogadu a {followersCount} contos chi ti sighint e {followingCount, plural, one {un'àteru contu} other {àteros # contos}} chi sighis.", "notification.status": "{name} at publicadu cosa", "notification.update": "{name} at modificadu una publicatzione", "notification_requests.accept": "Atzeta", + "notification_requests.accept_multiple": "{count, plural, one {Atzeta una rechesta…} other {Atzeta # rechestas…}}", + "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Atzeta sa rechesta} other {Atzeta is rechestas}}", + "notification_requests.confirm_accept_multiple.message": "Ses atzetende {count, plural, one {una rechesta de notìfica} other {# rechestas de notìfica}}. Seguru chi boles sighire?", + "notification_requests.confirm_accept_multiple.title": "Boles atzetare is rechestas de notìfica?", + "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Iscarta sa rechesta} other {Iscarta is rechestas}}", + "notification_requests.confirm_dismiss_multiple.message": "Ses acanta de iscartare {count, plural, one {una rechesta de notìfica} other {# rechestas de notìfica}}. No nche {count, plural, one {} other {}} as a pòdere prus atzèdere in manera sèmplitze. Seguru chi boles sighire?", + "notification_requests.confirm_dismiss_multiple.title": "Boles iscartare is rechestas de notìfica?", "notification_requests.dismiss": "Iscarta", + "notification_requests.dismiss_multiple": "{count, plural, one {Iscarta una rechesta…} other {Iscarta # rechestas…}}", + "notification_requests.edit_selection": "Modifica", + "notification_requests.exit_selection": "Fatu", + "notification_requests.explainer_for_limited_account": "Is notìficas de custu contu sunt istadas filtradas, ca su contu est istadu limitadu dae sa moderatzione.", + "notification_requests.explainer_for_limited_remote_account": "Is notìficas de custu contu sunt istadas filtradas, ca su contu o su serbidore suo est istadu limitadu dae sa moderatzione.", + "notification_requests.maximize": "Ismànnia", + "notification_requests.minimize_banner": "Mìnima su bànner de notìficas filtradas", "notification_requests.notifications_from": "Notìficas dae {name}", "notification_requests.title": "Notìficas filtradas", "notifications.clear": "Lìmpia notìficas", @@ -474,6 +559,11 @@ "poll_button.add_poll": "Agiunghe unu sondàgiu", "poll_button.remove_poll": "Cantzella su sondàgiu", "privacy.change": "Modìfica s'istadu de riservadesa", + "privacy.direct.long": "Totu is utentes mentovados in sa publicatzione", + "privacy.direct.short": "Persones ispetzìficas", + "privacy.private.long": "Isceti chie ti sighit", + "privacy.private.short": "Sighiduras", + "privacy.public.long": "Cale si siat persone a intro o a foras de Mastodon", "privacy.public.short": "Pùblicu", "privacy_policy.last_updated": "Ùrtima atualizatzione: {date}", "privacy_policy.title": "Polìtica de riservadesa", @@ -499,34 +589,64 @@ "report.categories.legal": "Giurìdicu", "report.categories.other": "Àteru", "report.categories.spam": "Àliga", + "report.category.subtitle": "Sèbera sa currispondèntzia prus arta", + "report.category.title": "Nara·nos ite sutzedet cun custu {type}", "report.category.title_account": "profilu", "report.category.title_status": "publicatzione", "report.close": "Fatu", + "report.comment.title": "Nch'at àteru chi depamus ischire?", "report.forward": "Torra a imbiare a {target}", "report.forward_hint": "Custu contu est de un'àteru serbidore. Ddi boles imbiare puru una còpia anònima de custu informe?", "report.mute": "A sa muda", + "report.mute_explanation": "No as a bìdere is publicatziones suas. Ti podet ancora sighire e bìdere is publicatziones, ma no at a ischire chi dd'as postu a sa muda.", "report.next": "Imbeniente", "report.placeholder": "Cummentos additzionales", "report.reasons.dislike": "Non mi praghet", "report.reasons.dislike_description": "Est una cosa chi non boles bìdere", "report.reasons.legal": "Illegale", "report.reasons.other": "Un'àtera cosa", + "report.reasons.other_description": "Su problema non currispondet a is àteras categorias", "report.reasons.spam": "Est àliga", + "report.rules.subtitle": "Seletziona totu is chi àplichent", + "report.statuses.subtitle": "Seletziona totu is chi àplichent", "report.submit": "Imbia", "report.target": "Informende de {target}", + "report.thanks.title": "Non boles bìdere custu?", + "report.thanks.title_actionable": "Gràtzias de sa sinnalatzione, dd'amus a averiguare.", "report.unfollow": "Non sigas prus a @{name}", + "report.unfollow_explanation": "Ses sighende custu contu. Si non boles bìdere is publicatziones suas in sa pàgina printzipale tua, no ddu sigas prus.", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", "report_notification.categories.legal": "Giurìdicu", "report_notification.categories.legal_sentence": "cuntenutu illegale", "report_notification.categories.other": "Àteru", "report_notification.categories.other_sentence": "àteru", "report_notification.categories.spam": "Àliga", + "report_notification.categories.spam_sentence": "àliga", + "report_notification.open": "Aberi una sinnalatzione", + "search.no_recent_searches": "Nissuna chirca reghente", "search.placeholder": "Chirca", + "search.quick_action.account_search": "Profilos chi currispondent cun {x}", + "search.quick_action.go_to_account": "Bae a su profilu {x}", + "search.quick_action.go_to_hashtag": "Bae a s'eticheta {x}", + "search.quick_action.open_url": "Aberi s'URL in Mastodon", + "search.quick_action.status_search": "Publicatziones chi currispondent cun {x}", + "search.search_or_paste": "Chirca o incolla un'URL", + "search_popout.full_text_search_disabled_message": "No a disponimentu a {domain}.", + "search_popout.full_text_search_logged_out_message": "Isceti a disponimentu cun sa sessione aberta.", + "search_popout.language_code": "Còdighe de limba ISO", + "search_popout.options": "Optziones de chirca", + "search_popout.quick_actions": "Atziones lestras", + "search_popout.recent": "Chircas reghentes", + "search_popout.specific_date": "data ispetzìfica", "search_popout.user": "utente", "search_results.accounts": "Profilos", "search_results.all": "Totus", "search_results.hashtags": "Etichetas", + "search_results.nothing_found": "Impossìbile agatare currispondèntzias pro custos tèrmines de chirca", + "search_results.see_all": "Bide totu", "search_results.statuses": "Publicatziones", + "search_results.title": "Chirca {q}", + "server_banner.about_active_users": "Gente chi at impreadu custu serbidore is ùrtimas 30 dies (Utentes cun Atividade a su Mese)", "server_banner.active_users": "utentes ativos", "server_banner.administered_by": "Amministradu dae:", "server_banner.server_stats": "Istatìsticas de su serbidore:", 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..ffca0914e580a6 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -33,8 +33,10 @@ "account.follow": "Sledovať", "account.follow_back": "Sledovať späť", "account.followers": "Sledovatelia", - "account.followers.empty": "Tento účet ešte nikto nesleduje.", + "account.followers.empty": "Ešte nikto nesleduje tohto užívateľa.", + "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ť", @@ -82,6 +85,7 @@ "alert.rate_limited.title": "Priveľa žiadostí", "alert.unexpected.message": "Vyskytla sa nečakaná chyba.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Alternatívny popis", "announcement.announcement": "Oznámenie", "attachments_list.unprocessed": "(nespracované)", "audio.hide": "Skryť zvuk", @@ -151,7 +155,6 @@ "compose_form.poll.duration": "Trvanie ankety", "compose_form.poll.multiple": "Viacero možností", "compose_form.poll.option_placeholder": "Možnosť {number}", - "compose_form.poll.single": "Jediný výber", "compose_form.poll.switch_to_multiple": "Zmeniť anketu a povoliť viaceré možnosti", "compose_form.poll.switch_to_single": "Zmeniť anketu na jediný povolený výber", "compose_form.poll.type": "Typ", @@ -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..32626b80f9d19d 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -155,7 +155,6 @@ "compose_form.poll.duration": "Trajanje ankete", "compose_form.poll.multiple": "Več možnosti", "compose_form.poll.option_placeholder": "Možnost {number}", - "compose_form.poll.single": "Izberite eno možnost", "compose_form.poll.switch_to_multiple": "Spremenite anketo, da omogočite več izbir", "compose_form.poll.switch_to_single": "Spremenite anketo, da omogočite eno izbiro", "compose_form.poll.type": "Slog", @@ -217,7 +216,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 +410,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..e38ea796f60d02 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", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Kohëzgjatje pyetësori", "compose_form.poll.multiple": "Shumë zgjedhje", "compose_form.poll.option_placeholder": "Mundësia {number}", - "compose_form.poll.single": "Zgjidhni një", + "compose_form.poll.single": "Zgjedhje njëshe", "compose_form.poll.switch_to_multiple": "Ndrysho votimin për të lejuar shumë zgjedhje", "compose_form.poll.switch_to_single": "Ndrysho votimin për të lejuar vetëm një zgjedhje", "compose_form.poll.type": "Stil", @@ -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}", @@ -506,7 +508,6 @@ "notification.favourite": "{name} i vuri shenjë postimit tuaj si të parapëlqyer", "notification.favourite.name_and_others_with_link": "{name} dhe {count, plural, one {# tjetër} other {# të tjerë}} i vunë shenjë postimit tuaj si të parapëlqyer", "notification.follow": "{name} zuri t’ju ndjekë", - "notification.follow.name_and_others": "Ju ndoqi {name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", "notification.follow_request": "{name} ka kërkuar t’ju ndjekë", "notification.follow_request.name_and_others": "Ka kërkuar t’ju ndjekë {name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", "notification.label.mention": "Përmendje", @@ -514,6 +515,7 @@ "notification.label.private_reply": "Përgjigje private", "notification.label.reply": "Përgjigje", "notification.mention": "Përmendje", + "notification.mentioned_you": "{name} ju ka përmendur", "notification.moderation-warning.learn_more": "Mësoni më tepër", "notification.moderation_warning": "Ju është dhënë një sinjalizim moderimi", "notification.moderation_warning.action_delete_statuses": "Disa nga postimet tuaja janë hequr.", @@ -850,6 +852,11 @@ "upload_error.poll": "Me pyetësorët s’lejohet ngarkim kartelash.", "upload_form.audio_description": "Përshkruajeni për persona me dëgjim të kufizuar", "upload_form.description": "Përshkruajeni për persona me probleme shikimi", + "upload_form.drag_and_drop.instructions": "Që të merrni një bashkëngjitje media, shtypni tastin Space ose Enter. Teksa bëhet tërheqje, përdorni tastet shigjetë për ta shpënë bashkëngjitjen media në cilëndo drejtori që doni. Shtypni sërish Space ose Enter që të lihet bashkëngjitja media në pozicionin e vet të ri, ose shtypni Esc, që të anulohet veprimi.", + "upload_form.drag_and_drop.on_drag_cancel": "Tërheqja u anulua. Bashkëngjitja media {item} u la.", + "upload_form.drag_and_drop.on_drag_end": "Bashkëngjitja media {item} u la.", + "upload_form.drag_and_drop.on_drag_over": "Bashkëngjitja media {item} u lëviz.", + "upload_form.drag_and_drop.on_drag_start": "U mor bashkëngjitja media {item}.", "upload_form.edit": "Përpunoni", "upload_form.thumbnail": "Ndryshoni miniaturën", "upload_form.video_description": "Përshkruajeni për persona me dëgjim të kufizuar ose probleme shikimi", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index de30ca280fae12..4a33c2f5cae019 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -154,7 +154,6 @@ "compose_form.poll.duration": "Trajanje ankete", "compose_form.poll.multiple": "Višestruki izbor", "compose_form.poll.option_placeholder": "Opcija {number}", - "compose_form.poll.single": "Odaberite jedno", "compose_form.poll.switch_to_multiple": "Promenite anketu da biste omogućili više izbora", "compose_form.poll.switch_to_single": "Promenite anketu da biste omogućili jedan izbor", "compose_form.poll.type": "Stil", @@ -209,7 +208,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 +397,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..d80411859ed17f 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -154,7 +154,6 @@ "compose_form.poll.duration": "Трајање анкете", "compose_form.poll.multiple": "Вишеструки избор", "compose_form.poll.option_placeholder": "Опција {number}", - "compose_form.poll.single": "Одаберите једно", "compose_form.poll.switch_to_multiple": "Промените анкету да бисте омогућили више избора", "compose_form.poll.switch_to_single": "Промените анкету да бисте омогућили један избор", "compose_form.poll.type": "Стил", @@ -209,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 говори са другим друштвеним мрежама.", @@ -399,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/sv.json b/app/javascript/mastodon/locales/sv.json index 4d560a6495e451..d9d4da4ad0a8c7 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Mängd begränsad", "alert.unexpected.message": "Ett oväntat fel uppstod.", "alert.unexpected.title": "Hoppsan!", + "alt_text_badge.title": "Alt-Text", "announcement.announcement": "Meddelande", "attachments_list.unprocessed": "(obehandlad)", "audio.hide": "Dölj audio", @@ -97,6 +98,8 @@ "block_modal.title": "Blockera användare?", "block_modal.you_wont_see_mentions": "Du kommer inte att se inlägg som nämner dem.", "boost_modal.combo": "Du kan trycka på {combo} för att hoppa över detta nästa gång", + "boost_modal.reblog": "Boosta inlägg?", + "boost_modal.undo_reblog": "Avboosta inlägg?", "bundle_column_error.copy_stacktrace": "Kopiera felrapport", "bundle_column_error.error.body": "Den begärda sidan kunde inte visas. Det kan bero på ett fel i vår kod eller ett problem med webbläsarens kompatibilitet.", "bundle_column_error.error.title": "Åh nej!", @@ -155,7 +158,7 @@ "compose_form.poll.duration": "Varaktighet för omröstning", "compose_form.poll.multiple": "Flera val", "compose_form.poll.option_placeholder": "Alternativ {number}", - "compose_form.poll.single": "Välj en", + "compose_form.poll.single": "Enval", "compose_form.poll.switch_to_multiple": "Ändra enkät för att tillåta flera val", "compose_form.poll.switch_to_single": "Ändra enkät för att tillåta ett enda val", "compose_form.poll.type": "Stil", @@ -219,7 +222,8 @@ "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_will_lose_num_followers": "Du kommer att förlora {followersCount, plural, other {{followersCountDisplay} följare}} och {followingCount, plural, one {{followingCountDisplay} person du följer} other {{followingCountDisplay} personer du följer}}.", + "domain_block_modal.you_will_lose_relationships": "Du kommer att förlora alla följare och personer du följer från denna server.", "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.", @@ -301,6 +305,7 @@ "filter_modal.select_filter.subtitle": "Använd en befintlig kategori eller skapa en ny", "filter_modal.select_filter.title": "Filtrera detta inlägg", "filter_modal.title.status": "Filtrera ett inlägg", + "filter_warning.matches_filter": "Matchar filtret \"{title}\"", "filtered_notifications_banner.pending_requests": "Från {count, plural, =0 {ingen} one {en person} other {# personer}} du kanske känner", "filtered_notifications_banner.title": "Filtrerade aviseringar", "firehose.all": "Allt", @@ -429,10 +434,10 @@ "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", + "lightbox.zoom_in": "Zooma till faktisk storlek", + "lightbox.zoom_out": "Zooma för att passa", "limited_account_hint.action": "Visa profil ändå", "limited_account_hint.title": "Denna profil har dolts av {domain}s moderatorer.", "link_preview.author": "Av {name}", @@ -466,6 +471,7 @@ "mute_modal.you_wont_see_mentions": "Du kommer inte att se inlägg som nämner dem.", "mute_modal.you_wont_see_posts": "De kan fortfarande se dina inlägg, men du kan inte se deras.", "navigation_bar.about": "Om", + "navigation_bar.administration": "Administration", "navigation_bar.advanced_interface": "Öppna i avancerat webbgränssnitt", "navigation_bar.blocks": "Blockerade användare", "navigation_bar.bookmarks": "Bokmärken", @@ -482,6 +488,7 @@ "navigation_bar.follows_and_followers": "Följer och följare", "navigation_bar.lists": "Listor", "navigation_bar.logout": "Logga ut", + "navigation_bar.moderation": "Moderering", "navigation_bar.mutes": "Tystade användare", "navigation_bar.opened_in_classic_interface": "Inlägg, konton och andra specifika sidor öppnas som standard i det klassiska webbgränssnittet.", "navigation_bar.personal": "Personligt", @@ -501,7 +508,6 @@ "notification.favourite": "{name} favoritmarkerade ditt inlägg", "notification.favourite.name_and_others_with_link": "{name} och {count, plural, one {# annan} other {# andra}} har favoritmarkerat ditt inlägg", "notification.follow": "{name} följer dig", - "notification.follow.name_and_others": "{name} och {count, plural, one {# en annan} other {# andra}} följer dig", "notification.follow_request": "{name} har begärt att följa dig", "notification.follow_request.name_and_others": "{name} och {count, plural, one {# en annan} other {# andra}} har bett att följa dig", "notification.label.mention": "Nämn", @@ -509,6 +515,7 @@ "notification.label.private_reply": "Privata svar", "notification.label.reply": "Svar", "notification.mention": "Nämn", + "notification.mentioned_you": "{name} nämnde dig", "notification.moderation-warning.learn_more": "Läs mer", "notification.moderation_warning": "Du har fått en moderationsvarning", "notification.moderation_warning.action_delete_statuses": "Några av dina inlägg har tagits bort.", @@ -773,6 +780,7 @@ "status.bookmark": "Bokmärk", "status.cancel_reblog_private": "Sluta boosta", "status.cannot_reblog": "Detta inlägg kan inte boostas", + "status.continued_thread": "Fortsatt tråd", "status.copy": "Kopiera inläggslänk", "status.delete": "Radera", "status.detailed_status": "Detaljerad samtalsvy", @@ -806,6 +814,7 @@ "status.reblogs.empty": "Ingen har boostat detta inlägg än. När någon gör det kommer de synas här.", "status.redraft": "Radera & gör om", "status.remove_bookmark": "Ta bort bokmärke", + "status.replied_in_thread": "Svarade i tråden", "status.replied_to": "Svarade på {name}", "status.reply": "Svara", "status.replyAll": "Svara på tråden", @@ -843,6 +852,11 @@ "upload_error.poll": "Filuppladdning tillåts inte med omröstningar.", "upload_form.audio_description": "Beskriv för personer med hörselnedsättning", "upload_form.description": "Beskriv för synskadade", + "upload_form.drag_and_drop.instructions": "För att plocka upp en mediebilaga, tryck på mellanslag eller enter. Använd piltangenterna för att flytta mediebilagan. Tryck på mellanslag eller enter igen för att släppa mediebilagan i sin nya position, eller tryck på escape för att avbryta.", + "upload_form.drag_and_drop.on_drag_cancel": "Flytten avbröts. Mediebilagan {item} släpptes.", + "upload_form.drag_and_drop.on_drag_end": "Mediebilagan {item} släpptes.", + "upload_form.drag_and_drop.on_drag_over": "Mediebilagan {item} flyttades.", + "upload_form.drag_and_drop.on_drag_start": "Mediebilagan {item} plockades upp.", "upload_form.edit": "Redigera", "upload_form.thumbnail": "Ändra miniatyr", "upload_form.video_description": "Beskriv för personer med hörsel- eller synnedsättning", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 9578431ff741b2..d05840aa83e4ac 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": "ซ่อนเสียง", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "ระยะเวลาการสำรวจความคิดเห็น", "compose_form.poll.multiple": "หลายตัวเลือก", "compose_form.poll.option_placeholder": "ตัวเลือก {number}", - "compose_form.poll.single": "เลือกอย่างใดอย่างหนึ่ง", "compose_form.poll.switch_to_multiple": "เปลี่ยนการสำรวจความคิดเห็นเป็นอนุญาตหลายตัวเลือก", "compose_form.poll.switch_to_single": "เปลี่ยนการสำรวจความคิดเห็นเป็นอนุญาตตัวเลือกเดียว", "compose_form.poll.type": "ลักษณะ", @@ -221,7 +221,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 +433,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}", @@ -506,7 +507,6 @@ "notification.favourite": "{name} ได้ชื่นชอบโพสต์ของคุณ", "notification.favourite.name_and_others_with_link": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ชื่นชอบโพสต์ของคุณ", "notification.follow": "{name} ได้ติดตามคุณ", - "notification.follow.name_and_others": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ติดตามคุณ", "notification.follow_request": "{name} ได้ขอติดตามคุณ", "notification.follow_request.name_and_others": "{name} และ {count, plural, other {# อื่น ๆ}} ได้ขอติดตามคุณ", "notification.label.mention": "การกล่าวถึง", @@ -514,6 +514,7 @@ "notification.label.private_reply": "การตอบกลับแบบส่วนตัว", "notification.label.reply": "การตอบกลับ", "notification.mention": "การกล่าวถึง", + "notification.mentioned_you": "{name} ได้กล่าวถึงคุณ", "notification.moderation-warning.learn_more": "เรียนรู้เพิ่มเติม", "notification.moderation_warning": "คุณได้รับคำเตือนการกลั่นกรอง", "notification.moderation_warning.action_delete_statuses": "เอาโพสต์บางส่วนของคุณออกแล้ว", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 6c21026bdbd0e4..2cf7f1929aa3cc 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -117,7 +117,6 @@ "compose_form.poll.duration": "tenpo pana", "compose_form.poll.multiple": "pana mute", "compose_form.poll.option_placeholder": "ken nanpa {number}", - "compose_form.poll.single": "pana pi wan taso", "compose_form.poll.switch_to_multiple": "o ante e nasin pana. pana mute o ken", "compose_form.poll.switch_to_single": "o ante e nasin pana. pana wan taso o lon", "compose_form.poll.type": "nasin", @@ -163,7 +162,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 +250,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..dae573370a637f 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", @@ -123,7 +124,7 @@ "column.direct": "Özel değinmeler", "column.directory": "Profillere göz at", "column.domain_blocks": "Engellenen alan adları", - "column.favourites": "Favorilerin", + "column.favourites": "Gözdelerin", "column.firehose": "Anlık Akışlar", "column.follow_requests": "Takip istekleri", "column.home": "Anasayfa", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "Anket süresi", "compose_form.poll.multiple": "Çoktan seçmeli", "compose_form.poll.option_placeholder": "Seçenek {number}", - "compose_form.poll.single": "Birini seç", + "compose_form.poll.single": "Tekli seçim", "compose_form.poll.switch_to_multiple": "Birden çok seçeneğe izin vermek için anketi değiştir", "compose_form.poll.switch_to_single": "Tek bir seçeneğe izin vermek için anketi değiştir", "compose_form.poll.type": "Stil", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} gönderinizi beğendi", "notification.favourite.name_and_others_with_link": "{name} ve {count, plural, one {# diğer kişi} other {# diğer kişi}} gönderinizi beğendi", "notification.follow": "{name} seni takip etti", - "notification.follow.name_and_others": "{name} ve {count, plural, one {# diğer kişi} other {# diğer kişi}} sizi takip etti", + "notification.follow.name_and_others": "{name} ve {count, plural, one {# diğer kişi} other {# diğer kişi}} sizi takip etti", "notification.follow_request": "{name} size takip isteği gönderdi", "notification.follow_request.name_and_others": "{name} ve {count, plural, one {# diğer kişi} other {# diğer kişi}} size takip etme isteği gönderdi", "notification.label.mention": "Bahsetme", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Özel yanıt", "notification.label.reply": "Yanıt", "notification.mention": "Bahsetme", + "notification.mentioned_you": "{name} sizden söz etti", "notification.moderation-warning.learn_more": "Daha fazlası", "notification.moderation_warning": "Hesabınız bir denetim uyarısı aldı", "notification.moderation_warning.action_delete_statuses": "Bazı gönderileriniz kaldırıldı.", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Hızlı filtre çubuğu", "notifications.column_settings.follow": "Yeni takipçiler:", "notifications.column_settings.follow_request": "Yeni takip istekleri:", + "notifications.column_settings.group": "Grupla", "notifications.column_settings.mention": "Bahsetmeler:", "notifications.column_settings.poll": "Anket sonuçları:", "notifications.column_settings.push": "Anlık bildirimler", @@ -810,7 +814,7 @@ "status.reblogged_by": "{name} yeniden paylaştı", "status.reblogs": "{count, plural, one {yeniden paylaşım} other {yeniden paylaşım}}", "status.reblogs.empty": "Henüz hiç kimse bu gönderiyi yeniden paylaşmadı. Herhangi bir kullanıcı yeniden paylaştığında burada görüntülenecek.", - "status.redraft": "Sil,Düzenle ve Yeniden paylaş", + "status.redraft": "Sil,Düzenle ve yeniden-paylaş", "status.remove_bookmark": "Yer işaretini kaldır", "status.replied_in_thread": "Akışta yanıtlandı", "status.replied_to": "{name} kullanıcısına yanıt verdi", @@ -850,6 +854,11 @@ "upload_error.poll": "Anketlerde dosya yüklemesine izin verilmez.", "upload_form.audio_description": "İşitme kaybı olan kişiler için yazı ekleyiniz", "upload_form.description": "Görme engelliler için açıklama", + "upload_form.drag_and_drop.instructions": "Bir medya eklentisini taşımak için, boşluk veya enter tuşuna basın. Sürükleme sırasında medya eklentisini herhangi bir yöne hareket ettirmek için ok tuşlarını kullanın. Medya eklentisini yeni konumuna bırakmak için tekrar boşluk veya enter tuşuna basın veya işlemi iptal etmek için escape tuşuna basın.", + "upload_form.drag_and_drop.on_drag_cancel": "Sürükleme iptal edildi. Medya eklentisi {item} bırakıldı.", + "upload_form.drag_and_drop.on_drag_end": "Medya eklentisi {item} bırakıldı.", + "upload_form.drag_and_drop.on_drag_over": "Medya eklentisi {item} hareket ettirildi.", + "upload_form.drag_and_drop.on_drag_start": "Medya eklentisi {item} tutuldu.", "upload_form.edit": "Düzenle", "upload_form.thumbnail": "Küçük resmi değiştir", "upload_form.video_description": "İşitme kaybı veya görme engeli olan kişiler için açıklama ekleyiniz", 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..66392afd79fcb3 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": "Сховати аудіо", @@ -157,7 +158,6 @@ "compose_form.poll.duration": "Тривалість опитування", "compose_form.poll.multiple": "Кілька варіантів", "compose_form.poll.option_placeholder": "Варіант {number}", - "compose_form.poll.single": "Виберіть варіант", "compose_form.poll.switch_to_multiple": "Дозволити вибір декількох відповідей", "compose_form.poll.switch_to_single": "Перемкнути у режим вибору однієї відповіді", "compose_form.poll.type": "Стиль", @@ -221,7 +221,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 +433,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}", @@ -506,7 +507,6 @@ "notification.favourite": "Ваш допис сподобався {name}", "notification.favourite.name_and_others_with_link": "{name} та {count, plural, one {# інший} few {# інших} many {# інших} other {# інший}} вподобали ваш допис", "notification.follow": "{name} підписалися на вас", - "notification.follow.name_and_others": "{name} та {count, plural, one {# інший} few {# інших} many {# інших} other {# інший}} стежать за вами", "notification.follow_request": "{name} відправили запит на підписку", "notification.follow_request.name_and_others": "{name} та {count, plural, one {# інший} few {# інших} many {# інших} other {# інший}} надсилають вам запит на стеження", "notification.label.mention": "Згадка", @@ -514,6 +514,7 @@ "notification.label.private_reply": "Приватна відповідь", "notification.label.reply": "Відповідь", "notification.mention": "Згадка", + "notification.mentioned_you": "{name} згадує вас", "notification.moderation-warning.learn_more": "Докладніше", "notification.moderation_warning": "Ви отримали попередження модерації", "notification.moderation_warning.action_delete_statuses": "Деякі з ваших дописів було вилучено.", @@ -564,6 +565,7 @@ "notifications.column_settings.filter_bar.category": "Панель швидкого фільтра", "notifications.column_settings.follow": "Нові підписники:", "notifications.column_settings.follow_request": "Нові запити на підписку:", + "notifications.column_settings.group": "Група", "notifications.column_settings.mention": "Згадки:", "notifications.column_settings.poll": "Результати опитування:", "notifications.column_settings.push": "Push-сповіщення", @@ -850,6 +852,11 @@ "upload_error.poll": "Не можна завантажувати файли до опитувань.", "upload_form.audio_description": "Опишіть для людей із вадами слуху", "upload_form.description": "Опишіть для людей з вадами зору", + "upload_form.drag_and_drop.instructions": "Щоб вибрати медіавкладення, натисніть пробіл або Enter. Під час перетягування, використайте клавіші зі стрілками для переміщення вкладення в будь-якому напрямку. Натисніть пробіл або Enter знову, щоб залишити медіавкладення в новому положенні, або натисніть клавішу Escape, щоб скасувати.", + "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/vi.json b/app/javascript/mastodon/locales/vi.json index 9fcd00ddc7c56a..1daeada1a28986 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,14 +434,14 @@ "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.more_from_author": "Viết bởi {name}", "link_preview.shares": "{count, plural, other {{counter} lượt chia sẻ}}", "lists.account.add": "Thêm vào danh sách", "lists.account.remove": "Xóa khỏi danh sách", @@ -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ệ", @@ -506,7 +508,7 @@ "notification.favourite": "{name} thích tút của bạn", "notification.favourite.name_and_others_with_link": "{name} và {count, plural, other {# người khác}} đã thích tút của bạn", "notification.follow": "{name} theo dõi bạn", - "notification.follow.name_and_others": "{name} và {count, plural, other {# người khác}} đã theo dõi bạn", + "notification.follow.name_and_others": "{name} và {count, plural, other {# người khác}} theo dõi bạn", "notification.follow_request": "{name} yêu cầu theo dõi bạn", "notification.follow_request.name_and_others": "{name} và {count, plural, other {# người khác}} đã yêu cầu theo dõi bạn", "notification.label.mention": "Lượt nhắc", @@ -514,6 +516,7 @@ "notification.label.private_reply": "Trả lời riêng", "notification.label.reply": "Trả lời", "notification.mention": "Lượt nhắc", + "notification.mentioned_you": "{name} nhắc đến bạn", "notification.moderation-warning.learn_more": "Tìm hiểu", "notification.moderation_warning": "Bạn vừa nhận một cảnh báo kiểm duyệt", "notification.moderation_warning.action_delete_statuses": "Một vài tút của bạn bị gỡ.", @@ -524,7 +527,7 @@ "notification.moderation_warning.action_silence": "Tài khoản của bạn đã bị hạn chế.", "notification.moderation_warning.action_suspend": "Tài khoản của bạn đã bị vô hiệu hóa.", "notification.own_poll": "Cuộc bình chọn của bạn đã kết thúc", - "notification.poll": "Cuộc bình chọn có bạn tham gia đã kết thúc", + "notification.poll": "Cuộc bình chọn mà bạn tham gia đã kết thúc", "notification.reblog": "{name} đăng lại tút của bạn", "notification.reblog.name_and_others_with_link": "{name} và {count, plural, other {# người khác}} đã đăng lại tút của bạn", "notification.relationships_severance_event": "Mất kết nối với {name}", @@ -533,7 +536,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 +557,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", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "Thanh lọc nhanh", "notifications.column_settings.follow": "Người theo dõi:", "notifications.column_settings.follow_request": "Yêu cầu theo dõi:", + "notifications.column_settings.group": "Nhóm", "notifications.column_settings.mention": "Lượt nhắc đến:", "notifications.column_settings.poll": "Kết quả bình chọn:", "notifications.column_settings.push": "Thông báo đẩy", @@ -601,8 +605,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 +625,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 +661,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 +717,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 +742,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 +752,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 +782,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 +791,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 +816,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 +854,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..3b1e6b813de9e0 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -36,7 +36,7 @@ "account.followers.empty": "目前无人关注此用户。", "account.followers_counter": "{count, plural, other {{counter} 关注者}}", "account.following": "正在关注", - "account.following_counter": "{count, plural, other {{counter} 关注}}", + "account.following_counter": "正在关注 {count, plural, other {{counter} 人}}", "account.follows.empty": "此用户目前未关注任何人。", "account.go_to_profile": "前往个人资料页", "account.hide_reblogs": "隐藏来自 @{name} 的转嘟", @@ -59,7 +59,7 @@ "account.posts_with_replies": "嘟文和回复", "account.report": "举报 @{name}", "account.requested": "正在等待对方同意。点击取消发送关注请求", - "account.requested_follow": "{name} 已经向你发送了关注请求", + "account.requested_follow": "{name} 向你发送了关注请求", "account.share": "分享 @{name} 的个人资料页", "account.show_reblogs": "显示来自 @{name} 的转嘟", "account.statuses_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": "隐藏音频", @@ -93,8 +94,8 @@ "block_modal.show_more": "显示更多", "block_modal.they_cant_mention": "他们不能提及或关注你。", "block_modal.they_cant_see_posts": "他们看不到你的嘟文,你也看不到他们的嘟文。", - "block_modal.they_will_know": "他们将能看到他们被屏蔽。", - "block_modal.title": "是否屏蔽该用户?", + "block_modal.they_will_know": "对方将能看到自己被屏蔽。", + "block_modal.title": "屏蔽该用户?", "block_modal.you_wont_see_mentions": "你将不会看到提及他们的嘟文。", "boost_modal.combo": "下次按住 {combo} 即可跳过此提示", "boost_modal.reblog": "是否转嘟?", @@ -203,7 +204,7 @@ "copy_icon_button.copied": "已复制到剪贴板", "copypaste.copied": "已复制", "copypaste.copy_to_clipboard": "复制到剪贴板", - "directory.federated": "来自已知的联邦宇宙", + "directory.federated": "来自已知联邦宇宙", "directory.local": "仅来自 {domain}", "directory.new_arrivals": "新来者", "directory.recently_active": "最近活跃", @@ -219,23 +220,24 @@ "domain_block_modal.block_account_instead": "改为屏蔽 @{name}", "domain_block_modal.they_can_interact_with_old_posts": "来自该服务器的人可以与你之前的嘟文交互。", "domain_block_modal.they_cant_follow": "此服务器上没有人可以关注你。", - "domain_block_modal.they_wont_know": "他们不会知道自己被屏蔽。", + "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与其它社交网络交流时使用的语言。", + "domain_pill.activitypub_lets_connect": "它让你不仅能与 Mastodon 上的人交流互动,还能与其它不同社交应用上的人联系。", + "domain_pill.activitypub_like_language": "ActivityPub 好比 Mastodon 与其它社交网络交流时使用的语言。", "domain_pill.server": "服务器", - "domain_pill.their_handle": "它们的代号:", - "domain_pill.their_server": "它们的数字家园,它们的所有嘟文都存放在那里。", - "domain_pill.their_username": "它们在它们的服务器上的唯一标识符。在不同的服务器上可能会找到相同用户名的用户。", + "domain_pill.their_handle": "对方代号:", + "domain_pill.their_server": "对方的数字家园,对方的所有嘟文都存放在那里。", + "domain_pill.their_username": "对方在其服务器上的唯一标识符。不同服务器上可能会存在相同用户名的用户。", "domain_pill.username": "用户名", "domain_pill.whats_in_a_handle": "代号里都有什么?", - "domain_pill.who_they_are": "代号可以告诉你一个人是谁和在哪里,所以你可以在社交网络上与的人们互动。", - "domain_pill.who_you_are": "你的代号可以告诉别人你是谁和你在哪里,这样社交网络上来自的人们就可以与你互动。", + "domain_pill.who_they_are": "代号可以表明用户和其所在站点,你可以在社交网络上与的人们互动。", + "domain_pill.who_you_are": "代号可以表明你自己和你所在站点,社交网络上来自的人们因此可以与你互动。", "domain_pill.your_handle": "你的代号:", "domain_pill.your_server": "你的数字家园,你的所有嘟文都存放在这里。不喜欢这个服务器吗?随时带上你的关注者一起迁移到其它服务器。", - "domain_pill.your_username": "你在这个服务器上的唯一标识符。在不同的服务器上可能会找到相同用户名的用户。", + "domain_pill.your_username": "你在这个服务器上的唯一标识符。不同服务器上可能会存在相同用户名的用户。", "embed.instructions": "复制下列代码以在你的网站中嵌入此嘟文。", "embed.preview": "它会像这样显示出来:", "emoji_button.activity": "活动", @@ -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}", @@ -463,11 +465,11 @@ "mute_modal.hide_options": "隐藏选项", "mute_modal.indefinite": "直到我取消隐藏他们", "mute_modal.show_options": "显示选项", - "mute_modal.they_can_mention_and_follow": "他们可以提及和关注你,但是你看不到他们。", - "mute_modal.they_wont_know": "它们不会知道自己已被隐藏。", - "mute_modal.title": "隐藏用户?", - "mute_modal.you_wont_see_mentions": "你看不到提及他们的嘟文。", - "mute_modal.you_wont_see_posts": "他们可以看到你的嘟文,但是你看不到他们的。", + "mute_modal.they_can_mention_and_follow": "对方可以提及和关注你,但是你看不到对方。", + "mute_modal.they_wont_know": "对方不会知道自己被隐藏。", + "mute_modal.title": "隐藏该用户?", + "mute_modal.you_wont_see_mentions": "你看不到提及对方的嘟文。", + "mute_modal.you_wont_see_posts": "对方可以看到你的嘟文,但是你看不到对方的。", "navigation_bar.about": "关于", "navigation_bar.administration": "管理", "navigation_bar.advanced_interface": "在高级网页界面中打开", @@ -506,7 +508,7 @@ "notification.favourite": "{name} 喜欢了你的嘟文", "notification.favourite.name_and_others_with_link": "{name} 和 {count, plural, other {另外 # 人}} 喜欢了你的嘟文", "notification.follow": "{name} 开始关注你", - "notification.follow.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 关注了你", + "notification.follow.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 关注了你", "notification.follow_request": "{name} 向你发送了关注请求", "notification.follow_request.name_and_others": "{name} 和 {count, plural, other {另外 # 人}} 向你发送了关注请求", "notification.label.mention": "提及", @@ -514,6 +516,7 @@ "notification.label.private_reply": "私人回复", "notification.label.reply": "回复", "notification.mention": "提及", + "notification.mentioned_you": "{name} 提到了你", "notification.moderation-warning.learn_more": "了解更多", "notification.moderation_warning": "你收到了一条管理警告", "notification.moderation_warning.action_delete_statuses": "你的一些嘟文已被移除。", @@ -521,15 +524,15 @@ "notification.moderation_warning.action_mark_statuses_as_sensitive": "你的一些嘟文已被标记为敏感内容。", "notification.moderation_warning.action_none": "你的账号收到了管理警告。", "notification.moderation_warning.action_sensitive": "今后你的嘟文都会被标记为敏感内容。", - "notification.moderation_warning.action_silence": "你的账号已被限制。", - "notification.moderation_warning.action_suspend": "你的账号已被封禁.", + "notification.moderation_warning.action_silence": "你的账号已被隐藏。", + "notification.moderation_warning.action_suspend": "你的账号已被封禁。", "notification.own_poll": "你的投票已经结束", "notification.poll": "你参与的一项投票已结束", "notification.reblog": "{name} 转发了你的嘟文", "notification.reblog.name_and_others_with_link": "{name} 和 {count, plural, other {另外 # 人}} 转嘟了你的嘟文", "notification.relationships_severance_event": "与 {name} 的联系已断开", - "notification.relationships_severance_event.account_suspension": "一名来自 {from} 的管理员已经封禁了{target},这意味着你将无法再收到他们的更新或与他们互动。", - "notification.relationships_severance_event.domain_block": "一名来自 {from} 的管理员已经屏蔽了 {target},其中包括你的 {followersCount} 个关注者和 {followingCount, plural, other {# 个关注}}。", + "notification.relationships_severance_event.account_suspension": "来自 {from} 的管理员封禁了 {target},这意味着你将无法再收到对方的更新或与其互动。", + "notification.relationships_severance_event.domain_block": "来自 {from} 的管理员屏蔽了 {target},其中包括你的 {followersCount} 个关注者和 {followingCount, plural, other {# 个关注}}。", "notification.relationships_severance_event.learn_more": "了解更多", "notification.relationships_severance_event.user_domain_block": "你已经屏蔽了 {target},移除了你的 {followersCount} 个关注者和 {followingCount, plural, other {# 个关注}}。", "notification.status": "{name} 刚刚发布嘟文", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "快速筛选栏", "notifications.column_settings.follow": "新粉丝:", "notifications.column_settings.follow_request": "新关注请求:", + "notifications.column_settings.group": "分组", "notifications.column_settings.mention": "提及:", "notifications.column_settings.poll": "投票结果:", "notifications.column_settings.push": "推送通知", @@ -778,14 +782,14 @@ "status.bookmark": "添加到书签", "status.cancel_reblog_private": "取消转贴", "status.cannot_reblog": "这条嘟文不允许被转嘟", - "status.continued_thread": "继续线程", + "status.continued_thread": "上接嘟文串", "status.copy": "复制嘟文链接", "status.delete": "删除", "status.detailed_status": "详细的对话视图", "status.direct": "私下提及 @{name}", "status.direct_indicator": "私下提及", "status.edit": "编辑", - "status.edited": "最近编辑于 {date}", + "status.edited": "最后编辑于 {date}", "status.edited_x_times": "共编辑 {count, plural, one {{count} 次} other {{count} 次}}", "status.embed": "获取嵌入代码", "status.favourite": "喜欢", @@ -812,10 +816,10 @@ "status.reblogs.empty": "没有人转嘟过此条嘟文。如果有人转嘟了,就会显示在这里。", "status.redraft": "删除并重新编辑", "status.remove_bookmark": "移除书签", - "status.replied_in_thread": "已在线程中回复", + "status.replied_in_thread": "回复给嘟文串", "status.replied_to": "回复给 {name}", "status.reply": "回复", - "status.replyAll": "回复所有人", + "status.replyAll": "回复此嘟文串", "status.report": "举报 @{name}", "status.sensitive_warning": "敏感内容", "status.share": "分享", @@ -850,6 +854,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..62a43fa7e4b723 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -151,7 +151,6 @@ "compose_form.poll.duration": "投票期限", "compose_form.poll.multiple": "多選", "compose_form.poll.option_placeholder": "選項 {number}", - "compose_form.poll.single": "選擇一個", "compose_form.poll.switch_to_multiple": "變更投票為允許多個選項", "compose_form.poll.switch_to_single": "變更投票為限定單一選項", "compose_form.poll.type": "風格", @@ -208,7 +207,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 +396,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..388e09fc98ac03 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": "隱藏音訊", @@ -157,7 +158,7 @@ "compose_form.poll.duration": "投票期限", "compose_form.poll.multiple": "多選", "compose_form.poll.option_placeholder": "選項 {number}", - "compose_form.poll.single": "選擇一個", + "compose_form.poll.single": "單一選擇", "compose_form.poll.switch_to_multiple": "變更投票為允許多個選項", "compose_form.poll.switch_to_single": "變更投票為允許單一選項", "compose_form.poll.type": "投票方式", @@ -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}", @@ -506,7 +508,7 @@ "notification.favourite": "{name} 已將您的嘟文加入最愛", "notification.favourite.name_and_others_with_link": "{name} 與{count, plural, other {其他 # 個人}}已將您的嘟文加入最愛", "notification.follow": "{name} 已跟隨您", - "notification.follow.name_and_others": "{name} 與{count, plural, other {其他 # 個人}}已跟隨您", + "notification.follow.name_and_others": "{name} 與{count, plural, other {其他 # 個人}}已跟隨您", "notification.follow_request": "{name} 要求跟隨您", "notification.follow_request.name_and_others": "{name} 與{count, plural, other {其他 # 個人}}已請求跟隨您", "notification.label.mention": "提及", @@ -514,6 +516,7 @@ "notification.label.private_reply": "私訊回嘟", "notification.label.reply": "回嘟", "notification.mention": "提及", + "notification.mentioned_you": "{name} 已提及您", "notification.moderation-warning.learn_more": "了解更多", "notification.moderation_warning": "您已收到管理員警告", "notification.moderation_warning.action_delete_statuses": "某些您的嘟文已被刪除。", @@ -564,6 +567,7 @@ "notifications.column_settings.filter_bar.category": "快速過濾器", "notifications.column_settings.follow": "新的跟隨者:", "notifications.column_settings.follow_request": "新的跟隨請求:", + "notifications.column_settings.group": "群組", "notifications.column_settings.mention": "提及:", "notifications.column_settings.poll": "投票結果:", "notifications.column_settings.push": "推播通知", @@ -850,6 +854,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/account.ts b/app/javascript/mastodon/models/account.ts index a04ebe62915803..8e8e3b0e8dffe8 100644 --- a/app/javascript/mastodon/models/account.ts +++ b/app/javascript/mastodon/models/account.ts @@ -95,6 +95,9 @@ export const accountDefaultValues: AccountShape = { limited: false, moved: null, hide_collections: false, + // This comes from `ApiMutedAccountJSON`, but we should eventually + // store that in a different object. + mute_expires_at: null, }; const AccountFactory = ImmutableRecord(accountDefaultValues); 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/compose.js b/app/javascript/mastodon/reducers/compose.js index 8f21b329faf241..6f1402916e027e 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -422,12 +422,12 @@ export default function compose(state = initialState, action) { .set('isUploadingThumbnail', false) .update('media_attachments', list => list.map(item => { if (item.get('id') === action.media.id) { - return fromJS(action.media); + return fromJS(action.media).set('unattached', item.get('unattached')); } return item; })); - case INIT_MEDIA_EDIT_MODAL: + case INIT_MEDIA_EDIT_MODAL: { const media = state.get('media_attachments').find(item => item.get('id') === action.id); return state.set('media_modal', ImmutableMap({ id: action.id, @@ -436,6 +436,7 @@ export default function compose(state = initialState, action) { focusY: media.getIn(['meta', 'focus', 'y'], 0), dirty: false, })); + } case COMPOSE_CHANGE_MEDIA_DESCRIPTION: return state.setIn(['media_modal', 'description'], action.description).setIn(['media_modal', 'dirty'], true); case COMPOSE_CHANGE_MEDIA_FOCUS: diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts index f3c83ccd8d6e44..7a165f5fec1297 100644 --- a/app/javascript/mastodon/reducers/notification_groups.ts +++ b/app/javascript/mastodon/reducers/notification_groups.ts @@ -29,6 +29,7 @@ import { import type { ApiNotificationJSON, ApiNotificationGroupJSON, + NotificationType, } from 'mastodon/api_types/notifications'; import { compareId } from 'mastodon/compare_id'; import { usePendingItems } from 'mastodon/initial_state'; @@ -204,7 +205,15 @@ function mergeGapsAround( function processNewNotification( groups: NotificationGroupsState['groups'], notification: ApiNotificationJSON, + groupedTypes: NotificationType[], ) { + if (!groupedTypes.includes(notification.type)) { + notification = { + ...notification, + group_key: `ungrouped-${notification.id}`, + }; + } + const existingGroupIndex = groups.findIndex( (group) => group.type !== 'gap' && group.group_key === notification.group_key, @@ -242,7 +251,7 @@ function processNewNotification( groups.unshift(existingGroup); } } else { - // Create a new group + // We have not found an existing group, create a new one groups.unshift(createNotificationGroupFromNotificationJSON(notification)); } } @@ -468,11 +477,13 @@ export const notificationGroupsReducer = createReducer( trimNotifications(state); }) .addCase(processNewNotificationForGroups.fulfilled, (state, action) => { - const notification = action.payload; - if (notification) { + if (action.payload) { + const { notification, groupedTypes } = action.payload; + processNewNotification( usePendingItems ? state.pendingGroups : state.groups, notification, + groupedTypes, ); updateLastReadId(state); trimNotifications(state); @@ -551,7 +562,10 @@ export const notificationGroupsReducer = createReducer( compareId(state.lastReadId, mostRecentGroup.page_max_id) < 0 ) state.lastReadId = mostRecentGroup.page_max_id; - commitLastReadId(state); + + // We don't call `commitLastReadId`, because that is conditional + // and we want to unconditionally update the state instead. + state.readMarkerId = state.lastReadId; }) .addCase(fetchMarkers.fulfilled, (state, action) => { if ( 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/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js index 622f5e8e884bbd..c99a619b52dc69 100644 --- a/app/javascript/mastodon/reducers/notifications.js +++ b/app/javascript/mastodon/reducers/notifications.js @@ -298,9 +298,10 @@ export default function notifications(state = initialState, action) { return action.payload.timeline === 'home' ? state.update(action.payload.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) : state; - case NOTIFICATIONS_MARK_AS_READ: + case NOTIFICATIONS_MARK_AS_READ: { const lastNotification = state.get('items').find(item => item !== null); return lastNotification ? recountUnread(state, lastNotification.get('id')) : state; + } case NOTIFICATIONS_SET_BROWSER_SUPPORT: return state.set('browserSupport', action.value); case NOTIFICATIONS_SET_BROWSER_PERMISSION: diff --git a/app/javascript/mastodon/reducers/search.js b/app/javascript/mastodon/reducers/search.js index 7828d49eeedd9a..7de1c65c07a295 100644 --- a/app/javascript/mastodon/reducers/search.js +++ b/app/javascript/mastodon/reducers/search.js @@ -72,9 +72,10 @@ export default function search(state = initialState, action) { }); case SEARCH_EXPAND_REQUEST: return state.set('type', action.searchType).set('isLoading', true); - case SEARCH_EXPAND_SUCCESS: + case SEARCH_EXPAND_SUCCESS: { const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id); return state.updateIn(['results', action.searchType], list => list.union(results)).set('isLoading', false); + } case SEARCH_HISTORY_UPDATE: return state.set('recent', ImmutableOrderedSet(fromJS(action.recent))); default: diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index e5ff2ff9104615..fc02ac71860dc8 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -78,6 +78,10 @@ const initialState = ImmutableMap({ 'admin.sign_up': true, 'admin.report': true, }), + + group: ImmutableMap({ + follow: true + }), }), firehose: ImmutableMap({ diff --git a/app/javascript/mastodon/selectors/filters.ts b/app/javascript/mastodon/selectors/filters.ts new file mode 100644 index 00000000000000..f84d01216adf97 --- /dev/null +++ b/app/javascript/mastodon/selectors/filters.ts @@ -0,0 +1,50 @@ +import { createSelector } from '@reduxjs/toolkit'; + +import type { RootState } from 'mastodon/store'; +import { toServerSideType } from 'mastodon/utils/filters'; + +// TODO: move to `app/javascript/mastodon/models` and use more globally +type Filter = Immutable.Map; + +// TODO: move to `app/javascript/mastodon/models` and use more globally +type FilterResult = Immutable.Map; + +export const getFilters = createSelector( + [ + (state: RootState) => state.filters as Immutable.Map, + (_, { contextType }: { contextType: string }) => contextType, + ], + (filters, contextType) => { + if (!contextType) { + return null; + } + + const now = new Date(); + const serverSideType = toServerSideType(contextType); + + return filters.filter((filter) => { + const context = filter.get('context') as Immutable.List; + const expiration = filter.get('expires_at') as Date | null; + return ( + context.includes(serverSideType) && + (expiration === null || expiration > now) + ); + }); + }, +); + +export const getStatusHidden = ( + state: RootState, + { id, contextType }: { id: string; contextType: string }, +) => { + const filters = getFilters(state, { contextType }); + if (filters === null) return false; + + const filtered = state.statuses.getIn([id, 'filtered']) as + | Immutable.List + | undefined; + return filtered?.some( + (result) => + filters.getIn([result.get('filter'), 'filter_action']) === 'hide', + ); +}; diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index 10e1b167cacee1..345ceac49a665c 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -1,22 +1,11 @@ import { createSelector } from '@reduxjs/toolkit'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; -import { toServerSideType } from 'mastodon/utils/filters'; - import { me } from '../initial_state'; -export { makeGetAccount } from "./accounts"; - -const getFilters = createSelector([state => state.get('filters'), (_, { contextType }) => contextType], (filters, contextType) => { - if (!contextType) { - return null; - } +import { getFilters } from './filters'; - const now = new Date(); - const serverSideType = toServerSideType(contextType); - - return filters.filter(filter => filter.get('context').includes(serverSideType) && (filter.get('expires_at') === null || filter.get('expires_at') > now)); -}); +export { makeGetAccount } from "./accounts"; export const makeGetStatus = () => { return createSelector( diff --git a/app/javascript/mastodon/selectors/settings.ts b/app/javascript/mastodon/selectors/settings.ts index e722ad09112034..ca3437416746fc 100644 --- a/app/javascript/mastodon/selectors/settings.ts +++ b/app/javascript/mastodon/selectors/settings.ts @@ -52,4 +52,7 @@ export const selectSettingsNotificationsMinimizeFilteredBanner = ( ) => state.settings.getIn(['notifications', 'minimizeFilteredBanner']) as boolean; +export const selectSettingsNotificationsGroupFollows = (state: RootState) => + state.settings.getIn(['notifications', 'group', 'follow']) as boolean; + /* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ diff --git a/app/javascript/mastodon/service_worker/web_push_locales.js b/app/javascript/mastodon/service_worker/web_push_locales.js index 89ae20007bba39..3e39c9a4edf890 100644 --- a/app/javascript/mastodon/service_worker/web_push_locales.js +++ b/app/javascript/mastodon/service_worker/web_push_locales.js @@ -6,6 +6,12 @@ const fs = require('fs'); const path = require('path'); +const { defineMessages } = require('react-intl'); + +const messages = defineMessages({ + mentioned_you: { id: 'notification.mentioned_you', defaultMessage: '{name} mentioned you' }, +}); + const filtered = {}; const filenames = fs.readdirSync(path.resolve(__dirname, '../locales')); @@ -20,7 +26,7 @@ filenames.forEach(filename => { 'notification.favourite': full['notification.favourite'] || '', 'notification.follow': full['notification.follow'] || '', 'notification.follow_request': full['notification.follow_request'] || '', - 'notification.mention': full['notification.mention'] || '', + 'notification.mention': full[messages.mentioned_you.id] || '', 'notification.reblog': full['notification.reblog'] || '', 'notification.poll': full['notification.poll'] || '', 'notification.status': full['notification.status'] || '', 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/breaking_news-fill.svg b/app/javascript/material-icons/400-24px/breaking_news-fill.svg new file mode 100644 index 00000000000000..633ca48d57d6b4 --- /dev/null +++ b/app/javascript/material-icons/400-24px/breaking_news-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/breaking_news.svg b/app/javascript/material-icons/400-24px/breaking_news.svg index d7dd0c12f47fec..c043f11a8b0207 100644 --- a/app/javascript/material-icons/400-24px/breaking_news.svg +++ b/app/javascript/material-icons/400-24px/breaking_news.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/captive_portal-fill.svg b/app/javascript/material-icons/400-24px/captive_portal-fill.svg new file mode 100644 index 00000000000000..5c0b26fb647b18 --- /dev/null +++ b/app/javascript/material-icons/400-24px/captive_portal-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/captive_portal.svg b/app/javascript/material-icons/400-24px/captive_portal.svg index 1f0f09c7734912..5c0b26fb647b18 100644 --- a/app/javascript/material-icons/400-24px/captive_portal.svg +++ b/app/javascript/material-icons/400-24px/captive_portal.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/chat_bubble-fill.svg b/app/javascript/material-icons/400-24px/chat_bubble-fill.svg new file mode 100644 index 00000000000000..b47338a6c9c9ab --- /dev/null +++ b/app/javascript/material-icons/400-24px/chat_bubble-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/chat_bubble.svg b/app/javascript/material-icons/400-24px/chat_bubble.svg index 7d210b460865ee..05d976d242d866 100644 --- a/app/javascript/material-icons/400-24px/chat_bubble.svg +++ b/app/javascript/material-icons/400-24px/chat_bubble.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud-fill.svg b/app/javascript/material-icons/400-24px/cloud-fill.svg new file mode 100644 index 00000000000000..d049a74c0191e3 --- /dev/null +++ b/app/javascript/material-icons/400-24px/cloud-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud.svg b/app/javascript/material-icons/400-24px/cloud.svg index 75b4e957fc416a..a36bddda918e0f 100644 --- a/app/javascript/material-icons/400-24px/cloud.svg +++ b/app/javascript/material-icons/400-24px/cloud.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_download-fill.svg b/app/javascript/material-icons/400-24px/cloud_download-fill.svg new file mode 100644 index 00000000000000..c55d49f7e5c0dd --- /dev/null +++ b/app/javascript/material-icons/400-24px/cloud_download-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_download.svg b/app/javascript/material-icons/400-24px/cloud_download.svg index 2fc3717ff9e35e..8e9314800cca76 100644 --- a/app/javascript/material-icons/400-24px/cloud_download.svg +++ b/app/javascript/material-icons/400-24px/cloud_download.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_sync-fill.svg b/app/javascript/material-icons/400-24px/cloud_sync-fill.svg new file mode 100644 index 00000000000000..0c648e19e4f36b --- /dev/null +++ b/app/javascript/material-icons/400-24px/cloud_sync-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_sync.svg b/app/javascript/material-icons/400-24px/cloud_sync.svg index dbf6adc0001ada..461796e323ff9a 100644 --- a/app/javascript/material-icons/400-24px/cloud_sync.svg +++ b/app/javascript/material-icons/400-24px/cloud_sync.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_upload-fill.svg b/app/javascript/material-icons/400-24px/cloud_upload-fill.svg new file mode 100644 index 00000000000000..66a7bb22d3511e --- /dev/null +++ b/app/javascript/material-icons/400-24px/cloud_upload-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/cloud_upload.svg b/app/javascript/material-icons/400-24px/cloud_upload.svg index 5e1a4b9aef684f..94968cb94713bf 100644 --- a/app/javascript/material-icons/400-24px/cloud_upload.svg +++ b/app/javascript/material-icons/400-24px/cloud_upload.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/code.svg b/app/javascript/material-icons/400-24px/code.svg index 5bdc338f7f5bc6..8ef5c55cd48598 100644 --- a/app/javascript/material-icons/400-24px/code.svg +++ b/app/javascript/material-icons/400-24px/code.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/computer-fill.svg b/app/javascript/material-icons/400-24px/computer-fill.svg new file mode 100644 index 00000000000000..91295d68463510 --- /dev/null +++ b/app/javascript/material-icons/400-24px/computer-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/computer.svg b/app/javascript/material-icons/400-24px/computer.svg index 8c5bd9110e1d23..b8af5d46447944 100644 --- a/app/javascript/material-icons/400-24px/computer.svg +++ b/app/javascript/material-icons/400-24px/computer.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/contact_mail-fill.svg b/app/javascript/material-icons/400-24px/contact_mail-fill.svg new file mode 100644 index 00000000000000..c42c799955cc9a --- /dev/null +++ b/app/javascript/material-icons/400-24px/contact_mail-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/contact_mail.svg b/app/javascript/material-icons/400-24px/contact_mail.svg index 1ae26cc4d157ed..4547c48ec5b7b4 100644 --- a/app/javascript/material-icons/400-24px/contact_mail.svg +++ b/app/javascript/material-icons/400-24px/contact_mail.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/database-fill.svg b/app/javascript/material-icons/400-24px/database-fill.svg new file mode 100644 index 00000000000000..3520f6961446e6 --- /dev/null +++ b/app/javascript/material-icons/400-24px/database-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/database.svg b/app/javascript/material-icons/400-24px/database.svg index 54ca2f4e560b2e..a3bc2bfbc24474 100644 --- a/app/javascript/material-icons/400-24px/database.svg +++ b/app/javascript/material-icons/400-24px/database.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/diamond-fill.svg b/app/javascript/material-icons/400-24px/diamond-fill.svg new file mode 100644 index 00000000000000..474968ad6f8cdf --- /dev/null +++ b/app/javascript/material-icons/400-24px/diamond-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/diamond.svg b/app/javascript/material-icons/400-24px/diamond.svg index 26f4814b443b95..b604492fa8bf7c 100644 --- a/app/javascript/material-icons/400-24px/diamond.svg +++ b/app/javascript/material-icons/400-24px/diamond.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/filter_alt-fill.svg b/app/javascript/material-icons/400-24px/filter_alt-fill.svg new file mode 100644 index 00000000000000..ec1d90bba6bbd5 --- /dev/null +++ b/app/javascript/material-icons/400-24px/filter_alt-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/filter_alt.svg b/app/javascript/material-icons/400-24px/filter_alt.svg index 0294cf1da53ac0..e4af9efd5d4d67 100644 --- a/app/javascript/material-icons/400-24px/filter_alt.svg +++ b/app/javascript/material-icons/400-24px/filter_alt.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/groups-fill.svg b/app/javascript/material-icons/400-24px/groups-fill.svg new file mode 100644 index 00000000000000..754eb0946c291c --- /dev/null +++ b/app/javascript/material-icons/400-24px/groups-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/groups.svg b/app/javascript/material-icons/400-24px/groups.svg index 0e795eb301d89d..998ff03729bd58 100644 --- a/app/javascript/material-icons/400-24px/groups.svg +++ b/app/javascript/material-icons/400-24px/groups.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/hide_source-fill.svg b/app/javascript/material-icons/400-24px/hide_source-fill.svg new file mode 100644 index 00000000000000..959631bc1aa150 --- /dev/null +++ b/app/javascript/material-icons/400-24px/hide_source-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/hide_source.svg b/app/javascript/material-icons/400-24px/hide_source.svg index d103ed770a5d6b..09633cef8c83b6 100644 --- a/app/javascript/material-icons/400-24px/hide_source.svg +++ b/app/javascript/material-icons/400-24px/hide_source.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/inbox-fill.svg b/app/javascript/material-icons/400-24px/inbox-fill.svg new file mode 100644 index 00000000000000..15ae2d8f3c4068 --- /dev/null +++ b/app/javascript/material-icons/400-24px/inbox-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/inbox.svg b/app/javascript/material-icons/400-24px/inbox.svg index 427817958c169a..32c727e8104990 100644 --- a/app/javascript/material-icons/400-24px/inbox.svg +++ b/app/javascript/material-icons/400-24px/inbox.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/list-fill.svg b/app/javascript/material-icons/400-24px/list-fill.svg new file mode 100644 index 00000000000000..c9cbe35eb52fa9 --- /dev/null +++ b/app/javascript/material-icons/400-24px/list-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/list.svg b/app/javascript/material-icons/400-24px/list.svg index 457a820ab1781b..c9cbe35eb52fa9 100644 --- a/app/javascript/material-icons/400-24px/list.svg +++ b/app/javascript/material-icons/400-24px/list.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/mail.svg b/app/javascript/material-icons/400-24px/mail.svg index a92ea7b198a82f..15e1d12d4e1a21 100644 --- a/app/javascript/material-icons/400-24px/mail.svg +++ b/app/javascript/material-icons/400-24px/mail.svg @@ -1 +1 @@ - \ No newline at end of file + \ 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/mood-fill.svg b/app/javascript/material-icons/400-24px/mood-fill.svg new file mode 100644 index 00000000000000..9480d0fb92aaa3 --- /dev/null +++ b/app/javascript/material-icons/400-24px/mood-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/mood.svg b/app/javascript/material-icons/400-24px/mood.svg index 27b3534244888c..46cafa76808008 100644 --- a/app/javascript/material-icons/400-24px/mood.svg +++ b/app/javascript/material-icons/400-24px/mood.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/report-fill.svg b/app/javascript/material-icons/400-24px/report-fill.svg new file mode 100644 index 00000000000000..50c638869d69cd --- /dev/null +++ b/app/javascript/material-icons/400-24px/report-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/report.svg b/app/javascript/material-icons/400-24px/report.svg index f281f0e1fa8f01..b08b5a1c987d5a 100644 --- a/app/javascript/material-icons/400-24px/report.svg +++ b/app/javascript/material-icons/400-24px/report.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/safety_check-fill.svg b/app/javascript/material-icons/400-24px/safety_check-fill.svg new file mode 100644 index 00000000000000..b38091a8ec4f2a --- /dev/null +++ b/app/javascript/material-icons/400-24px/safety_check-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/safety_check.svg b/app/javascript/material-icons/400-24px/safety_check.svg index f4eab46fb75b82..87bdba21fe3444 100644 --- a/app/javascript/material-icons/400-24px/safety_check.svg +++ b/app/javascript/material-icons/400-24px/safety_check.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/material-icons/400-24px/speed-fill.svg b/app/javascript/material-icons/400-24px/speed-fill.svg new file mode 100644 index 00000000000000..dca22ac521e3f0 --- /dev/null +++ b/app/javascript/material-icons/400-24px/speed-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/speed.svg b/app/javascript/material-icons/400-24px/speed.svg index ceb855c684f8c3..0837877f42f2f8 100644 --- a/app/javascript/material-icons/400-24px/speed.svg +++ b/app/javascript/material-icons/400-24px/speed.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/trending_up-fill.svg b/app/javascript/material-icons/400-24px/trending_up-fill.svg new file mode 100644 index 00000000000000..cd0e368964ec68 --- /dev/null +++ b/app/javascript/material-icons/400-24px/trending_up-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/trending_up.svg b/app/javascript/material-icons/400-24px/trending_up.svg index 06f9ba20639860..cd0e368964ec68 100644 --- a/app/javascript/material-icons/400-24px/trending_up.svg +++ b/app/javascript/material-icons/400-24px/trending_up.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/admin.scss b/app/javascript/styles/mastodon/admin.scss index 4d217cf5b7c357..93b78f605eef40 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -226,6 +226,10 @@ $content-width: 840px; gap: 5px; white-space: nowrap; + @media screen and (max-width: $mobile-breakpoint) { + flex: 1 0 50%; + } + &:hover, &:focus, &:active { @@ -1041,6 +1045,12 @@ a.name-tag, color: var(--user-role-accent); } +.applications-list { + .icon { + vertical-align: middle; + } +} + .announcements-list, .filters-list { border: 1px solid var(--background-border-color); @@ -1070,6 +1080,10 @@ a.name-tag, } } + .icon { + vertical-align: middle; + } + a.announcements-list__item__title { &:hover, &:focus, diff --git a/app/javascript/styles/mastodon/basics.scss b/app/javascript/styles/mastodon/basics.scss index 1f961cb9e1279d..1a74d8d52d3c24 100644 --- a/app/javascript/styles/mastodon/basics.scss +++ b/app/javascript/styles/mastodon/basics.scss @@ -141,6 +141,7 @@ body { width: 100%; height: auto; margin-top: -120px; + margin-bottom: -45px; } } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index c99674a0cbc991..c9f46e22cf2ea5 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; @@ -652,19 +669,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; @@ -685,8 +722,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; @@ -1481,6 +1517,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); } @@ -2048,7 +2093,6 @@ body > [data-popper-placement] { display: block; position: relative; border-radius: var(--avatar-border-radius); - background-color: var(--surface-background-color); img { width: 100%; @@ -2058,7 +2102,11 @@ body > [data-popper-placement] { display: inline-block; // to not show broken images } - &-inline { + &--loading { + background-color: var(--surface-background-color); + } + + &--inline { display: inline-block; vertical-align: middle; margin-inline-end: 5px; @@ -2724,7 +2772,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; @@ -2831,7 +2879,7 @@ $ui-header-logo-wordmark-width: 99px; } .column { - width: 400px; + width: clamp(380px, calc((100% - 350px) / 4), 400px); position: relative; box-sizing: border-box; display: flex; @@ -3493,12 +3541,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 { @@ -3509,6 +3559,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, @@ -3550,6 +3630,7 @@ $ui-header-logo-wordmark-width: 99px; overflow-y: auto; width: 100%; height: 100%; + z-index: 0; } .drawer__inner__mastodon { @@ -3872,22 +3953,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; @@ -5941,6 +6006,7 @@ a.status-card { .icon { width: 24px; height: 24px; + filter: var(--overlay-icon-shadow); } &:hover, @@ -6035,6 +6101,10 @@ a.status-card { .icon-button { color: $white; + .icon { + filter: var(--overlay-icon-shadow); + } + &:hover, &:focus, &:active { @@ -6093,6 +6163,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; @@ -6369,6 +6440,14 @@ a.status-card { display: flex; gap: 16px; align-items: center; + + strong { + font-weight: 700; + } + } + + &--deemphasized { + color: $secondary-text-color; } &__icon { @@ -7050,7 +7129,7 @@ a.status-card { .media-gallery__actions { position: absolute; - bottom: 6px; + top: 6px; inset-inline-end: 6px; display: flex; gap: 2px; @@ -7073,17 +7152,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; @@ -7091,8 +7170,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 { @@ -7165,35 +7277,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; @@ -7201,26 +7313,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; @@ -7235,6 +7347,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; @@ -7243,15 +7358,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 { @@ -7271,7 +7415,7 @@ a.status-card { position: absolute; top: 0; inset-inline-start: 0; - z-index: 0; + z-index: -2; background: $base-overlay-background; &--hidden { @@ -7284,22 +7428,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, @@ -7322,6 +7460,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; @@ -7378,6 +7518,7 @@ a.status-card { .video-player__controls { padding-top: 10px; background: transparent; + z-index: 1; } } @@ -7391,19 +7532,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 { @@ -7422,7 +7562,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; @@ -7737,26 +7877,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; } } @@ -8019,18 +8149,50 @@ noscript { background: rgba($base-overlay-background, 0.5); } +.list-adder, .list-editor { - background: $ui-base-color; + backdrop-filter: var(--background-filter); + background: var(--modal-background-color); + border: 1px solid var(--modal-border-color); flex-direction: column; border-radius: 8px; - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); width: 380px; overflow: hidden; @media screen and (width <= 420px) { width: 90%; } +} + +.list-adder { + &__lists { + height: 50vh; + border-radius: 0 0 8px 8px; + overflow-y: auto; + } + + .list { + padding: 10px; + border-bottom: 1px solid var(--background-border-color); + } + + .list__wrapper { + display: flex; + } + .list__display-name { + flex: 1 1 auto; + overflow: hidden; + text-decoration: none; + font-size: 16px; + padding: 10px; + display: flex; + align-items: center; + gap: 4px; + } +} + +.list-editor { h4 { padding: 15px 0; background: lighten($ui-base-color, 13%); @@ -8042,12 +8204,10 @@ noscript { .drawer__pager { height: 50vh; - border-radius: 4px; + border: 0; } .drawer__inner { - border-radius: 0 0 8px 8px; - &.backdrop { width: calc(100% - 60px); box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); @@ -8056,6 +8216,7 @@ noscript { } &__accounts { + background: unset; overflow-y: auto; } @@ -8074,47 +8235,6 @@ noscript { } } -.list-adder { - background: $ui-base-color; - flex-direction: column; - border-radius: 8px; - box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); - width: 380px; - overflow: hidden; - - @media screen and (width <= 420px) { - width: 90%; - } - - &__account { - background: lighten($ui-base-color, 13%); - } - - &__lists { - background: lighten($ui-base-color, 13%); - height: 50vh; - border-radius: 0 0 8px 8px; - overflow-y: auto; - } - - .list { - padding: 10px; - border-bottom: 1px solid var(--background-border-color); - } - - .list__wrapper { - display: flex; - } - - .list__display-name { - flex: 1 1 auto; - overflow: hidden; - text-decoration: none; - font-size: 16px; - padding: 10px; - } -} - .focal-point { position: relative; cursor: move; @@ -10662,6 +10782,7 @@ noscript { gap: 8px; .logo { + width: 16px; height: 16px; color: $darker-text-color; } @@ -10844,21 +10965,17 @@ noscript { color: $darker-text-color; -webkit-line-clamp: 4; -webkit-box-orient: vertical; - max-height: 4 * 22px; + max-height: none; overflow: hidden; - p { - display: none; - - &:first-child { - display: initial; - } - } - p, a { color: inherit; } + + p { + margin-bottom: 8px; + } } .reply-indicator__attachments { 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..641fb19a577358 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -23,6 +23,8 @@ code { position: relative; overflow: hidden; height: 160px; + max-width: 566px; + margin-inline: auto; &::after { content: ''; @@ -312,6 +314,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/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index e4e299ff82d9c2..0a05ce7c62d72a 100644 --- a/app/javascript/styles/mastodon/rtl.scss +++ b/app/javascript/styles/mastodon/rtl.scss @@ -35,6 +35,10 @@ body.rtl { direction: rtl; } + .column-back-button__icon { + transform: scale(-1, 1); + } + .simple_form select { background: $ui-base-color url("data:image/svg+xml;utf8,") diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss index 2becd85bc667ef..0cbf5c1d554921 100644 --- a/app/javascript/styles/mastodon/tables.scss +++ b/app/javascript/styles/mastodon/tables.scss @@ -137,6 +137,7 @@ a.table-action-link { padding: 0 10px; color: $darker-text-color; font-weight: 500; + white-space: nowrap; &:hover { color: $highlight-text-color; @@ -359,6 +360,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..cbc5b309b426e3 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -42,6 +42,7 @@ def audience_cc def process_status @tags = [] @mentions = [] + @unresolved_mentions = [] @silenced_account_ids = [] @params = {} @@ -55,6 +56,7 @@ def process_status end resolve_thread(@status) + resolve_unresolved_mentions(@status) fetch_replies(@status) distribute forward_for_reply @@ -197,6 +199,8 @@ def process_mention(tag) return if account.nil? @mentions << Mention.new(account: account, silent: false) + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS + @unresolved_mentions << tag['href'] end def process_emoji(tag) @@ -246,7 +250,7 @@ def process_attachments media_attachment.download_file! media_attachment.download_thumbnail! media_attachment.save - rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) rescue Seahorse::Client::NetworkingError => e Rails.logger.warn "Error storing media attachment: #{e}" @@ -301,6 +305,12 @@ def resolve_thread(status) ThreadResolveWorker.perform_async(status.id, in_reply_to_uri, { 'request_id' => @options[:request_id] }) end + def resolve_unresolved_mentions(status) + @unresolved_mentions.uniq.each do |uri| + MentionResolveWorker.perform_in(rand(30...600).seconds, status.id, uri, { 'request_id' => @options[:request_id] }) + end + end + def fetch_replies(status) collection = @object['replies'] return if collection.blank? @@ -342,7 +352,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/content_security_policy.rb b/app/lib/content_security_policy.rb index a6901a6757dd8f..2e6c43be8f3509 100644 --- a/app/lib/content_security_policy.rb +++ b/app/lib/content_security_policy.rb @@ -40,7 +40,7 @@ def url_from_configured_asset_host end def cdn_host_value - s3_alias_host || s3_cloudfront_host || azure_alias_host || s3_hostname_host + s3_alias_host || s3_cloudfront_host || azure_alias_host || s3_hostname_host || swift_object_url end def paperclip_root_url @@ -76,6 +76,14 @@ def s3_hostname_host host_to_url ENV.fetch('S3_HOSTNAME', nil) end + def swift_object_url + url = ENV.fetch('SWIFT_OBJECT_URL', nil) + return if url.blank? || !url.start_with?('https://') + + url += '/' unless url.end_with?('/') + url + end + def uri_from_configuration_and_string(host_string) Addressable::URI.parse("#{host_protocol}://#{host_string}").tap do |uri| uri.path += '/' unless uri.path.blank? || uri.path.end_with?('/') 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/lib/vacuum/imports_vacuum.rb b/app/lib/vacuum/imports_vacuum.rb index 700bd81847f4ac..b67865194f39a9 100644 --- a/app/lib/vacuum/imports_vacuum.rb +++ b/app/lib/vacuum/imports_vacuum.rb @@ -9,10 +9,10 @@ def perform private def clean_unconfirmed_imports! - BulkImport.state_unconfirmed.where(created_at: ..10.minutes.ago).reorder(nil).in_batches.delete_all + BulkImport.state_unconfirmed.where(created_at: ..10.minutes.ago).in_batches.delete_all end def clean_old_imports! - BulkImport.where(created_at: ..1.week.ago).reorder(nil).in_batches.delete_all + BulkImport.where(created_at: ..1.week.ago).in_batches.delete_all end end diff --git a/app/lib/web_push_request.rb b/app/lib/web_push_request.rb new file mode 100644 index 00000000000000..a43e22480e12a2 --- /dev/null +++ b/app/lib/web_push_request.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +class WebPushRequest + SIGNATURE_ALGORITHM = 'p256ecdsa' + AUTH_HEADER = 'WebPush' + PAYLOAD_EXPIRATION = 24.hours + JWT_ALGORITHM = 'ES256' + JWT_TYPE = 'JWT' + + attr_reader :web_push_subscription + + delegate( + :endpoint, + :key_auth, + :key_p256dh, + to: :web_push_subscription + ) + + def initialize(web_push_subscription) + @web_push_subscription = web_push_subscription + end + + def audience + @audience ||= Addressable::URI.parse(endpoint).normalized_site + end + + def authorization_header + [AUTH_HEADER, encoded_json_web_token].join(' ') + end + + def crypto_key_header + [SIGNATURE_ALGORITHM, vapid_key.public_key_for_push_header].join('=') + end + + def encrypt(payload) + Webpush::Encryption.encrypt(payload, key_p256dh, key_auth) + end + + private + + def encoded_json_web_token + JWT.encode( + web_token_payload, + vapid_key.curve, + JWT_ALGORITHM, + typ: JWT_TYPE + ) + end + + def web_token_payload + { + aud: audience, + exp: PAYLOAD_EXPIRATION.from_now.to_i, + sub: payload_subject, + } + end + + def payload_subject + [:mailto, contact_email].join(':') + end + + def vapid_key + @vapid_key ||= Webpush::VapidKey.from_keys( + Rails.configuration.x.vapid_public_key, + Rails.configuration.x.vapid_private_key + ) + end + + def contact_email + @contact_email ||= ::Setting.site_contact_email + 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..a20992dcb56f19 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}>", @@ -84,7 +86,7 @@ def set_list_headers! end def thread_by_conversation! - return if @status.conversation.nil? + return if @status&.conversation.nil? conversation_message_id = "" diff --git a/app/models/account.rb b/app/models/account.rb index c5d98ee7a4fe31..5178f59a5737ad 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -69,8 +69,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{(? { where(domain: nil) } scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) } scope :silenced, -> { where.not(silenced_at: nil) } - scope :suspended, -> { where.not(suspended_at: nil) } scope :sensitized, -> { where.not(sensitized_at: nil) } - scope :without_suspended, -> { where(suspended_at: nil) } scope :without_silenced, -> { where(silenced_at: nil) } scope :without_instance_actor, -> { where.not(id: INSTANCE_ACTOR_ID) } scope :recent, -> { reorder(id: :desc) } @@ -257,41 +256,6 @@ def unsilence! update!(silenced_at: nil) end - def suspended? - suspended_at.present? && !instance_actor? - end - - def suspended_locally? - suspended? && suspension_origin_local? - end - - def suspended_permanently? - suspended? && deletion_request.nil? - end - - def suspended_temporarily? - suspended? && deletion_request.present? - end - - alias unavailable? suspended? - alias permanently_unavailable? suspended_permanently? - - def suspend!(date: Time.now.utc, origin: :local, block_email: true) - transaction do - create_deletion_request! - update!(suspended_at: date, suspension_origin: origin) - create_canonical_email_block! if block_email - end - end - - def unsuspend! - transaction do - deletion_request&.destroy! - update!(suspended_at: nil, suspension_origin: nil) - destroy_canonical_email_block! - end - end - def sensitized? sensitized_at.present? end diff --git a/app/models/account_alias.rb b/app/models/account_alias.rb index 3b75919afe2969..41623ddedb8a1f 100644 --- a/app/models/account_alias.rb +++ b/app/models/account_alias.rb @@ -35,7 +35,7 @@ def pretty_acct def set_uri target_account = ResolveAccountService.new.call(acct) self.uri = ActivityPub::TagManager.instance.uri_for(target_account) unless target_account.nil? - rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error + rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::Error # Validation will take care of it end diff --git a/app/models/account_filter.rb b/app/models/account_filter.rb index 42b1c49538b0a5..e2f359a8c32ef6 100644 --- a/app/models/account_filter.rb +++ b/app/models/account_filter.rb @@ -21,7 +21,7 @@ def initialize(params) end def results - scope = Account.includes(:account_stat, user: [:ips, :invite_request]).without_instance_actor.reorder(nil) + scope = Account.includes(:account_stat, user: [:ips, :invite_request]).without_instance_actor relevant_params.each do |key, value| next if key.to_s == 'page' diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb index 7a01e250e2c213..7bda388f2a81a3 100644 --- a/app/models/account_migration.rb +++ b/app/models/account_migration.rb @@ -61,7 +61,7 @@ def cooldown_at def set_target_account self.target_account = ResolveAccountService.new.call(acct, skip_cache: true) - rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError + rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::Error, Addressable::URI::InvalidURIError # Validation will take care of it end diff --git a/app/models/admin/tag_filter.rb b/app/models/admin/tag_filter.rb index 6149c52175884b..5e75757b2374a7 100644 --- a/app/models/admin/tag_filter.rb +++ b/app/models/admin/tag_filter.rb @@ -14,7 +14,7 @@ def initialize(params) end def results - scope = Tag.reorder(nil) + scope = Tag.all params.each do |key, value| next if key == :page diff --git a/app/models/concerns/account/avatar.rb b/app/models/concerns/account/avatar.rb index 39f599db182275..5ca8fa862f9495 100644 --- a/app/models/concerns/account/avatar.rb +++ b/app/models/concerns/account/avatar.rb @@ -6,10 +6,13 @@ module Account::Avatar IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze LIMIT = 2.megabytes + AVATAR_DIMENSIONS = [400, 400].freeze + AVATAR_GEOMETRY = [AVATAR_DIMENSIONS.first, AVATAR_DIMENSIONS.last].join('x') + class_methods do def avatar_styles(file) - styles = { original: { geometry: '400x400#', file_geometry_parser: FastGeometryParser } } - styles[:static] = { geometry: '400x400#', format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif' + styles = { original: { geometry: "#{AVATAR_GEOMETRY}#", file_geometry_parser: FastGeometryParser } } + styles[:static] = { geometry: "#{AVATAR_GEOMETRY}#", format: 'png', convert_options: '-coalesce', file_geometry_parser: FastGeometryParser } if file.content_type == 'image/gif' styles end diff --git a/app/models/concerns/account/header.rb b/app/models/concerns/account/header.rb index 44ae774e94d034..2a47097fcfd038 100644 --- a/app/models/concerns/account/header.rb +++ b/app/models/concerns/account/header.rb @@ -5,7 +5,10 @@ module Account::Header IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'].freeze LIMIT = 2.megabytes - MAX_PIXELS = 750_000 # 1500x500px + + HEADER_DIMENSIONS = [1500, 500].freeze + HEADER_GEOMETRY = [HEADER_DIMENSIONS.first, HEADER_DIMENSIONS.last].join('x') + MAX_PIXELS = HEADER_DIMENSIONS.first * HEADER_DIMENSIONS.last class_methods do def header_styles(file) diff --git a/app/models/concerns/account/suspensions.rb b/app/models/concerns/account/suspensions.rb new file mode 100644 index 00000000000000..c981fb5a2954cf --- /dev/null +++ b/app/models/concerns/account/suspensions.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Account::Suspensions + extend ActiveSupport::Concern + + included do + scope :suspended, -> { where.not(suspended_at: nil) } + scope :without_suspended, -> { where(suspended_at: nil) } + end + + def suspended? + suspended_at.present? && !instance_actor? + end + alias unavailable? suspended? + + def suspended_locally? + suspended? && suspension_origin_local? + end + + def suspended_permanently? + suspended? && deletion_request.nil? + end + alias permanently_unavailable? suspended_permanently? + + def suspended_temporarily? + suspended? && deletion_request.present? + end + + def suspend!(date: Time.now.utc, origin: :local, block_email: true) + transaction do + create_deletion_request! + update!(suspended_at: date, suspension_origin: origin) + create_canonical_email_block! if block_email + end + end + + def unsuspend! + transaction do + deletion_request&.destroy! + update!(suspended_at: nil, suspension_origin: nil) + destroy_canonical_email_block! + end + end +end diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index 8382c9159968d8..15133e7bde9eec 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -26,7 +26,7 @@ def remotable_attachment(attachment_name, limit, suppress_errors: true, download public_send(:"#{attachment_name}=", ResponseWithLimit.new(response, limit)) end - rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS => e Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present? raise e unless suppress_errors diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index b5d1f2e0796645..2853f6457a9b44 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -40,7 +40,9 @@ def policies if suspend? [:suspend] else - [severity.to_sym, reject_media? ? :reject_media : nil, reject_reports? ? :reject_reports : nil].reject { |policy| policy == :noop || policy.nil? } + [severity.to_sym, reject_media? ? :reject_media : nil, reject_reports? ? :reject_reports : nil] + .reject { |policy| policy == :noop } + .compact end end diff --git a/app/models/export.rb b/app/models/export.rb index 2457dcc1565ad4..6ed9f60c7c8cf4 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -55,42 +55,6 @@ def to_blocked_domains_csv end end - def total_storage - account.media_attachments.sum(:file_file_size) - end - - def total_statuses - account.statuses_count - end - - def total_bookmarks - account.bookmarks.count - end - - def total_follows - account.following_count - end - - def total_lists - account.owned_lists.count - end - - def total_followers - account.followers_count - end - - def total_blocks - account.blocking.count - end - - def total_mutes - account.muting.count - end - - def total_domain_blocks - account.domain_blocks.count - end - private def to_csv(accounts) diff --git a/app/models/follow_recommendation.rb b/app/models/follow_recommendation.rb index 7ac9e6dfb95743..0435437a814baf 100644 --- a/app/models/follow_recommendation.rb +++ b/app/models/follow_recommendation.rb @@ -18,5 +18,6 @@ class FollowRecommendation < ApplicationRecord belongs_to :account_summary, foreign_key: :account_id, inverse_of: false belongs_to :account - scope :localized, ->(locale) { joins(:account_summary).merge(AccountSummary.localized(locale)) } + scope :unsupressed, -> { where.not(FollowRecommendationSuppression.where(FollowRecommendationSuppression.arel_table[:account_id].eq(arel_table[:account_id])).select(1).arel.exists) } + scope :localized, ->(locale) { unsupressed.joins(:account_summary).merge(AccountSummary.localized(locale)) } end diff --git a/app/models/follow_recommendation_filter.rb b/app/models/follow_recommendation_filter.rb index 62a02eba5ae5c5..f3b0fd319bec2e 100644 --- a/app/models/follow_recommendation_filter.rb +++ b/app/models/follow_recommendation_filter.rb @@ -11,7 +11,7 @@ class FollowRecommendationFilter attr_reader :params, :language def initialize(params) - @language = params.delete('language') || I18n.locale + @language = usable_language(params.delete('language') || I18n.locale) @params = params end @@ -22,4 +22,15 @@ def results Account.includes(:account_stat).joins(:follow_recommendation).merge(FollowRecommendation.localized(@language).order(rank: :desc)) end end + + private + + def usable_language(locale) + return locale if Trends.available_locales.include?(locale) + + locale = locale.to_s.split(/[_-]/).first + return locale if Trends.available_locales.include?(locale) + + nil + end end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 7dde2fc3141709..32a649af40421b 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -88,6 +88,8 @@ class Form::AdminSettings authorized_fetch: :authorized_fetch_mode?, }.freeze + DESCRIPTION_LIMIT = 200 + attr_accessor(*KEYS) validates :registrations_mode, inclusion: { in: %w(open approved none) }, if: -> { 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/form/redirect.rb b/app/models/form/redirect.rb index 3cd5731e6d6e25..c5b3c1f8f3906c 100644 --- a/app/models/form/redirect.rb +++ b/app/models/form/redirect.rb @@ -32,7 +32,7 @@ def acct=(val) def set_target_account @target_account = ResolveAccountService.new.call(acct, skip_cache: true) - rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError + rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::Error, Addressable::URI::InvalidURIError # Validation will take care of it end 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/models/notification_policy.rb b/app/models/notification_policy.rb index 3b16f33d88155a..d22f871a37b7bb 100644 --- a/app/models/notification_policy.rb +++ b/app/models/notification_policy.rb @@ -62,6 +62,6 @@ def filter_private_mentions=(value) private def pending_notification_requests - @pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) + @pending_notification_requests ||= notification_requests.without_suspended.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) end end diff --git a/app/models/notification_request.rb b/app/models/notification_request.rb index f0778b3af32919..eb9ff93ab7223f 100644 --- a/app/models/notification_request.rb +++ b/app/models/notification_request.rb @@ -26,6 +26,8 @@ class NotificationRequest < ApplicationRecord before_save :prepare_notifications_count + scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) } + def self.preload_cache_collection(requests) cached_statuses_by_id = yield(requests.filter_map(&:last_status)).index_by(&:id) # Call cache_collection in block diff --git a/app/models/remote_follow.rb b/app/models/remote_follow.rb index 10715ac97da425..f9719b86707be7 100644 --- a/app/models/remote_follow.rb +++ b/app/models/remote_follow.rb @@ -3,7 +3,6 @@ class RemoteFollow include ActiveModel::Validations include RoutingHelper - include WebfingerHelper attr_accessor :acct, :addressable_template @@ -66,8 +65,8 @@ def redirect_uri_template end def acct_resource - @acct_resource ||= webfinger!("acct:#{acct}") - rescue Webfinger::Error, HTTP::ConnectionError + @acct_resource ||= Webfinger.new("acct:#{acct}").perform + rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS nil end diff --git a/app/models/report_filter.rb b/app/models/report_filter.rb index fd0e23cb81705d..9d2b0fb37420f5 100644 --- a/app/models/report_filter.rb +++ b/app/models/report_filter.rb @@ -18,13 +18,25 @@ def initialize(params) def results scope = Report.unresolved - params.each do |key, value| + relevant_params.each do |key, value| scope = scope.merge scope_for(key, value) end scope end + private + + def relevant_params + params.tap do |args| + args.delete(:target_origin) if origin_is_remote_and_domain_present? + end + end + + def origin_is_remote_and_domain_present? + params[:target_origin] == 'remote' && params[:by_target_domain].present? + end + def scope_for(key, value) case key.to_sym when :by_target_domain diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb index d0a77daf0a666c..8b8e533d30c980 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -28,6 +28,8 @@ class SessionActivation < ApplicationRecord before_create :assign_access_token + DEFAULT_SCOPES = %w(read write follow).freeze + class << self def active?(id) id && exists?(session_id: id) @@ -64,7 +66,7 @@ def access_token_attributes { application_id: Doorkeeper::Application.find_by(superapp: true)&.id, resource_owner_id: user_id, - scopes: 'read write follow', + scopes: DEFAULT_SCOPES.join(' '), expires_in: Doorkeeper.configuration.access_token_expires_in, use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?, } diff --git a/app/models/user.rb b/app/models/user.rb index df8444e2d3757b..e685ce65d32c06 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -71,7 +71,8 @@ class User < ApplicationRecord ACTIVE_DURATION = ENV.fetch('USER_ACTIVE_DAYS', 7).to_i.days.freeze devise :two_factor_authenticatable, - otp_secret_encryption_key: Rails.configuration.x.otp_secret + otp_secret_encryption_key: Rails.configuration.x.otp_secret, + otp_secret_length: 32 include LegacyOtpSecret # Must be after the above `devise` line in order to override the legacy method diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index ddfd08146e76ae..9d30881bf38238 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -29,26 +29,6 @@ class Web::PushSubscription < ApplicationRecord delegate :locale, to: :associated_user - def encrypt(payload) - Webpush::Encryption.encrypt(payload, key_p256dh, key_auth) - end - - def audience - @audience ||= Addressable::URI.parse(endpoint).normalized_site - end - - def crypto_key_header - p256ecdsa = vapid_key.public_key_for_push_header - - "p256ecdsa=#{p256ecdsa}" - end - - def authorization_header - jwt = JWT.encode({ aud: audience, exp: 24.hours.from_now.to_i, sub: "mailto:#{contact_email}" }, vapid_key.curve, 'ES256', typ: 'JWT') - - "WebPush #{jwt}" - end - def pushable?(notification) policy_allows_notification?(notification) && alert_enabled_for_notification_type?(notification) end @@ -92,14 +72,6 @@ def find_or_create_access_token ) end - def vapid_key - @vapid_key ||= Webpush::VapidKey.from_keys(Rails.configuration.x.vapid_public_key, Rails.configuration.x.vapid_private_key) - end - - def contact_email - @contact_email ||= ::Setting.site_contact_email - end - def alert_enabled_for_notification_type?(notification) truthy?(data&.dig('alerts', notification.type.to_s)) end 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/presenters/export_summary.rb b/app/presenters/export_summary.rb new file mode 100644 index 00000000000000..8e45aadf67dd49 --- /dev/null +++ b/app/presenters/export_summary.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +class ExportSummary + attr_reader :account, :counts + + delegate( + :blocking, + :bookmarks, + :domain_blocks, + :owned_lists, + :media_attachments, + :muting, + to: :account, + prefix: true + ) + + def initialize(account) + @account = account + @counts = populate_counts + end + + def total_blocks + counts[:blocks].value + end + + def total_bookmarks + counts[:bookmarks].value + end + + def total_domain_blocks + counts[:domain_blocks].value + end + + def total_followers + account.followers_count + end + + def total_follows + account.following_count + end + + def total_lists + counts[:owned_lists].value + end + + def total_mutes + counts[:muting].value + end + + def total_statuses + account.statuses_count + end + + def total_storage + counts[:storage].value + end + + private + + def populate_counts + { + blocks: account_blocking.async_count, + bookmarks: account_bookmarks.async_count, + domain_blocks: account_domain_blocks.async_count, + owned_lists: account_owned_lists.async_count, + muting: account_muting.async_count, + storage: account_media_attachments.async_sum(:file_file_size), + } + end +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/manifest_serializer.rb b/app/serializers/manifest_serializer.rb index cf0164c24a34b8..3496f329f82241 100644 --- a/app/serializers/manifest_serializer.rb +++ b/app/serializers/manifest_serializer.rb @@ -8,7 +8,8 @@ class ManifestSerializer < ActiveModel::Serializer attributes :id, :name, :short_name, :icons, :theme_color, :background_color, :display, :start_url, :scope, - :share_target, :shortcuts + :share_target, :shortcuts, + :prefer_related_applications, :related_applications def id # This is set to `/home` because that was the old value of `start_url` and @@ -89,4 +90,28 @@ def shortcuts }, ] end + + def prefer_related_applications + true + end + + def related_applications + [ + { + platform: 'play', + url: 'https://play.google.com/store/apps/details?id=org.joinmastodon.android', + id: 'org.joinmastodon.android', + }, + { + platform: 'itunes', + url: 'https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974', + id: 'id1571998974', + }, + { + platform: 'f-droid', + url: 'https://f-droid.org/en/packages/org.joinmastodon.android/', + id: 'org.joinmastodon.android', + }, + ] + end 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/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb index 2c372c2ec3fd84..560cf424e1539f 100644 --- a/app/services/activitypub/fetch_remote_actor_service.rb +++ b/app/services/activitypub/fetch_remote_actor_service.rb @@ -3,7 +3,6 @@ class ActivityPub::FetchRemoteActorService < BaseService include JsonLdHelper include DomainControlHelper - include WebfingerHelper class Error < StandardError; end @@ -45,7 +44,7 @@ def call(uri, prefetched_body: nil, break_on_redirect: false, only_key: false, s private def check_webfinger! - webfinger = webfinger!("acct:#{@username}@#{@domain}") + webfinger = Webfinger.new("acct:#{@username}@#{@domain}").perform confirmed_username, confirmed_domain = split_acct(webfinger.subject) if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? @@ -54,7 +53,7 @@ def check_webfinger! return end - webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") + webfinger = Webfinger.new("acct:#{confirmed_username}@#{confirmed_domain}").perform @username, @domain = split_acct(webfinger.subject) raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index a7422b5d02af7b..df6f23c0216caf 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -127,13 +127,13 @@ def set_fetchable_attributes! begin @account.avatar_remote_url = image_url('icon') || '' unless skip_download? @account.avatar = nil if @account.avatar_remote_url.blank? - rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS RedownloadAvatarWorker.perform_in(rand(30..600).seconds, @account.id) end begin @account.header_remote_url = image_url('image') || '' unless skip_download? @account.header = nil if @account.header_remote_url.blank? - rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS RedownloadHeaderWorker.perform_in(rand(30..600).seconds, @account.id) end @account.statuses_count = outbox_total_items if outbox_total_items.present? @@ -276,7 +276,7 @@ def collection_info(type) total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil has_first_page = collection.is_a?(Hash) && collection['first'].present? @collections[type] = [total_items, has_first_page] - rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::LengthValidationError + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::LengthValidationError @collections[type] = [nil, nil] end diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index 4f049a5ae940b0..cadc7d2d10e300 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -2,6 +2,7 @@ class ActivityPub::ProcessCollectionService < BaseService include JsonLdHelper + include DomainControlHelper def call(body, actor, **options) @account = actor @@ -69,6 +70,9 @@ def process_item(item) end def verify_account! + return unless @json['signature'].is_a?(Hash) + return if domain_not_allowed?(@json['signature']['creator']) + @options[:relayed_through_actor] = @account @account = ActivityPub::LinkedDataSignature.new(@json).verify_actor! @account = nil unless @account.is_a?(Account) diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 1dbed27f28db3e..141ad24e92716a 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -109,7 +109,7 @@ def download_media_files! media_attachment.download_file! if media_attachment.remote_url_previously_changed? media_attachment.download_thumbnail! if media_attachment.thumbnail_remote_url_previously_changed? media_attachment.save - rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError + rescue Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id) rescue Seahorse::Client::NetworkingError => e Rails.logger.warn "Error storing media attachment: #{e}" 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/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 7662fc1f297e03..4141fb43df5f34 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -29,7 +29,7 @@ def call(status) end attach_card if @card&.persisted? - rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Encoding::UndefinedConversionError, ActiveRecord::RecordInvalid => e + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Encoding::UndefinedConversionError, ActiveRecord::RecordInvalid => e Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" } nil end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index b69015a5e9aa6e..911950cccae2ed 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -12,7 +12,7 @@ def call(url) return if url.blank? process(url) - rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e Rails.logger.debug { "Error fetching resource #{@url}: #{e}" } nil end diff --git a/app/services/import_service.rb b/app/services/import_service.rb index 6dafb5a0bb1920..a695df2fc92746 100644 --- a/app/services/import_service.rb +++ b/app/services/import_service.rb @@ -115,7 +115,7 @@ def import_bookmarks! next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri) status || ActivityPub::FetchRemoteStatusService.new.call(uri) - rescue HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::UnexpectedResponseError nil rescue => e Rails.logger.warn "Unexpected error when importing bookmark: #{e}" 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/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index 1c4c7805f1423e..3839eb4df4aa3f 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -44,7 +44,7 @@ def scan_text! if mention_undeliverable?(mentioned_account) begin mentioned_account = ResolveAccountService.new.call(Regexp.last_match(1)) - rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::UnexpectedResponseError + rescue Webfinger::Error, *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::UnexpectedResponseError mentioned_account = nil end end diff --git a/app/services/purge_domain_service.rb b/app/services/purge_domain_service.rb index ca0f0d441fe5bb..feab8aa1dd5da2 100644 --- a/app/services/purge_domain_service.rb +++ b/app/services/purge_domain_service.rb @@ -16,12 +16,12 @@ def purge_relationship_severance_events! end def purge_accounts! - Account.remote.where(domain: @domain).reorder(nil).find_each do |account| + Account.remote.where(domain: @domain).find_each do |account| DeleteAccountService.new.call(account, reserve_username: false, skip_side_effects: true) end end def purge_emojis! - CustomEmoji.remote.where(domain: @domain).reorder(nil).find_each(&:destroy) + CustomEmoji.remote.where(domain: @domain).find_each(&:destroy) end end diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index 8a5863baba6c7f..cd96b55c740e23 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -2,7 +2,6 @@ class ResolveAccountService < BaseService include DomainControlHelper - include WebfingerHelper include Redisable include Lockable @@ -81,7 +80,7 @@ def process_options!(uri, options) end def process_webfinger!(uri) - @webfinger = webfinger!("acct:#{uri}") + @webfinger = Webfinger.new("acct:#{uri}").perform confirmed_username, confirmed_domain = split_acct(@webfinger.subject) if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? @@ -91,7 +90,7 @@ def process_webfinger!(uri) end # Account doesn't match, so it may have been redirected - @webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}") + @webfinger = Webfinger.new("acct:#{confirmed_username}@#{confirmed_domain}").perform @username, @domain = split_acct(@webfinger.subject) raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? diff --git a/app/services/software_update_check_service.rb b/app/services/software_update_check_service.rb index c8ce1753f5f6c6..24a6955b8859ac 100644 --- a/app/services/software_update_check_service.rb +++ b/app/services/software_update_check_service.rb @@ -22,7 +22,7 @@ def fetch_update_notices Request.new(:get, "#{api_url}?version=#{version}").add_headers('Accept' => 'application/json', 'User-Agent' => 'Mastodon update checker').perform do |res| return Oj.load(res.body_with_limit, mode: :strict) if res.code == 200 end - rescue HTTP::Error, OpenSSL::SSL::SSLError, Oj::ParseError + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Oj::ParseError nil end diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb index e2e076e21b9bbe..bcd4703beb0004 100644 --- a/app/services/translate_status_service.rb +++ b/app/services/translate_status_service.rb @@ -9,6 +9,8 @@ class TranslateStatusService < BaseService def call(status, target_language) @status = status @source_texts = source_texts + + target_language = target_language.split(/[_-]/).first unless target_languages.include?(target_language) @target_language = target_language raise Mastodon::NotPermittedError unless permitted? @@ -32,11 +34,15 @@ def translation_backend def permitted? return false unless @status.distributable? && TranslationService.configured? - languages[@status.language]&.include?(@target_language) + target_languages.include?(@target_language) end def languages - Rails.cache.fetch('translation_service/languages', expires_in: 7.days, race_condition_ttl: 1.hour) { TranslationService.configured.languages } + Rails.cache.fetch('translation_service/languages', expires_in: 7.days, race_condition_ttl: 1.hour) { translation_backend.languages } + end + + def target_languages + languages[@status.language] || [] end def content_hash diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index c4f4191e1f3bab..17c86426be7855 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -10,7 +10,7 @@ def call(field) return unless link_back_present? field.mark_verified! - rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, IPAddr::AddressFamilyError => e + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, IPAddr::AddressFamilyError => e Rails.logger.debug { "Error fetching link #{@url}: #{e}" } nil end diff --git a/app/views/admin/action_logs/index.html.haml b/app/views/admin/action_logs/index.html.haml index c02c8f0ad41fae..a5d41882943cf2 100644 --- a/app/views/admin/action_logs/index.html.haml +++ b/app/views/admin/action_logs/index.html.haml @@ -16,7 +16,7 @@ %strong= t('admin.action_logs.filter_by_action') .input.select.optional = form.select :action_type, - options_for_select(Admin::ActionLogFilter::ACTION_TYPE_MAP.keys.map { |key| [I18n.t("admin.action_logs.action_types.#{key}"), key] }, params[:action_type]), + options_for_select(sorted_action_log_types, params[:action_type]), prompt: I18n.t('admin.accounts.moderation.all') - if @action_logs.empty? diff --git a/app/views/admin/announcements/index.html.haml b/app/views/admin/announcements/index.html.haml index 72227b04577a04..6a76c187766a5c 100644 --- a/app/views/admin/announcements/index.html.haml +++ b/app/views/admin/announcements/index.html.haml @@ -9,7 +9,7 @@ %strong= t('admin.relays.status') %ul %li= filter_link_to t('generic.all'), published: nil, unpublished: nil - %li= filter_link_to safe_join([t('admin.announcements.live'), "(#{number_with_delimiter(Announcement.published.count)})"], ' '), published: '1', unpublished: nil + %li= filter_link_to safe_join([t('admin.announcements.live'), "(#{number_with_delimiter(@published_announcements_count.value)})"], ' '), published: '1', unpublished: nil - if @announcements.empty? .muted-hint.center-text diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 27d8f4790ba8be..2b4d02fa67c0a0 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -2,9 +2,7 @@ = t('admin.dashboard.title') - content_for :heading_actions do - = l(@time_period.first) - = ' - ' - = l(@time_period.last) + = date_range(@time_period) - unless @system_checks.empty? .flash-message-stack diff --git a/app/views/admin/disputes/appeals/index.html.haml b/app/views/admin/disputes/appeals/index.html.haml index 7f04dd40fb5f91..e09e275e5d5c3e 100644 --- a/app/views/admin/disputes/appeals/index.html.haml +++ b/app/views/admin/disputes/appeals/index.html.haml @@ -5,7 +5,7 @@ .filter-subset %strong= t('admin.tags.review') %ul - %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Appeal.pending.count})"], ' '), status: 'pending' + %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{@pending_appeals_count.value})"], ' '), status: 'pending' %li= filter_link_to t('admin.trends.approved'), status: 'approved' %li= filter_link_to t('admin.trends.rejected'), status: 'rejected' diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml index dd4b83ee3f2832..2dfdca93763dda 100644 --- a/app/views/admin/email_domain_blocks/new.html.haml +++ b/app/views/admin/email_domain_blocks/new.html.haml @@ -16,7 +16,7 @@ label: I18n.t('admin.email_domain_blocks.allow_registrations_with_approval'), wrapper: :with_label - - if defined?(@resolved_records) + - if defined?(@resolved_records) && @resolved_records.any? %p.hint= t('admin.email_domain_blocks.resolved_dns_records_hint_html') .batch-table diff --git a/app/views/admin/instances/_dashboard.html.haml b/app/views/admin/instances/_dashboard.html.haml new file mode 100644 index 00000000000000..ef8500103be462 --- /dev/null +++ b/app/views/admin/instances/_dashboard.html.haml @@ -0,0 +1,66 @@ +-# locals: (instance_domain:, period_end_at:, period_start_at:) +%p + = material_symbol 'info' + = t('admin.instances.totals_time_period_hint_html') + +.dashboard + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + href: admin_accounts_path(origin: 'remote', by_domain: instance_domain), + label: t('admin.instances.dashboard.instance_accounts_measure'), + measure: 'instance_accounts', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_statuses_measure'), + measure: 'instance_statuses', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_media_attachments_measure'), + measure: 'instance_media_attachments', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_follows_measure'), + measure: 'instance_follows', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_followers_measure'), + measure: 'instance_followers', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :counter, + end_at: period_end_at, + href: admin_reports_path(by_target_domain: instance_domain), + label: t('admin.instances.dashboard.instance_reports_measure'), + measure: 'instance_reports', + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :dimension, + dimension: 'instance_accounts', + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_accounts_dimension'), + limit: 8, + params: { domain: instance_domain }, + start_at: period_start_at + .dashboard__item + = react_admin_component :dimension, + dimension: 'instance_languages', + end_at: period_end_at, + label: t('admin.instances.dashboard.instance_languages_dimension'), + limit: 8, + params: { domain: instance_domain }, + start_at: period_start_at diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml index c55eb89dc94933..812a9c8870b0eb 100644 --- a/app/views/admin/instances/show.html.haml +++ b/app/views/admin/instances/show.html.haml @@ -3,77 +3,10 @@ - if current_user.can?(:view_dashboard) - content_for :heading_actions do - = l(@time_period.first) - = ' - ' - = l(@time_period.last) + = date_range(@time_period) - if @instance.persisted? - %p - = material_symbol 'info' - = t('admin.instances.totals_time_period_hint_html') - - .dashboard - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - href: admin_accounts_path(origin: 'remote', by_domain: @instance.domain), - label: t('admin.instances.dashboard.instance_accounts_measure'), - measure: 'instance_accounts', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_statuses_measure'), - measure: 'instance_statuses', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_media_attachments_measure'), - measure: 'instance_media_attachments', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_follows_measure'), - measure: 'instance_follows', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_followers_measure'), - measure: 'instance_followers', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :counter, - end_at: @time_period.last, - href: admin_reports_path(by_target_domain: @instance.domain), - label: t('admin.instances.dashboard.instance_reports_measure'), - measure: 'instance_reports', - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :dimension, - dimension: 'instance_accounts', - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_accounts_dimension'), - limit: 8, - params: { domain: @instance.domain }, - start_at: @time_period.first - .dashboard__item - = react_admin_component :dimension, - dimension: 'instance_languages', - end_at: @time_period.last, - label: t('admin.instances.dashboard.instance_languages_dimension'), - limit: 8, - params: { domain: @instance.domain }, - start_at: @time_period.first - + = render 'dashboard', instance_domain: @instance.domain, period_end_at: @time_period.last, period_start_at: @time_period.first - else %p = t('admin.instances.unknown_instance') diff --git a/app/views/admin/invites/_invite.html.haml b/app/views/admin/invites/_invite.html.haml index 8bd5f10feefdc6..e3e5d325428c6e 100644 --- a/app/views/admin/invites/_invite.html.haml +++ b/app/views/admin/invites/_invite.html.haml @@ -1,8 +1,8 @@ -%tr +%tr{ id: dom_id(invite) } %td .input-copy .input-copy__wrapper - %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: public_invite_url(invite_code: invite.code) } + = copyable_input value: public_invite_url(invite_code: invite.code) %button{ type: :button }= t('generic.copy') %td 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/tags/show.html.haml b/app/views/admin/tags/show.html.haml index 93387843b2ce41..462ca312a07e86 100644 --- a/app/views/admin/tags/show.html.haml +++ b/app/views/admin/tags/show.html.haml @@ -4,9 +4,7 @@ - content_for :heading_actions do - if current_user.can?(:view_dashboard) .time-period - = l(@time_period.first) - = ' - ' - = l(@time_period.last) + = date_range(@time_period) = link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener noreferrer' diff --git a/app/views/admin/trends/links/preview_card_providers/index.html.haml b/app/views/admin/trends/links/preview_card_providers/index.html.haml index 93daf25f31a74d..0770ac4b810bfb 100644 --- a/app/views/admin/trends/links/preview_card_providers/index.html.haml +++ b/app/views/admin/trends/links/preview_card_providers/index.html.haml @@ -12,7 +12,7 @@ %li= filter_link_to t('generic.all'), status: nil %li= filter_link_to t('admin.trends.approved'), status: 'approved' %li= filter_link_to t('admin.trends.rejected'), status: 'rejected' - %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{PreviewCardProvider.unreviewed.count})"], ' '), status: 'pending_review' + %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{@pending_preview_card_providers_count.value})"], ' '), status: 'pending_review' .back-link = link_to admin_trends_links_path do = material_symbol 'chevron_left' diff --git a/app/views/admin/trends/tags/index.html.haml b/app/views/admin/trends/tags/index.html.haml index 480877456f5f96..21f6c2947aca37 100644 --- a/app/views/admin/trends/tags/index.html.haml +++ b/app/views/admin/trends/tags/index.html.haml @@ -12,7 +12,7 @@ %li= filter_link_to t('generic.all'), status: nil %li= filter_link_to t('admin.trends.approved'), status: 'approved' %li= filter_link_to t('admin.trends.rejected'), status: 'rejected' - %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), status: 'pending_review' + %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{@pending_tags_count.value})"], ' '), status: 'pending_review' = form_with model: @form, url: batch_admin_trends_tags_path do |f| = hidden_field_tag :page, params[:page] || 1 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/application/mailer/_hashtag.html.haml b/app/views/application/mailer/_hashtag.html.haml index b740ba31b99437..0fe7117bc4d1c8 100644 --- a/app/views/application/mailer/_hashtag.html.haml +++ b/app/views/application/mailer/_hashtag.html.haml @@ -17,5 +17,4 @@ %span.email-mini-hashtag-img-span = image_tag full_asset_url(account.avatar.url), alt: '', width: 16, height: 16 %td - - people = hashtag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts - %p= t('user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(people), count: people) + %p= recent_tag_usage(hashtag) 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/invites/_invite.html.haml b/app/views/invites/_invite.html.haml index 892fdc5a0e38af..7c94062de450bb 100644 --- a/app/views/invites/_invite.html.haml +++ b/app/views/invites/_invite.html.haml @@ -2,7 +2,7 @@ %td .input-copy .input-copy__wrapper - %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: public_invite_url(invite_code: invite.code) } + = copyable_input value: public_invite_url(invite_code: invite.code) %button{ type: :button }= t('generic.copy') - if invite.valid_for_use? diff --git a/app/views/oauth/authorizations/show.html.haml b/app/views/oauth/authorizations/show.html.haml index a5122a87fc39d7..bdff3363682c07 100644 --- a/app/views/oauth/authorizations/show.html.haml +++ b/app/views/oauth/authorizations/show.html.haml @@ -3,5 +3,5 @@ %p= t('doorkeeper.authorizations.show.title') .input-copy .input-copy__wrapper - %input.oauth-code{ type: 'text', spellcheck: 'false', readonly: true, value: params[:code] } + = copyable_input value: params[:code], class: 'oauth-code' %button{ type: :button }= t('generic.copy') 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..85fdefa0fcdf2e --- /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 + = form.label t('activerecord.attributes.doorkeeper/application.scopes'), required: true + %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) { label_for_scope(scope) }, + label: false, + required: false, + selected: form.object.scopes.all, + wrapper: :with_block_label diff --git a/app/views/settings/applications/index.html.haml b/app/views/settings/applications/index.html.haml index 80eaed5c3994f8..e3011947a64f59 100644 --- a/app/views/settings/applications/index.html.haml +++ b/app/views/settings/applications/index.html.haml @@ -18,7 +18,9 @@ - @applications.each do |application| %tr %td= link_to application.name, settings_application_path(application) - %th= application.scopes + %th + - application.scopes.to_s.split.each do |scope| + = tag.samp(scope, class: 'information-badge', title: t("doorkeeper.scopes.#{scope}")) %td = table_link_to 'close', t('doorkeeper.applications.index.delete'), settings_application_path(application), method: :delete, data: { confirm: t('doorkeeper.applications.confirmations.destroy') } 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..bfde27daa96440 100644 --- a/app/views/settings/applications/show.html.haml +++ b/app/views/settings/applications/show.html.haml @@ -15,16 +15,17 @@ %td %code= @application.secret %tr - %th{ rowspan: 2 }= t('applications.your_token') + %th= t('applications.your_token') %td %code= current_user.token_for_app(@application).token %tr + %th %td= table_link_to 'refresh', t('applications.regenerate_token'), regenerate_settings_application_path(@application), method: :post %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) 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/exports/show.html.haml b/app/views/settings/exports/show.html.haml index 320bb0c7cebcbb..5a151be73becce 100644 --- a/app/views/settings/exports/show.html.haml +++ b/app/views/settings/exports/show.html.haml @@ -6,39 +6,39 @@ %tbody %tr %th= t('exports.storage') - %td= number_to_human_size @export.total_storage + %td= number_to_human_size @export_summary.total_storage %td %tr %th= t('accounts.posts_tab_heading') - %td= number_with_delimiter @export.total_statuses + %td= number_with_delimiter @export_summary.total_statuses %td %tr %th= t('admin.accounts.follows') - %td= number_with_delimiter @export.total_follows + %td= number_with_delimiter @export_summary.total_follows %td= table_link_to 'download', t('exports.csv'), settings_exports_follows_path(format: :csv) %tr %th= t('exports.lists') - %td= number_with_delimiter @export.total_lists + %td= number_with_delimiter @export_summary.total_lists %td= table_link_to 'download', t('exports.csv'), settings_exports_lists_path(format: :csv) %tr %th= t('admin.accounts.followers') - %td= number_with_delimiter @export.total_followers + %td= number_with_delimiter @export_summary.total_followers %td %tr %th= t('exports.mutes') - %td= number_with_delimiter @export.total_mutes + %td= number_with_delimiter @export_summary.total_mutes %td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv) %tr %th= t('exports.blocks') - %td= number_with_delimiter @export.total_blocks + %td= number_with_delimiter @export_summary.total_blocks %td= table_link_to 'download', t('exports.csv'), settings_exports_blocks_path(format: :csv) %tr %th= t('exports.domain_blocks') - %td= number_with_delimiter @export.total_domain_blocks + %td= number_with_delimiter @export_summary.total_domain_blocks %td= table_link_to 'download', t('exports.csv'), settings_exports_domain_blocks_path(format: :csv) %tr %th= t('exports.bookmarks') - %td= number_with_delimiter @export.total_bookmarks + %td= number_with_delimiter @export_summary.total_bookmarks %td= table_link_to 'download', t('exports.csv'), settings_exports_bookmarks_path(format: :csv) %hr.spacer/ @@ -61,7 +61,8 @@ %tbody - @backups.each do |backup| %tr - %td= l backup.created_at + %td + %time.formatted{ datetime: backup.created_at.iso8601, title: l(backup.created_at) }= l backup.created_at - if backup.processed? %td= number_to_human_size backup.dump_file_size %td= table_link_to 'download', t('exports.archive_takeout.download'), download_backup_url(backup) diff --git a/app/views/settings/imports/index.html.haml b/app/views/settings/imports/index.html.haml index 634631b5aaa4cc..55421991e13173 100644 --- a/app/views/settings/imports/index.html.haml +++ b/app/views/settings/imports/index.html.haml @@ -55,7 +55,10 @@ = t("imports.states.#{import.state}") %td #{import.imported_items} / #{import.total_items} - %td= l(import.created_at) + %td + %time.formatted{ datetime: import.created_at.iso8601, title: l(import.created_at) } + = l(import.created_at) + %td - num_failed = import.processed_items - import.imported_items - if num_failed.positive? diff --git a/app/views/settings/imports/show.html.haml b/app/views/settings/imports/show.html.haml index 4d50049d3d3da5..dd18ac2168c8c7 100644 --- a/app/views/settings/imports/show.html.haml +++ b/app/views/settings/imports/show.html.haml @@ -5,9 +5,9 @@ .flash-message.warning= t('imports.mismatched_types_warning') - if @bulk_import.overwrite? - %p.hint= t("imports.overwrite_preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items) + %p.hint= t("imports.overwrite_preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, count: @bulk_import.total_items) - else - %p.hint= t("imports.preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items) + %p.hint= t("imports.preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, count: @bulk_import.total_items) .simple_form .actions diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index b0cd1cba09d63c..0d127bc81de780 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -4,7 +4,7 @@ - content_for :heading_actions do = button_tag t('generic.save_changes'), class: 'button', form: 'edit_user' -= simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f| += simple_form_for current_user, url: settings_preferences_appearance_path, html: { id: :edit_user } do |f| .fields-row .fields-group.fields-row__column.fields-row__column-6 = f.input :locale, diff --git a/app/views/settings/preferences/notifications/show.html.haml b/app/views/settings/preferences/notifications/show.html.haml index 17d5ac20fad68c..9fc293f0a293f9 100644 --- a/app/views/settings/preferences/notifications/show.html.haml +++ b/app/views/settings/preferences/notifications/show.html.haml @@ -4,7 +4,7 @@ - content_for :heading_actions do = button_tag t('generic.save_changes'), class: 'button', form: 'edit_notification' -= simple_form_for current_user, url: settings_preferences_notifications_path, html: { method: :put, id: 'edit_notification' } do |f| += simple_form_for current_user, url: settings_preferences_notifications_path, html: { id: :edit_notification } do |f| = render 'shared/error_messages', object: current_user %h4= t 'notifications.email_events' diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml index 49d03ca00a612b..b260826fe529f2 100644 --- a/app/views/settings/preferences/other/show.html.haml +++ b/app/views/settings/preferences/other/show.html.haml @@ -4,7 +4,7 @@ - content_for :heading_actions do = button_tag t('generic.save_changes'), class: 'button', form: 'edit_preferences' -= simple_form_for current_user, url: settings_preferences_other_path, html: { method: :put, id: 'edit_preferences' } do |f| += simple_form_for current_user, url: settings_preferences_other_path, html: { id: :edit_preferences } do |f| = render 'shared/error_messages', object: current_user = f.simple_fields_for :settings, current_user.settings do |ff| diff --git a/app/views/settings/privacy/show.html.haml b/app/views/settings/privacy/show.html.haml index 3fb14023b06f09..e8e5bdb906322f 100644 --- a/app/views/settings/privacy/show.html.haml +++ b/app/views/settings/privacy/show.html.haml @@ -5,7 +5,7 @@ %h2= t('settings.profile') = render partial: 'settings/shared/profile_navigation' -= simple_form_for @account, url: settings_privacy_path, html: { method: :put } do |f| += simple_form_for @account, url: settings_privacy_path do |f| = render 'shared/error_messages', object: @account %p.lead= t('privacy.hint_html') diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index fc44f01402e1d1..e00c39da684675 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -5,7 +5,7 @@ %h2= t('settings.profile') = render partial: 'settings/shared/profile_navigation' -= simple_form_for @account, url: settings_profile_path, html: { method: :put, id: 'edit_profile' } do |f| += simple_form_for @account, url: settings_profile_path, html: { id: :edit_profile } do |f| = render 'shared/error_messages', object: @account %p.lead= t('edit_profile.hint_html') @@ -27,14 +27,14 @@ = 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 .fields-group = f.input :avatar, - hint: t('simple_form.hints.defaults.avatar', dimensions: '400x400', size: number_to_human_size(Account::Avatar::LIMIT)), + hint: t('simple_form.hints.defaults.avatar', dimensions: Account::Avatar::AVATAR_GEOMETRY, size: number_to_human_size(Account::Avatar::LIMIT)), input_html: { accept: Account::Avatar::IMAGE_MIME_TYPES.join(',') }, wrapper: :with_block_label @@ -50,7 +50,7 @@ .fields-row__column.fields-row__column-6 .fields-group = f.input :header, - hint: t('simple_form.hints.defaults.header', dimensions: '1500x500', size: number_to_human_size(Account::Header::LIMIT)), + hint: t('simple_form.hints.defaults.header', dimensions: Account::Header::HEADER_GEOMETRY, size: number_to_human_size(Account::Header::LIMIT)), input_html: { accept: Account::Header::IMAGE_MIME_TYPES.join(',') }, wrapper: :with_block_label diff --git a/app/views/settings/shared/_profile_navigation.html.haml b/app/views/settings/shared/_profile_navigation.html.haml index d490bd75661704..2f81cb5cfdccdf 100644 --- a/app/views/settings/shared/_profile_navigation.html.haml +++ b/app/views/settings/shared/_profile_navigation.html.haml @@ -1,7 +1,7 @@ .content__heading__tabs = render_navigation renderer: :links do |primary| :ruby - primary.item :profile, safe_join([material_symbol('person'), t('settings.edit_profile')]), settings_profile_path - primary.item :privacy, safe_join([material_symbol('lock'), t('privacy.title')]), settings_privacy_path + primary.item :edit_profile, safe_join([material_symbol('person'), t('settings.edit_profile')]), settings_profile_path + primary.item :privacy_reach, safe_join([material_symbol('lock'), t('privacy.title')]), settings_privacy_path primary.item :verification, safe_join([material_symbol('check'), t('verification.verification')]), settings_verification_path primary.item :featured_tags, safe_join([material_symbol('tag'), t('settings.featured_tags')]), settings_featured_tags_path diff --git a/app/views/settings/two_factor_authentication/confirmations/new.html.haml b/app/views/settings/two_factor_authentication/confirmations/new.html.haml index 0b8278a104eaea..a35479b84e6850 100644 --- a/app/views/settings/two_factor_authentication/confirmations/new.html.haml +++ b/app/views/settings/two_factor_authentication/confirmations/new.html.haml @@ -5,7 +5,7 @@ %p.hint= t('otp_authentication.instructions_html') .qr-wrapper - .qr-code!= @qrcode.as_svg(padding: 0, module_size: 4) + .qr-code!= @qrcode.as_svg(padding: 0, module_size: 4, use_path: true) .qr-alternative %p.hint= t('otp_authentication.manual_instructions') diff --git a/app/views/settings/verifications/show.html.haml b/app/views/settings/verifications/show.html.haml index 5318b0767ddfb0..4def10e595dbe3 100644 --- a/app/views/settings/verifications/show.html.haml +++ b/app/views/settings/verifications/show.html.haml @@ -16,7 +16,7 @@ .input-copy.lead .input-copy__wrapper - %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: link_to('Mastodon', ActivityPub::TagManager.instance.url_for(@account), rel: 'me').to_str } + = copyable_input value: link_to('Mastodon', ActivityPub::TagManager.instance.url_for(@account), rel: :me) %button{ type: :button }= t('generic.copy') %p.lead= t('verification.extra_instructions_html') @@ -31,32 +31,41 @@ = material_symbol 'check', class: 'verified-badge__mark' %span= field.value -= simple_form_for @account, url: settings_verification_path, html: { method: :put, class: 'form-section' } do |f| += simple_form_for @account, url: settings_verification_path, html: { class: 'form-section' } do |f| = render 'shared/error_messages', object: @account %h3= t('author_attribution.title') %p.lead= t('author_attribution.hint_html') - .fields-row - .fields-row__column.fields-row__column-6 - .fields-group - = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4 } - .fields-row__column.fields-row__column-6 - .fields-group.fade-out-top - %div - .status-card.expanded.bottomless - .status-card__image - = image_tag frontend_asset_url('images/preview.png'), alt: '', class: 'status-card__image-image' - .status-card__content - %span.status-card__host - %span= t('author_attribution.s_blog', name: @account.username) - · - %time.time-ago{ datetime: 1.year.ago.to_date.iso8601 } - %strong.status-card__title= t('author_attribution.example_title') - .more-from-author - = logo_as_symbol(:icon) - = t('author_attribution.more_from_html', name: link_to(root_url, class: 'story__details__shared__author-link') { image_tag(@account.avatar.url, class: 'account__avatar', width: 16, height: 16, alt: '') + content_tag(:bdi, display_name(@account)) }) + .fields-group.fade-out-top + %div + .status-card.expanded.bottomless + .status-card__image + = image_tag frontend_asset_url('images/preview.png'), alt: '', class: 'status-card__image-image' + .status-card__content + %span.status-card__host + %span= t('author_attribution.s_blog', name: display_name(@account)) + · + %time.time-ago{ datetime: 1.year.ago.to_date.iso8601 } + %strong.status-card__title= t('author_attribution.example_title') + .more-from-author + = logo_as_symbol(:icon) + = t('author_attribution.more_from_html', name: link_to(root_url, class: 'story__details__shared__author-link') { image_tag(@account.avatar.url, class: 'account__avatar', width: 16, height: 16, alt: '') + tag.bdi(display_name(@account)) }) + + %h4= t('verification.here_is_how') + + %p.lead= t('author_attribution.instructions') + + .input-copy.lead + .input-copy__wrapper + = copyable_input value: tag.meta(name: 'fediverse:creator', content: "@#{@account.local_username_and_domain}") + %button{ type: :button }= t('generic.copy') + + %p.lead= t('author_attribution.then_instructions') + + .fields-group + = f.input :attribution_domains_as_text, as: :text, wrapper: :with_block_label, input_html: { placeholder: "example1.com\nexample2.com\nexample3.com", rows: 4 } .actions = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/severed_relationships/index.html.haml b/app/views/severed_relationships/index.html.haml index 7c599e9c0e7e55..cc9439b4681eed 100644 --- a/app/views/severed_relationships/index.html.haml +++ b/app/views/severed_relationships/index.html.haml @@ -15,7 +15,9 @@ %tbody - @events.each do |event| %tr - %td= l event.created_at + %td + %time.formatted{ datetime: event.created_at.iso8601, title: l(event.created_at) } + = l(event.created_at) %td= t("severed_relationships.event_type.#{event.type}", target_name: event.target_name) - if event.purged? %td{ rowspan: 2 }= t('severed_relationships.purged') 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/app/views/user_mailer/welcome.text.erb b/app/views/user_mailer/welcome.text.erb index d9da2997daecd7..144d44b8429a5b 100644 --- a/app/views/user_mailer/welcome.text.erb +++ b/app/views/user_mailer/welcome.text.erb @@ -53,7 +53,7 @@ <%= t('user_mailer.welcome.hashtags_subtitle') %> <%- @tags.each do |tag| %> -* #<%= tag.display_name %> · <%= t('user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(tag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts)) %> +* #<%= tag.display_name %> · <%= recent_tag_usage(tag) %> <%= tag_url(tag) %> <%- end %> diff --git a/app/workers/filtered_notification_cleanup_worker.rb b/app/workers/filtered_notification_cleanup_worker.rb index 2b955da3c0a1ac..87ff6a9eb5e928 100644 --- a/app/workers/filtered_notification_cleanup_worker.rb +++ b/app/workers/filtered_notification_cleanup_worker.rb @@ -4,6 +4,6 @@ class FilteredNotificationCleanupWorker include Sidekiq::Worker def perform(account_id, from_account_id) - Notification.where(account_id: account_id, from_account_id: from_account_id, filtered: true).reorder(nil).in_batches(order: :desc).delete_all + Notification.where(account_id: account_id, from_account_id: from_account_id, filtered: true).in_batches(order: :desc).delete_all end end diff --git a/app/workers/mention_resolve_worker.rb b/app/workers/mention_resolve_worker.rb new file mode 100644 index 00000000000000..72dcd9633f32fe --- /dev/null +++ b/app/workers/mention_resolve_worker.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +class MentionResolveWorker + include Sidekiq::Worker + include ExponentialBackoff + include JsonLdHelper + + sidekiq_options queue: 'pull', retry: 7 + + def perform(status_id, uri, options = {}) + status = Status.find_by(id: status_id) + return if status.nil? + + account = account_from_uri(uri) + account = ActivityPub::FetchRemoteAccountService.new.call(uri, request_id: options[:request_id]) if account.nil? + + return if account.nil? + + status.mentions.create!(account: account, silent: false) + rescue ActiveRecord::RecordNotFound + # Do nothing + rescue Mastodon::UnexpectedResponseError => e + response = e.response + + if response_error_unsalvageable?(response) + # Give up + else + raise e + end + end + + private + + def account_from_uri(uri) + ActivityPub::TagManager.instance.uri_to_resource(uri, Account) + end +end diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb index 4b712d3aaeb625..7b26e4a0623ad4 100644 --- a/app/workers/refollow_worker.rb +++ b/app/workers/refollow_worker.rb @@ -21,7 +21,7 @@ def perform(target_account_id) # Schedule re-follow begin FollowService.new.call(follower, target_account, reblogs: reblogs, notify: notify, languages: languages, bypass_limit: true) - rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError + rescue Mastodon::NotPermittedError, ActiveRecord::RecordNotFound, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS next end end diff --git a/app/workers/scheduler/user_cleanup_scheduler.rb b/app/workers/scheduler/user_cleanup_scheduler.rb index 9f58d9225b3a14..f7551283320dce 100644 --- a/app/workers/scheduler/user_cleanup_scheduler.rb +++ b/app/workers/scheduler/user_cleanup_scheduler.rb @@ -16,7 +16,7 @@ def perform private def clean_unconfirmed_accounts! - User.unconfirmed.where(confirmation_sent_at: ..UNCONFIRMED_ACCOUNTS_MAX_AGE_DAYS.days.ago).reorder(nil).find_in_batches do |batch| + User.unconfirmed.where(confirmation_sent_at: ..UNCONFIRMED_ACCOUNTS_MAX_AGE_DAYS.days.ago).find_in_batches do |batch| # We have to do it separately because of missing database constraints AccountModerationNote.where(target_account_id: batch.map(&:account_id)).delete_all Account.where(id: batch.map(&:account_id)).delete_all diff --git a/app/workers/web/push_notification_worker.rb b/app/workers/web/push_notification_worker.rb index 7e9691aaba37cd..e771928ef31fa7 100644 --- a/app/workers/web/push_notification_worker.rb +++ b/app/workers/web/push_notification_worker.rb @@ -16,10 +16,10 @@ def perform(subscription_id, notification_id) # in the meantime, so we have to double-check before proceeding return unless @notification.activity.present? && @subscription.pushable?(@notification) - payload = @subscription.encrypt(push_notification_json) + payload = web_push_request.encrypt(push_notification_json) - request_pool.with(@subscription.audience) do |http_client| - request = Request.new(:post, @subscription.endpoint, body: payload.fetch(:ciphertext), http_client: http_client) + request_pool.with(web_push_request.audience) do |http_client| + request = Request.new(:post, web_push_request.endpoint, body: payload.fetch(:ciphertext), http_client: http_client) request.add_headers( 'Content-Type' => 'application/octet-stream', @@ -27,8 +27,8 @@ def perform(subscription_id, notification_id) 'Urgency' => URGENCY, 'Content-Encoding' => 'aesgcm', 'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}", - 'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{@subscription.crypto_key_header}", - 'Authorization' => @subscription.authorization_header + 'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{web_push_request.crypto_key_header}", + 'Authorization' => web_push_request.authorization_header ) request.perform do |response| @@ -50,17 +50,23 @@ def perform(subscription_id, notification_id) private + def web_push_request + @web_push_request || WebPushRequest.new(@subscription) + end + def push_notification_json - json = I18n.with_locale(@subscription.locale.presence || I18n.default_locale) do - ActiveModelSerializers::SerializableResource.new( - @notification, - serializer: Web::NotificationSerializer, - scope: @subscription, - scope_name: :current_push_subscription - ).as_json + I18n.with_locale(@subscription.locale.presence || I18n.default_locale) do + Oj.dump(serialized_notification.as_json) end + end - Oj.dump(json) + def serialized_notification + ActiveModelSerializers::SerializableResource.new( + @notification, + serializer: Web::NotificationSerializer, + scope: @subscription, + scope_name: :current_push_subscription + ) end def request_pool diff --git a/config/application.rb b/config/application.rb index 0013c788583035..5e2f44453d4d9c 100644 --- a/config/application.rb +++ b/config/application.rb @@ -96,10 +96,6 @@ class Application < Rails::Application config.middleware.use Rack::Attack config.middleware.use Mastodon::RackMiddleware - initializer :deprecator do |app| - app.deprecators[:mastodon] = ActiveSupport::Deprecation.new('4.3', 'mastodon/mastodon') - end - config.before_configuration do require 'mastodon/redis_configuration' ::REDIS_CONFIGURATION = Mastodon::RedisConfiguration.new diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 26c722da60ea28..16330734736209 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -74,8 +74,8 @@ ignore_unused: - 'admin_mailer.*.subject' - 'user_mailer.*.subject' - 'notification_mailer.*' - - 'imports.overwrite_preambles.{following,blocking,muting,domain_blocking,bookmarks,lists}_html' - - 'imports.preambles.{following,blocking,muting,domain_blocking,bookmarks,lists}_html' + - 'imports.overwrite_preambles.{following,blocking,muting,domain_blocking,bookmarks,lists}_html.*' + - 'imports.preambles.{following,blocking,muting,domain_blocking,bookmarks,lists}_html.*' - 'mail_subscriptions.unsubscribe.emails.*' - 'preferences.other' # some locales are missing other keys, therefore leading i18n-tasks to detect `preferences` as plural and not finding use - 'edit_profile.other' # some locales are missing other keys, therefore leading i18n-tasks to detect `preferences` as plural and not finding use diff --git a/config/initializers/0_duplicate_migrations.rb b/config/initializers/0_duplicate_migrations.rb deleted file mode 100644 index f99357187702d6..00000000000000 --- a/config/initializers/0_duplicate_migrations.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -# Some migrations have been present in glitch-soc for a long time and have then -# been merged in upstream Mastodon, under a different version number. -# -# This puts us in an uneasy situation in which if we remove upstream's -# migration file, people migrating from upstream will end up having a conflict -# with their already-ran migration. -# -# On the other hand, if we keep upstream's migration and remove our own, -# any current glitch-soc user will have a conflict during migration. -# -# For lack of a better solution, as those migrations are indeed identical, -# we decided monkey-patching Rails' Migrator to completely ignore the duplicate, -# keeping only the one that has run, or an arbitrary one. - -ALLOWED_DUPLICATES = [2018_04_10_220657, 2018_08_31_171112].freeze - -module ActiveRecord - class Migrator - def self.new(direction, migrations, schema_migration, internal_metadata, target_version = nil) - migrated = Set.new(Base.connection.migration_context.get_all_versions) - - migrations.group_by(&:name).each_value do |duplicates| - next unless duplicates.length > 1 && duplicates.all? { |m| ALLOWED_DUPLICATES.include?(m.version) } - - # We have a set of allowed duplicates. Keep the migrated one, if any. - non_migrated = duplicates.reject { |m| migrated.include?(m.version.to_i) } - - migrations = begin - if duplicates.length == non_migrated.length || non_migrated.empty? - # There weren't any migrated one, so we have to pick one “canonical” migration - migrations - duplicates[1..] - else - # Just reject every duplicate which hasn't been migrated yet - migrations - non_migrated - end - end - end - - super - end - end - - class MigrationContext - def needs_migration? - # A set of duplicated migrations is considered migrated if at least one of - # them is migrated. - migrated = get_all_versions - migrations.group_by(&:name).each_value do |duplicates| - return true unless duplicates.any? { |m| migrated.include?(m.version.to_i) } - end - false - end - end -end diff --git a/config/initializers/active_record_encryption.rb b/config/initializers/active_record_encryption.rb index b7a874e4046f2d..9ae28e401bab4d 100644 --- a/config/initializers/active_record_encryption.rb +++ b/config/initializers/active_record_encryption.rb @@ -10,7 +10,9 @@ ENV[key] = SecureRandom.hex(64) end - value = ENV.fetch(key) do + value = ENV.fetch(key, '') + + if value.blank? abort <<~MESSAGE Mastodon now requires that these variables are set: @@ -20,6 +22,7 @@ - ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY Run `bin/rails db:encryption:init` to generate new secrets and then assign the environment variables. + Do not change the secrets once they are set, as doing so may cause data loss and other issues that will be difficult or impossible to recover from. MESSAGE end diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index b47e76c08bc60a..de1c75f576ec8e 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -9,16 +9,9 @@ current_user || redirect_to(new_user_session_url) end - resource_owner_from_credentials do |_routes| - user = User.authenticate_with_ldap(email: request.params[:username], password: request.params[:password]) if Devise.ldap_authentication - user ||= User.authenticate_with_pam(email: request.params[:username], password: request.params[:password]) if Devise.pam_authentication - - if user.nil? - user = User.find_by(email: request.params[:username]) - user = nil unless user&.valid_password?(request.params[:password]) - end - - user unless user&.otp_required_for_login? + # Disable Resource Owner Password Credentials Grant Flow + resource_owner_from_credentials do + nil end # Doorkeeper provides some administrative interfaces for managing OAuth @@ -169,7 +162,7 @@ # http://tools.ietf.org/html/rfc6819#section-4.4.3 # - grant_flows %w(authorization_code password client_credentials) + grant_flows %w(authorization_code client_credentials) # Under some circumstances you might want to have applications auto-approved, # so that the user skips the authorization step. 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..45149cd1173b95 100644 --- a/config/locales/activerecord.eo.yml +++ b/config/locales/activerecord.eo.yml @@ -15,11 +15,17 @@ 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: username: - invalid: nur literoj, ciferoj kaj substrekoj + invalid: devas enhavi nur literojn, ciferojn kaj substrekojn reserved: rezervita admin/webhook: attributes: diff --git a/config/locales/activerecord.fy.yml b/config/locales/activerecord.fy.yml index b571ab60dc93df..69139eba1d47a4 100644 --- a/config/locales/activerecord.fy.yml +++ b/config/locales/activerecord.fy.yml @@ -15,6 +15,12 @@ fy: user/invite_request: text: Reden errors: + attributes: + domain: + invalid: is in ûnjildige domeinnamme + messages: + invalid_domain_on_line: "%{value} is in ûnjildige domeinnamme" + too_many_lines: giet oer de limyt fan %{limit} rigels models: account: attributes: diff --git a/config/locales/activerecord.ia.yml b/config/locales/activerecord.ia.yml index bccfb96602b7f5..809b8fd5821343 100644 --- a/config/locales/activerecord.ia.yml +++ b/config/locales/activerecord.ia.yml @@ -20,6 +20,7 @@ ia: invalid: non es un nomine de dominio valide messages: invalid_domain_on_line: "%{value} non es un nomine de dominio valide" + too_many_lines: il es ultra le limite de %{limit} lineas 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.ja.yml b/config/locales/activerecord.ja.yml index 468df9b12b0ea7..21be8aa3451d08 100644 --- a/config/locales/activerecord.ja.yml +++ b/config/locales/activerecord.ja.yml @@ -15,6 +15,12 @@ ja: 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.lad.yml b/config/locales/activerecord.lad.yml index 31e0223ccac764..8fd23b53fec7f3 100644 --- a/config/locales/activerecord.lad.yml +++ b/config/locales/activerecord.lad.yml @@ -15,6 +15,11 @@ lad: user/invite_request: text: Razon errors: + attributes: + domain: + invalid: no es un nombre de domeno valido + messages: + invalid_domain_on_line: "%{value} no es un nombre de domeno valido" models: account: attributes: diff --git a/config/locales/activerecord.ml.yml b/config/locales/activerecord.ml.yml index 8b20ee34b32e3b..90c5b38ad5ab86 100644 --- a/config/locales/activerecord.ml.yml +++ b/config/locales/activerecord.ml.yml @@ -4,23 +4,37 @@ ml: attributes: poll: expires_at: സമയപരിധി - options: ചോയ്‌സുകൾ + options: തിരഞ്ഞെടുപ്പുകൾ user: agreement: സേവന ഉടമ്പടി email: ഇ-മെയിൽ വിലാസം locale: ഭാഷ - password: രഹസ്യവാചകം + password: രഹസ്യവാക്കു് user/account: username: ഉപയോക്തൃനാമം user/invite_request: text: കാരണം errors: + attributes: + domain: + invalid: ഇതൊരു തെറ്റിയ മേഖലപേരാണു് + messages: + invalid_domain_on_line: "%{value} ഒരു തെറ്റിയ മേഖലപേരാണു്" + too_many_lines: ഇതു് %{limit} വരിയതിരിന്റെ മേലെയാണു് models: account: attributes: username: invalid: അക്ഷരങ്ങളും, അക്കങ്ങളും, പിന്നെ അടിവരയും മാത്രം reserved: കരുതിവച്ചു + admin/webhook: + attributes: + url: + invalid: ഇതൊരു തെറ്റിയ വിലാസമാണു് + doorkeeper/application: + attributes: + website: + invalid: ഇതൊരു തെറ്റിയ വിലാസമാണു് status: attributes: reblog: 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/activerecord.zh-TW.yml b/config/locales/activerecord.zh-TW.yml index 7422550660217b..113d881ae59c1d 100644 --- a/config/locales/activerecord.zh-TW.yml +++ b/config/locales/activerecord.zh-TW.yml @@ -46,7 +46,7 @@ zh-TW: user: attributes: email: - blocked: 使用不被允許的電子郵件供應商 + blocked: 使用不被允許的電子郵件提供商 unreachable: 該電子郵件地址似乎無法使用 role_id: elevated: 不能高於您目前的角色 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..1a6f0da8c669bb 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1394,20 +1394,6 @@ ar: merge_long: الإبقاء علي التسجيلات الحالية وإضافة الجديدة overwrite: إعادة الكتابة overwrite_long: استبدال التسجيلات الحالية بالجديدة - overwrite_preambles: - blocking_html: أنت على وشك استبدال قائمة الحظر بما يصل إلى %{total_items} من الحسابات من %{filename}. - bookmarks_html: أنت على وشك استبدال إشاراتك المرجعية بما يصل إلى %{total_items} من المشاركات من %{filename}. - domain_blocking_html: أنت على وشك إرشاداتك المرجعية بما يصل إلى %{total_items} من المشاركات من %{filename}. - following_html: أنت على وشك متابعة ما يصل إلى %{total_items} من الحسابات من %{filename} والتوقف عن متابعة أي شخص آخر. - lists_html: إنّك بصدد استبدال قوائمك بمحتوى مِلَفّ %{filename}. ما يُقارِب %{total_items} حسابًا سوف تُضاف إلى قوائم جديدة. - muting_html: أنت على وشك استبدال قائمة الحسابات الصامتة بما يصل إلى %{total_items} من الحسابات من %{filename}. - preambles: - blocking_html: أنت على وشك حظر ما يصل إلى %{total_items} من الحسابات من %{filename}. - bookmarks_html: أنت على وشك إضافة ما يصل إلى %{total_items} من المشاركات من %{filename} إلى إشاراتك المرجعية. - domain_blocking_html: أنت على وشك حظر ما يصل إلى %{total_items} من النطاقات من %{filename}. - following_html: أنت على وشك متابعة ما يصل إلى %{total_items} من الحسابات من %{filename}. - lists_html: أنت على وشك إضافة ما يصل إلى %{total_items} حسابات من %{filename} إلى قوائمك. سيتم إنشاء قوائم جديدة في حالة عدم وجود قائمة للإضافة إليها. - muting_html: أنت على وشك تجاهل ما يصل إلى %{total_items} من الحسابات
من %{filename}. preface: بإمكانك استيراد بيانات قد قُمتَ بتصديرها مِن مثيل خادم آخَر، كقوائم المستخدِمين الذين كنتَ تتابِعهم أو قُمتَ بحظرهم. recent_imports: الاستيرادات الحديثة states: @@ -1719,7 +1705,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..a3310f0d4631f3 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -449,7 +449,7 @@ ast: your_token: El pase d'accesu auth: delete_account: Desaniciu de la cuenta - delete_account_html: Si quies desaniciar la cuenta, pues facelo equí. Va pidísete que confirmes l'aición. + delete_account_html: Si quies desaniciar la cuenta, pues facelo equí. Vamos pidite que confirmes l'aición. description: prefix_sign_up: "¡Rexístrate güei en Mastodon!" didnt_get_confirmation: "¿Nun recibiesti l'enllaz de confirmación?" @@ -645,6 +645,7 @@ ast: errors: missing_also_known_as: nun ye un nomatu d'esta cuenta move_to_self: nun pue ser la cuenta actual + incoming_migrations: Migración d'otra cuenta incoming_migrations_html: Pa migrar d'otra cuenta a esta, primero tienes de crear un nomatu de cuenta. warning: followers: Esta aición va mover tolos siguidores de la cuenta actual a la nueva @@ -726,6 +727,7 @@ ast: over_daily_limit: Superesti la llende de %{limit} artículos programaos pa güei over_total_limit: Superesti la llende de %{limit} artículos programaos sessions: + activity: Última actividá browser: Restolador browsers: alipay: Alipay @@ -774,11 +776,11 @@ 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 migrate: Migración de la cuenta + notifications: Avisos per corréu electrónicu preferences: Preferencies profile: Perfil públicu relationships: Perfiles que sigues y te siguen diff --git a/config/locales/be.yml b/config/locales/be.yml index d45f443b75f06c..b627672b2d12c9 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -1391,20 +1391,6 @@ be: merge_long: Захаваць існуючыя запісы і дадаць новыя overwrite: Перазапісаць overwrite_long: Замяніць бягучыя запісы на новыя - overwrite_preambles: - blocking_html: Вы збіраецеся замяніць свой спіс блакіровак на %{total_items} уліковых запісаў з файла %{filename}. - bookmarks_html: Вы збіраецеся замяніць свае закладкі на %{total_items} допісаў з файла %{filename}. - domain_blocking_html: Вы збіраецеся замяніць свой спіс блакіроўкі даменаў на %{total_items} даменаў з файла %{filename}. - following_html: Вы збіраецеся падпісацца на %{total_items} уліковых запісаў з файла %{filename} і адпісацца ад усіх іншых карыстальнікаў. - lists_html: Вы збіраецеся замяніць свае спісы змесцівам з %{filename}. Да %{total_items} уліковых запісаў будуць дададзены ў новыя спісы. - muting_html: Вы збіраецеся замяніць свой спіс ігнараваных уліковых запісаў на %{total_items} уліковых запісаў з файла %{filename}. - preambles: - blocking_html: Вы збіраецеся заблакіраваць да %{total_items} уліковых запісаў з файла%{filename}. - bookmarks_html: Вы збіраецеся дадаць да %{total_items} паведамленняў з файла %{filename} у вашы закладкі. - domain_blocking_html: Вы збіраецеся заблакіраваць да %{total_items} даменаў з файла %{filename}. - following_html: Вы збіраецеся падпісацца на%{total_items} уліковых запісаў з файла %{filename}. - lists_html: Вы збіраецеся дадаць да %{total_items} уліковых запісаў з %{filename} у вашы спісы. Новыя спісы будуць створаны, калі іх няма. - muting_html: Вы збіраецеся ігнараваць да %{total_items} уліковых запісаў з файла %{filename}. preface: Вы можаце імпартаваць даныя, экспартаваныя вамі з іншага сервера, напрыклад, спіс людзей, на якіх вы падпісаны або якіх блакуеце. recent_imports: Нядаўнія імпарты states: @@ -1722,7 +1708,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..1fdd0e3533bcde 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -1300,20 +1300,6 @@ bg: merge_long: Пази текущите записи и добавя нови overwrite: Презаписване overwrite_long: Заменя текущите записи с новите - overwrite_preambles: - blocking_html: На път сте да замените списъка си с блокирани с до %{total_items} акаунта от %{filename}. - bookmarks_html: На път сте да замените списъка си с отметки с до %{total_items} публикации от %{filename}. - domain_blocking_html: На път сте да замените списъка си с блокирани домейни с до %{total_items} домейна от %{filename}. - following_html: На път сте да последвате до %{total_items} акаунта от %{filename} и да спрете да следвате някой друг. - lists_html: На път сте да замените списъците си със съдържание от %{filename}. До %{total_items} акаунта ще се добавят към новите списъци. - muting_html: На път сте да замените списъка си със заглушени акаунти с до %{total_items} акаунта от %{filename}. - preambles: - blocking_html: На път сте да блокирате до %{total_items} акаунта от %{filename}. - bookmarks_html: На път сте да добавите до %{total_items} публикации от %{filename} в отметките си. - domain_blocking_html: На път сте да блокирате до %{total_items} домейна от %{filename}. - following_html: На път сте да последвате до %{total_items} акаунта от %{filename}. - lists_html: На път сте да добавите до %{total_items} акаунта от %{filename} към вашите списъци. Нови списъци ще се сътворят, ако няма списъци за добавяне. - muting_html: На път сте да заглушите до %{total_items} акаунта от %{filename}. preface: Можеш да импортираш някои данни, като например всички хора, които следваш или блокираш в акаунта си на тази инстанция, от файлове, създадени чрез експорт в друга инстанция. recent_imports: Скорошни внасяния states: @@ -1617,7 +1603,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..9d861fa30c3109 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -21,6 +21,7 @@ ca: one: Tut other: Tuts posts_tab_heading: Tuts + self_follow_error: No es permet seguir el compte propi admin: account_actions: action: Realitza l'acció @@ -446,6 +447,7 @@ ca: title: Blocar el nou domini de correu-e no_email_domain_block_selected: No s'han canviat els bloqueigs de domini perquè no se n'ha seleccionat cap not_permitted: No permés + resolved_dns_records_hint_html: El nom del domini resol als següents dominis MX, que són els responsables finals per a acceptar els correus. Blocar un domini MX blocarà els registres des de qualsevol adreça de correu que utilitzi el mateix domini MX, encara que el nom visible sigui diferent. Vigileu de no blocar els grans proveïdors de correu. resolved_through_html: Resolt mitjançant %{domain} title: Dominis de correu-e blocats export_domain_allows: @@ -800,6 +802,7 @@ ca: destroyed_msg: La càrrega al lloc s'ha suprimit correctament! software_updates: critical_update: Crítica - si us plau, actualitza ràpidament + description: Es recomana de mantenir actualizada la instal·lació de Mastodon per a beneficiar-se de les darreres correccions i característiques. A més, de vegades és fonamental actualitzar-la per a evitar problemes de seguretat. Per això Mastodon comprova si hi ha actualitzacions cada 30 minuts i us notificarà d'acord amb les preferències de notificacions de correu electrònic. documentation_link: Més informació release_notes: Notes de llançament title: Actualitzacions disponibles @@ -873,6 +876,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. @@ -1152,6 +1158,7 @@ ca: account_status: Estat del compte confirming: Esperant que es completi la confirmació del correu-e. functional: El teu compte està completament operatiu. + pending: La vostra sol·licitud està pendent de revisió pel nostre personal. Això pot trigar una mica. Rebreu un correu electrònic quan s'aprovi. redirecting_to: El teu compte és inactiu perquè actualment està redirigint a %{acct}. self_destruct: Com que %{domain} tanca, només tindreu accés limitat al vostre compte. view_strikes: Veure accions del passat contra el teu compte @@ -1159,7 +1166,6 @@ ca: use_security_key: Usa clau de seguretat author_attribution: example_title: Text d'exemple - hint_html: Controleu com se us acredita quan els enllaços es comparteixen a Mastodon. more_from_html: Més de %{name} s_blog: Blog de %{name} title: Atribució d'autor @@ -1199,6 +1205,9 @@ ca: before: 'Abans de procedir, llegiu amb cura aquestes notes:' caches: El contingut que ha estat memoritzat en la memòria cau per altres servidors pot persistir data_removal: Els teus tuts i altres dades seran permanentment eliminades + email_change_html: Podeu canviar l'adreça de correu sense eliminar el vostre compte + email_contact_html: Si encara no arriba, podeu enviar un correu-e a %{email} per a demanar ajuda + email_reconfirmation_html: Si no rebeu el correu electrònic de confirmació , podeu tornar-lo a demanar irreversible: No seràs capaç de restaurar o reactivar el teu compte more_details_html: Per a més detalls, llegeix la política de privadesa. username_available: El teu nom d'usuari esdevindrà altre cop disponible @@ -1356,20 +1365,6 @@ ca: merge_long: Mantenir els registres existents i afegir-ne de nous overwrite: Sobreescriu overwrite_long: Reemplaça els registres actuals amb els nous - overwrite_preambles: - blocking_html: Ets a punt per a reemplaçar la teva llista de bloquejos de fins a %{total_items} comptes des de %{filename}. - bookmarks_html: Ets a punt de reemplaçar els teus marcadors de fins a %{total_items} tuts des de %{filename}. - domain_blocking_html: Ets a punt de reemplaçar la teva llista de dominis bloquejats de fins a %{total_items} dominis des de %{filename}. - following_html: Ets a punt de seguir fins a %{total_items} comptes des de %{filename} i deixar de seguir a la resta. - lists_html: Estàs a punt de reemplaçar les teves llistes amb contactes de %{filename}. S'afegiran fins a %{total_items} comptes a les noves llistes. - muting_html: Ets a punt de reemplaçar la teva llista de comptes silenciats de fins a %{total_items} comptes des de %{filename}. - preambles: - blocking_html: Ets a punt de bloquejar fins a %{total_items} comptes des de %{filename}. - bookmarks_html: Ets a punt d'afegir fins a %{total_items} tuts des de %{filename} als teus marcadors. - domain_blocking_html: Ets a punt de bloquejar fins a %{total_items} dominis des de %{filename}. - following_html: Ets a punt de seguir fins a %{total_items} comptes des de %{filename}. - lists_html: Estàs a punt d'afegir %{total_items} comptes de %{filename} a les teves llistes. Es crearan noves llistes si no hi ha cap llista on afegir-los. - muting_html: Ets a punt de silenciar fins a %{total_items} comptes des de %{filename}. preface: Pots importar algunes les dades que has exportat des d'un altre servidor, com ara el llistat de les persones que estàs seguint o bloquejant. recent_imports: Importacions recents states: @@ -1686,7 +1681,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..15211b928a433e 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1348,20 +1348,6 @@ cs: merge_long: Ponechat existující záznamy a přidat nové overwrite: Přepsat overwrite_long: Nahradit aktuální záznamy novými - overwrite_preambles: - blocking_html: Chystáte se nahradit váš seznam bloků s %{total_items} účtami od %{filename}. - bookmarks_html: Chystáte se nahradit své záložky s %{total_items} příspěvků z %{filename}. - domain_blocking_html: Chystáte se nahradit seznam stránek s %{total_items} stránek z %{filename}. - following_html: Chystáte se sledovat%{total_items} účtů z %{filename} a přestanete sledovat všechny ostatní. - lists_html: Chystáte se nahradit své seznamy obsahem %{filename}. Až %{total_items} účtů budou přidány do nových seznamů. - muting_html: Chystáte se nahradit seznam skrytých účtů s %{total_items} účtami z %{filename}. - preambles: - blocking_html: Chystáte se blokovat%{total_items} účtů z %{filename}. - bookmarks_html: Chystáte se přidat až %{total_items} příspěvků z %{filename} do vašich záložek. - domain_blocking_html: Chystáte se blokovat%{total_items} stránek z %{filename}. - following_html: Chystáte se sledovat%{total_items} účtů z %{filename}. - lists_html: Chystáte se přidat %{total_items} účtů z %{filename} do vaších seznamů. Nové seznamy budou vytvořeny, pokud neexistuje žádný seznam, do kterého by bylo možné přidat. - muting_html: Chystáte se skrýt%{total_items} účtů z %{filename}. preface: Můžete importovat data, která jste exportovali z jiného serveru, jako například seznam lidí, které sledujete či blokujete. recent_imports: Nedávné importy states: @@ -1666,7 +1652,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..2d6a0eb38d118a 100644 --- a/config/locales/cy.yml +++ b/config/locales/cy.yml @@ -29,6 +29,7 @@ cy: two: Postiadau zero: Postiadau posts_tab_heading: Postiadau + self_follow_error: Chewch chi ddim dilyn eich cyfrif eich hun admin: account_actions: action: Cyflawni gweithred @@ -918,7 +919,7 @@ cy: message_html: Mae gan eich clwstwr Elasticsearch fwy nag un nod, ond nid yw Mastodon wedi'i ffurfweddu i'w defnyddio. elasticsearch_preset_single_node: action: Darllenwch y ddogfennaeth - message_html: Dim ond un nod sydd gan eich clwstwr Elasticsearch, mae angen gosod ES_PRESET i single_node_cluster . + message_html: Dim ond un nod sydd gan eich clwstwr Elasticsearch, mae angen gosod ES_PRESET i single_node_cluster. elasticsearch_reset_chewy: message_html: Mae eich mynegai system Elasticsearch wedi dyddio oherwydd newid gosodiad. Rhedwch chwiliad tootctl search deploy --reset-chewy i'w ddiweddaru. elasticsearch_running_check: @@ -931,6 +932,9 @@ cy: message_html: Nid ydych wedi diffinio unrhyw reolau gweinydd. sidekiq_process_check: message_html: Does dim proses Sidekiq yn rhedeg ar gyfer y ciw(iau) %{value}. Adolygwch eich ffurfweddiad Sidekiq + software_version_check: + action: Gweld y diweddariadau sydd ar gael + message_html: Mae diweddariad Mastodon ar gael. software_version_critical_check: action: Gweld y diweddariadau sydd ar gael message_html: Mae diweddariad hanfodol Mastodon ar gael, diweddarwch cyn gynted â phosibl. @@ -1059,7 +1063,7 @@ cy: webhooks: add_new: Ychwanegu diweddbwynt delete: Dileu - description_html: Mae bachyn gwe yn galluogi Mastodon i wthio hysbysiadau amser real am ddigwyddiadau a ddewiswyd i'ch cais eich hun, fel y gall eich cais ysgogi ymatebion yn awtomatig . + description_html: Mae bachyn gwe yn galluogi Mastodon i wthio hysbysiadau amser real am ddigwyddiadau a ddewiswyd i'ch cais eich hun, fel y gall eich cais ysgogi ymatebion yn awtomatig. disable: Analluogi disabled: Wedi'i analluogi edit: Golygu diweddbwynt @@ -1123,7 +1127,7 @@ cy: created_msg: Wedi creu enw arall yn llwyddiannus. Gallwch nawr ddechrau symud o'r hen gyfrif. deleted_msg: Wedi tynnu enw arall yn llwyddiannus. Ni fydd symud o'r cyfrif hynny i'r cyfrif hon yn bosib. empty: Nid oes gennych enwau eraill. - hint_html: Os ydych chi am symud o gyfrif arall i'r un hwn, gallwch greu enw arall yma, sy'n ofynnol cyn y gallwch symud ymlaen i symud dilynwyr o'r hen gyfrif i'r un hwn. Mae'r weithred hon ynddo'i hun yn ddiniwed ac yn wrthdroadwy. Mae'r mudo cyfrif yn cael ei wneud o'r hen gyfrif . + hint_html: Os ydych chi am symud o gyfrif arall i'r un hwn, gallwch greu enw arall yma, sy'n ofynnol cyn y gallwch symud ymlaen i symud dilynwyr o'r hen gyfrif i'r un hwn. Mae'r weithred hon ynddo'i hun yn ddiniwed ac yn wrthdroadwy. Mae'r mudo cyfrif yn cael ei wneud o'r hen gyfrif. remove: Dadgysylltu'r enw arall appearance: advanced_web_interface: Rhyngwyneb gwe uwch @@ -1234,9 +1238,11 @@ cy: use_security_key: Defnyddiwch allwedd diogelwch author_attribution: example_title: Testun enghreifftiol - hint_html: Rheolwch sut rydych chi'n cael eich canmol pan fydd dolenni'n cael eu rhannu ar Mastodon. + hint_html: Ydych chi'n ysgrifennu erthyglau newyddion neu flog y tu allan i Mastodon? Rheolwch sut y byddwch yn cael eich cydnabod pan fyddan nhw'n cael eu rhannu ar Mastodon. + instructions: 'Gwnewch yn siŵr fod y cod hwn yn HTML eich erthygl:' more_from_html: Mwy gan %{name} s_blog: Blog %{name} + then_instructions: Yna, ychwanegwch enw parth y cyhoeddiad yn y maes isod. title: Priodoliad awdur challenge: confirm: Parhau @@ -1364,7 +1370,7 @@ cy: add_keyword: Ychwanegu allweddair keywords: Allweddeiriau statuses: Postiadau unigol - statuses_hint_html: Mae'r hidlydd hwn yn berthnasol i ddewis postiadau unigol pa un ai a ydynt yn cyfateb i'r allweddeiriau isod. Adolygu neu ddileu postiadau o'r hidlydd . + statuses_hint_html: Mae'r hidlydd hwn yn berthnasol i ddewis postiadau unigol pa un ai a ydynt yn cyfateb i'r allweddeiriau isod. Adolygu neu ddileu postiadau o'r hidlydd. title: Golygu hidlydd errors: deprecated_api_multiple_keywords: Nid oes modd newid y paramedrau hyn o'r cais hwn oherwydd eu bod yn berthnasol i fwy nag un allweddair hidlo. Defnyddiwch raglen fwy diweddar neu'r rhyngwyneb gwe. @@ -1463,19 +1469,91 @@ cy: overwrite: Trosysgrifio overwrite_long: Amnewid y cofnodion cyfredol gyda'r rhai newydd overwrite_preambles: - blocking_html: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{total_items} o gyfrifon o %{filename} . - bookmarks_html: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{total_items} o bostiadau gan %{filename} . - domain_blocking_html: Rydych ar fin amnewid eich rhestr rhwystro parth gyda hyd at %{total_items} parth o %{filename} . - following_html: Rydych ar fin dilyn hyd at %{total_items} o gyfrifon o %{filename} a pheidio a ddilyn unrhyw un arall . - lists_html: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename} . Bydd hyd at %{total_items} o gyfrifon yn cael eu hychwanegu at restrau newydd. - muting_html: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{total_items} o gyfrifon o %{filename} . + blocking_html: + few: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + many: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + one: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + other: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + two: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + zero: Rydych ar fin amnewid eich rhestr rhwystro gyda hyd at %{count} o gyfrifon o %{filename}. + bookmarks_html: + few: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{count} postiadau gan %{filename}. + many: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{count} postiadau gan %{filename}. + one: Rydych ar fin disodli eich nodau tudalen gyda hyd at %{count} postiad o %{filename}. + other: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{count} postiadau gan %{filename}. + two: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{count} postiadau gan %{filename}. + zero: Rydych ar fin amnewid eich nodau tudalen gyda hyd at %{count} postiadau gan %{filename}. + domain_blocking_html: + few: Rydych ar fin amnewid eich rhestr rhwystro parthau gyda hyd at %{count} parth o %{filename}. + many: Rydych ar fin amnewid eich rhestr rhwystro parthau gyda hyd at %{count} parth o %{filename}. + one: Rydych ar fin disodli eich rhestr blociau parth gyda hyd at %{count} parth o %{filename}. + other: Rydych ar fin amnewid eich rhestr rhwystro parthau gyda hyd at %{count} parth o %{filename}. + two: Rydych ar fin amnewid eich rhestr rhwystro parthau gyda hyd at %{count} parth o %{filename}amnewid eich rhestr rhwystro parthau gyda hyd at %{count} parth o %{filename}. + following_html: + few: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename} a pheidio â dilyn unrhyw un arall. + many: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename} a pheidio â dilyn unrhyw un arall. + one: Rydych ar fin dilyn hyd at %{count} gyfrif o %{filename} a rhoi'r gorau i ddilyn unrhyw un arall. + other: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename} a pheidio â dilyn unrhyw un arall. + two: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename} a pheidio â dilyn unrhyw un arall. + zero: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename} a pheidio â dilyn unrhyw un arall. + lists_html: + few: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + many: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + one: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + other: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + two: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + zero: Rydych ar fin amnewid eich rhestrau gyda chynnwys %{filename}. Bydd hyd at %{count} cyfrif yn cael eu hychwanegu at restrau newydd. + muting_html: + few: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{count} o gyfrifon o %{filename}. + many: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{count} o gyfrifon o %{filename}. + one: Rydych ar fin disodli eich rhestr o gyfrifon wedi'u tewi am hyd at %{count} gyfrif o %{filename}. + other: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{count} o gyfrifon o %{filename}. + two: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{count} o gyfrifon o %{filename}. + zero: Rydych ar fin amnewid eich rhestr o gyfrifon tawel gyda hyd at %{count} o gyfrifon o %{filename}. preambles: - blocking_html: Rydych ar fin rhwystro hyd at %{total_items} o gyfrifon o %{filename} . - bookmarks_html: Rydych ar fin ychwanegu hyd at %{total_items} o bostiadau o %{filename} at eich nodau tudalen . - domain_blocking_html: Rydych ar fin rhwystro hyd at %{total_items} parth o %{filename} . - following_html: Rydych ar fin dilyn hyd at %{total_items} cyfrif gan %{filename} . - lists_html: Rydych ar fin ychwanegu hyd at %{total_items} o gyfrifon o %{filename} at eich rhestrau . Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. - muting_html: Rydych ar fin anwybyddu hyd at %{total_items} cyfrif o %{filename}. + blocking_html: + few: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + many: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + one: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + other: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + two: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + zero: Rydych ar fin rhwystro hyd at %{count} cyfrif o %{filename}. + bookmarks_html: + few: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + many: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + one: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + other: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + two: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + zero: Rydych ar fin ychwanegu hyd at %{count} pbostiad o %{filename} at eich nodau tudalen. + domain_blocking_html: + few: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + many: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + one: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + other: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + two: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + zero: Rydych ar fin rhwystro hyd at %{count} parth o %{filename}. + following_html: + few: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename}. + many: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename}. + one: Rydych ar fin dilyn hyd at %{count} gyfrif o %{filename}. + other: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename}. + two: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename}. + zero: Rydych ar fin dilyn hyd at %{count} cyfrif gan %{filename}. + lists_html: + few: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + many: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + one: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + other: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + two: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + zero: Rydych ar fin ychwanegu hyd at %{count} cyfrif o %{filename} at eich rhestrau. Bydd rhestrau newydd yn cael eu creu os nad oes rhestr i ychwanegu ati. + muting_html: + few: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. + many: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. + one: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. + other: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. + two: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. + zero: Rydych ar fin tewi hyd at %{count} cyfrif o %{filename}. preface: Gallwch fewnforio data rydych chi wedi'i allforio o weinydd arall, fel rhestr o'r bobl rydych chi'n eu dilyn neu'n eu blocio. recent_imports: Mewnforion diweddar states: @@ -1558,7 +1636,7 @@ cy: follow_request: e-byst ceisiadau dilyn mention: e-byst hysbysu crybwylliadau reblog: e-byst hysbysiadau hybu - resubscribe_html: Os ydych wedi dad-danysgrifio trwy gamgymeriad, gallwch ail-danysgrifio drwy'ch gosodiadau hysbysu e-bost . + resubscribe_html: Os ydych wedi dad-danysgrifio trwy gamgymeriad, gallwch ail-danysgrifio drwy'ch gosodiadau hysbysu e-bost. success_html: Ni fyddwch bellach yn derbyn %{type} ar gyfer Mastodon ar %{domain} i'ch e-bost am %{email}. title: Dad-danysgrifio media_attachments: @@ -1580,7 +1658,7 @@ cy: on_cooldown: Rydych ar amser allan followers_count: Dilynwyr ar adeg y symud incoming_migrations: Symud o gyfrif wahanol - incoming_migrations_html: I symud o gyfrif arall i'r un hwn, yn gyntaf mae angen i chi greu enwarall (alias) cyfrif . + incoming_migrations_html: I symud o gyfrif arall i'r un hwn, yn gyntaf mae angen i chi greu enwarall (alias) cyfrif. moved_msg: Mae eich cyfrif bellach yn ailgyfeirio i %{acct} ac mae eich dilynwyr yn cael eu symud drosodd. not_redirecting: Nid yw eich cyfrif yn ailgyfeirio i unrhyw gyfrif arall ar hyn o bryd. on_cooldown: Rydych chi wedi mudo'ch cyfrif yn ddiweddar. Bydd y swyddogaeth hon ar gael eto ymhen %{count} diwrnod. @@ -1595,7 +1673,7 @@ cy: cooldown: Ar ôl symud, bydd yna cyfnod aros na fydd modd i chi symud eto disabled_account: Ni fydd modd defnyddio'ch cyfrif cyfredol yn llawn wedyn. Fodd bynnag, bydd gennych fynediad i allforio data yn ogystal ag ail agor. followers: Bydd y weithred hon yn symud yr holl ddilynwyr o'r cyfrif cyfredol i'r cyfrif newydd - only_redirect_html: Fel arall, dim ond ailgyfeiriad y gallwch chi ei osod ar eich proffil . + only_redirect_html: Fel arall, dim ond ailgyfeiriad y gallwch chi ei osod ar eich proffil. other_data: Ni fydd unrhyw data arall yn cael ei symud yn awtomatig redirect: Bydd proffil eich cyfrif presennol yn cael ei diweddaru gyda hysbysiad ailgyfeirio ac yn cael ei eithrio o chwiliadau moderation: @@ -1796,7 +1874,7 @@ cy: delete: Dileu cyfrif development: Datblygu edit_profile: Golygu proffil - export: Allforio data + export: Allforio 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..6447afb4930381 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -21,6 +21,7 @@ da: one: Indlæg other: Indlæg posts_tab_heading: Indlæg + self_follow_error: Det er ikke tilladt at følge sin egen konto admin: account_actions: action: Udfør handling @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ da: use_security_key: Brug sikkerhedsnøgle author_attribution: example_title: Eksempeltekst - hint_html: Styrer, hvordan man krediteres, når links deles på Mastodon. + hint_html: Skriver du nyheder eller blogartikler uden for Mastodon? Styr, hvordan man bliver krediteret, når disse deles på Mastodon. + instructions: 'Sørg for, at denne kode er i artikelens HTML:' more_from_html: Flere fra %{name} s_blog: "%{name}s blog" + then_instructions: Tilføj dernæst publikationsdomænenavnet i feltet nedenfor. title: Forfattertilskrivning challenge: confirm: Fortsæt @@ -1363,19 +1369,43 @@ da: overwrite: Overskriv overwrite_long: Erstat aktuelle poster med de nye overwrite_preambles: - blocking_html: Du er ved at erstatte bloklisten med op til %{total_items} konti fra %{filename}. - bookmarks_html: Du er ved at erstatte bogmærkelisten med op til %{total_items} emner fra %{filename}. - domain_blocking_html: Du er ved at erstatte domæneblokeringslisten med op til %{total_items} domæner fra %{filename}. - following_html: Du er ved at følge op til %{total_items} konti fra %{filename} og stoppe med at følge alle andre. - lists_html: Du er ved at erstatte dine lister med indholdet af %{filename}. Op til %{total_items} konti tilføjes nye lister. - muting_html: Du er ved at erstatte listen over tavsgjorte konti med op til %{total_items} konti fra %{filename}. + blocking_html: + one: Man er ved at erstatte sin sortliste med %{count} konto fra %{filename}. + other: Man er ved at erstatte sin sortliste med optil %{count} konti fra %{filename}. + bookmarks_html: + one: Man er ved at erstatte sine bogmærker med %{count} post fra %{filename}. + other: Man er ved at erstatte sine bogmærker med op til %{count} poster fra %{filename}. + domain_blocking_html: + one: Man er ved at erstatte sin domænesortliste med %{count} domæne fra %{filename}. + other: Man er ved at erstatte sin domænesortliste med op til %{count} domæner fra %{filename}. + following_html: + one: Man er ved at følge %{count} konto fra %{filename} og stoppe med at følge andre. + other: Man er ved at følge %{count} konti fra %{filename} og stoppe med at følge andre. + lists_html: + one: Man er ved at erstatte sine lister med indhold fra %{filename}. %{count} konto føjes til nye lister. + other: Man er ved at erstatte sine lister med indhold fra %{filename}. Op til %{count} konti føjes til nye lister. + muting_html: + one: Man er ved at sin liste over en tavsgjort konto med %{count} konto fra %{filename}. + other: Man er ved at sin liste over tavsgjorte konti med op til %{count} konti fra %{filename}. preambles: - blocking_html: Du er ved at blokere op til %{total_items} konti fra %{filename}. - bookmarks_html: Du er ved at føje op til %{total_items} indlæg fra %{filename} til bogmærkelisten. - domain_blocking_html: Du er ved at blokere op til %{total_items} domæner fra %{filename}. - following_html: Du er ved at følge op til %{total_items} konti fra %{filename}. - lists_html: Du er ved at tilføje op til %{total_items} konti fra %{filename} til dine lister. Nye lister oprettes, hvis der ikke er nogen liste at føje konti til. - muting_html: Du er ved at tavsgøre op til %{total_items} konti fra %{filename}. + blocking_html: + one: Man er ved at blokere %{count} konto fra %{filename}. + other: Man er ved at blokere op til %{count} konti fra %{filename}. + bookmarks_html: + one: Man er ved at tilføje %{count} post fra %{filename} til sine bogmærker. + other: Man er ved at tilføje %{count} poster fra %{filename} til sine bogmærker. + domain_blocking_html: + one: Man er ved at blokere %{count} domæne fra %{filename}. + other: Man er ved at blokere op til %{count} domæner fra %{filename}. + following_html: + one: Man er ved at følge %{count} konto fra %{filename}. + other: Man er ved at følge op til%{count} konti fra %{filename}. + lists_html: + one: Man er ved at tilføje %{count} konto fra %{filename} til sine lister. Nye lister oprettes, hvis der ikke findes nogen liste at tilføje til. + other: Man er ved at tilføje %{count} konti fra %{filename} til sine lister. Nye lister oprettes, hvis der ikke findes nogen liste at tilføje til. + muting_html: + one: Man er ved at tavsgøre %{count} konto fra %{filename}. + other: Man er ved at tavsgøre op til %{count} konto fra %{filename}. preface: Du kan importere data, du har eksporteret fra en anden server, såsom en liste over folk du følger eller blokerer. recent_imports: Seneste importer states: @@ -1692,7 +1722,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..323579f25fdcfc 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -21,6 +21,7 @@ de: one: Beitrag other: Beiträge posts_tab_heading: Beiträge + self_follow_error: Es ist nicht erlaubt, deinem eigenen Konto zu folgen admin: account_actions: action: Aktion ausführen @@ -79,7 +80,7 @@ de: invite_request_text: Begründung für das Beitreten invited_by: Eingeladen von ip: IP-Adresse - joined: Beigetreten + joined: Mitglied seit location: all: Alle local: Lokal @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ de: use_security_key: Sicherheitsschlüssel verwenden author_attribution: example_title: Beispieltext - hint_html: Bestimme, wie du Anerkennungen durch geteilte Links auf Mastodon handhaben möchtest. + hint_html: Schreibst du außerhalb von Mastodon Nachrichtenartikel oder betreibst du einen Blog? Bestimme, wie du Anerkennungen durch geteilte Links auf Mastodon handhaben möchtest. + instructions: 'Der nachfolgende Code muss im HTML-Code deines Artikels sein:' more_from_html: Mehr von %{name} s_blog: Blog von %{name} + then_instructions: Ergänze die Domain, auf der deine Inhalte veröffentlicht werden in das unten stehende Feld. title: Anerkennung als Autor*in challenge: confirm: Fortfahren @@ -1363,19 +1369,43 @@ de: overwrite: Überschreiben overwrite_long: Bestehende Datensätze durch neue ersetzen overwrite_preambles: - blocking_html: Du bist dabei, deine Liste blockierter Konten durch bis zu %{total_items} Konten aus %{filename} zu ersetzen. - bookmarks_html: Du bist dabei, deine Lesezeichen durch bis zu %{total_items} Beiträge aus %{filename} zu ersetzen. - domain_blocking_html: Du bist dabei, deine Liste blockierter Domains durch bis zu %{total_items} Domains aus %{filename} zu ersetzen. - following_html: Du bist dabei, bis zu %{total_items} Konten aus %{filename} zu folgen und niemand anderes zu folgen. - lists_html: Du bist dabei, deine Listen durch den Inhalt aus %{filename} zu ersetzen. Es werden bis zu %{total_items} Konten zu neuen Listen hinzugefügt. - muting_html: Du bist dabei, deine Liste stummgeschalteter Konten durch bis zu %{total_items} Konten aus %{filename} zu ersetzen. + blocking_html: + one: Du bist dabei, deine Liste blockierter Konten aus %{filename} durch bis zu %{count} Konto zu ersetzen. + other: Du bist dabei, deine Liste blockierter Konten aus %{filename} durch bis zu %{count} Konten zu ersetzen. + bookmarks_html: + one: Du bist dabei, deine Lesezeichen aus %{filename} durch bis zu %{count} Beitrag zu ersetzen. + other: Du bist dabei, deine Lesezeichen aus %{filename} durch bis zu %{count} Beiträge zu ersetzen. + domain_blocking_html: + one: Du bist dabei, deine Liste blockierter Domains aus %{filename} durch bis zu %{count} Domain zu ersetzen. + other: Du bist dabei, deine Liste blockierter Domains aus %{filename} durch bis zu %{count} Domains zu ersetzen. + following_html: + one: Du bist dabei, bis zu %{count} Konto aus %{filename} zu folgen und allen anderen zu entfolgen. + other: Du bist dabei, bis zu %{count} Konten aus %{filename} zu folgen und allen anderen zu entfolgen. + lists_html: + one: Du bist dabei, deine Listen mit dem Inhalt aus %{filename} zu ersetzen. Bis zu %{count} Konto wird zu neuen Listen hinzugefügt. + other: Du bist dabei, deine Listen mit dem Inhalt aus %{filename} zu ersetzen. Bis zu %{count} Konten wird zu neuen Listen hinzugefügt. + muting_html: + one: Du bist dabei, deine Liste mit einem stummgeschalteten Konto aus %{filename} durch bis zu %{count} Konto zu ersetzen. + other: Du bist dabei, deine Liste stummgeschalteter Konten aus %{filename} durch bis zu %{count} Konten zu ersetzen. preambles: - blocking_html: Du bist dabei, bis zu %{total_items}%{total_items} Konten aus %{filename} zu blockieren. - bookmarks_html: Du bist dabei, bis zu %{total_items} Beiträge aus %{filename} zu deinen Lesezeichen hinzuzufügen. - domain_blocking_html: Du bist dabei, bis zu %{total_items} Domains aus %{filename} zu blockieren. - following_html: Du bist dabei, bis zu %{total_items} Konten aus %{filename} zu folgen. - lists_html: Du bist dabei, bis zu %{total_items} Konten aus %{filename} zu deinen Listen hinzuzufügen. Wenn es keine Liste gibt, zu der etwas hinzugefügt werden kann, dann werden neue Listen erstellt. - muting_html: Du bist dabei, bis zu %{total_items} Konten aus %{filename} stummzuschalten. + blocking_html: + one: Du bist dabei, bis zu %{count} Konto aus %{filename} zu blockieren. + other: Du bist dabei, bis zu %{count} Konten aus %{filename} zu blockieren. + bookmarks_html: + one: Du bist dabei, bis zu %{count} Beitrag aus %{filename} zu deinen Lesezeichen hinzuzufügen. + other: Du bist dabei, bis zu %{count} Beiträge aus %{filename} zu deinen Lesezeichen hinzuzufügen. + domain_blocking_html: + one: Du bist dabei, bis zu %{count} Domain aus %{filename} zu blockieren. + other: Du bist dabei, bis zu %{count} Domains aus %{filename} zu blockieren. + following_html: + one: Du bist dabei, bis zu %{count} Konto aus %{filename} zu folgen. + other: Du bist dabei, bis zu %{count} Konten aus %{filename} zu folgen. + lists_html: + one: Du bist dabei, bis zu %{count} Konto aus %{filename} zu deinen Listen hinzuzufügen. Wenn es keine Listen gibt, zu denen etwas hinzugefügt werden kann, dann werden neue Listen erstellt. + other: Du bist dabei, bis zu %{count} Konten aus %{filename} zu deinen Listen hinzuzufügen. Wenn es keine Listen gibt, zu denen etwas hinzugefügt werden kann, dann werden neue Listen erstellt. + muting_html: + one: Du bist dabei, bis zu %{count} Konto aus %{filename} stummzuschalten. + other: Du bist dabei, bis zu %{count} Konten aus %{filename} stummzuschalten. preface: Daten, die du von einem Mastodon-Server exportiert hast, kannst du hierher importieren. Das betrifft beispielsweise die Listen von Profilen, denen du folgst oder die du blockiert hast. recent_imports: Zuletzt importiert states: @@ -1422,7 +1452,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 +1930,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 @@ -1939,7 +1969,7 @@ de: extra_instructions_html: Hinweis: Der Link auf deiner Website kann unsichtbar sein. Der wichtige Teil ist rel="me", wodurch das Nachahmen von Personen auf Websites mit nutzergenerierten Inhalten verhindert wird. Du kannst auch ein link-Tag statt a im Header auf der Seite verwenden, jedoch muss der HTML-Code ohne das Ausführen von JavaScript zugänglich sein. here_is_how: So funktioniert’s hint_html: "Alle können ihre Identität auf Mastodon verifizieren. Basierend auf offenen Standards – jetzt und für immer kostenlos. Alles, was du brauchst, ist eine eigene Website. Wenn du von deinem Profil auf diese Website verlinkst, überprüfen wir, ob die Website zu deinem Profil zurückverlinkt, und zeigen einen visuellen Hinweis an." - instructions_html: Kopiere den unten stehenden Code und füge ihn in das HTML deiner Website ein. Trage anschließend die Adresse deiner Website in ein Zusatzfeld auf deinem Profil ein und speichere die Änderungen. Die Zusatzfelder befinden sich im Reiter „Profil bearbeiten“. + instructions_html: Kopiere den unten stehenden Code und füge ihn in den HTML-Code deiner Website ein. Trage anschließend die Adresse deiner Website in ein Zusatzfeld auf deinem Profil ein und speichere die Änderungen. Die Zusatzfelder befinden sich im Reiter „Profil bearbeiten“. verification: Verifizierung verified_links: Deine verifizierten Links website_verification: Website-Verifizierung diff --git a/config/locales/devise.eo.yml b/config/locales/devise.eo.yml index 193fecc757201a..88514ab5e2824f 100644 --- a/config/locales/devise.eo.yml +++ b/config/locales/devise.eo.yml @@ -6,7 +6,7 @@ eo: send_instructions: Vi ricevos retmesaĝon kun instrukcioj por konfirmi vian retadreson ene de kelkaj minutoj. Bonvolu kontroli vian spamujon se vi ne ricevis ĉi tiun retmesaĝon. send_paranoid_instructions: Se via retadreso ekzistas en nia datumbazo, vi ricevos retmesaĝon kun instrukcioj por konfirmi vian retadreson ene de kelkaj minutoj. Bonvolu kontroli vian spamujon se vi ne ricevis ĉi tiun retmesaĝon. failure: - already_authenticated: Vi jam salutis. + already_authenticated: Vi jam ensalutis. inactive: Via konto ankoraŭ ne estas konfirmita. invalid: Nevalida %{authentication_keys} aŭ pasvorto. last_attempt: Vi ankoraŭ povas provi unufoje antaŭ ol via konto estos ŝlosita. @@ -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,13 @@ 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. + extra: Ensaluto nun eblas uzante nur la ĵetonon generitan de la parigita tempbazita unufoja pasvorta aplikaĵo. subject: 'Mastodon: sekureca-ŝlosila aŭtentigo malebligita' title: Sekurecaj ŝlosiloj malaktivigitaj webauthn_enabled: + explanation: Sekurecŝlosila aŭtentigo estas ebligita por via konto. + 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..3df18d6f7a4978 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. @@ -51,7 +50,9 @@ ast: confirmations: revoke: "¿De xuru que quies facer esta aición?" index: + authorized_at: 'Data d''autorización: %{date}' description_html: Estes son les aplicaciones que puen acceder a la cuenta cola API. Si equí hai aplicaciones que nun conoces o hai dalguna aplicación que nun funciona correutamente, pues revocar el so accesu. + last_used_at: 'Últimu usu: %{date}' never_used: Enxamás s'usó scopes: Permisos title: Les aplicaciones qu'autoricesti 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..984eff887127c4 100644 --- a/config/locales/doorkeeper.el.yml +++ b/config/locales/doorkeeper.el.yml @@ -60,7 +60,7 @@ el: error: title: Εμφανίστηκε σφάλμα new: - prompt_html: Το %{client_name} θα ήθελε άδεια πρόσβασης στο λογαριασμό σου. Είναι μια εφαρμογή τρίτων. Αν δεν το εμπιστεύεσαι, τότε δεν πρέπει να το εγκρίνεις. + 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..eaf1bf69fb7673 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: "%{client_name} desea obtener permiso para acceder a tu cuenta. Aprueba esta solicitud solamente 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..fb135b1f96cf3b 100644 --- a/config/locales/doorkeeper.et.yml +++ b/config/locales/doorkeeper.et.yml @@ -60,7 +60,7 @@ 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." + prompt_html: "%{client_name} soovib saada ligipääsu su kontole. Kinnita see taotlus ainult siis, kui sa tunned ja usaldad seda allikat." 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..8e2bc864a27cd2 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: @@ -131,7 +130,7 @@ fa: favourites: برگزیده‌ها filters: پالایه‌ها follow: پی‌گیری، خموشی و مسدودی‌ها - follows: پی‌گرفتگان + follows: پی‌گرفتن‌ها lists: سیاهه‌ها media: پیوست‌های رسانه‌ای mutes: خموش‌ها 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..180c7e733f119b 100644 --- a/config/locales/doorkeeper.fy.yml +++ b/config/locales/doorkeeper.fy.yml @@ -60,7 +60,7 @@ 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." + prompt_html: "%{client_name} freget om tagong ta jo account. Keur dit fersyk allinnich goed as jo dizze boarne werkenne en fertrouwe." 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..5d7148b84b0284 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: @@ -69,7 +69,7 @@ gl: buttons: revoke: Retirar autorización confirmations: - revoke: Estás segura? + revoke: Tes certeza? index: authorized_at: Autorizada o %{date} description_html: Estas aplicacións poden acceder á túa conta usando a API. Se ves aplicacións que non recoñeces, ou hai comportamentos non consentidos dalgunha delas, podes revogar o acceso. 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..1fabd1b55f3f13 100644 --- a/config/locales/doorkeeper.is.yml +++ b/config/locales/doorkeeper.is.yml @@ -60,7 +60,7 @@ 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." + prompt_html: "%{client_name} vill fá heimild til að skoða aðganginn þinn. Ekki samþykkja þessa beiðni nema þú þekkir og treystir viðkomandi." 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..d44451c74630ce 100644 --- a/config/locales/doorkeeper.ja.yml +++ b/config/locales/doorkeeper.ja.yml @@ -60,7 +60,7 @@ ja: error: title: エラーが発生しました new: - prompt_html: "%{client_name}があなたのアカウントにアクセスする許可を求めています。心当たりが無い場合はアクセス許可しないでください。" + 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..ca8271ebf1c5d1 100644 --- a/config/locales/doorkeeper.sv.yml +++ b/config/locales/doorkeeper.sv.yml @@ -60,7 +60,7 @@ 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." + prompt_html: "%{client_name} vill ha behörighet att komma åt ditt konto. Godkänn bara denna begäran om du känner igen och litar på källan." review_permissions: Granska behörigheter title: Godkännande krävs show: @@ -133,7 +133,7 @@ sv: follow: Följare, mjutade och blockerade follows: Följer lists: Listor - media: Mediabilagor + media: Mediebilagor mutes: Tystade användare notifications: Aviseringar profile: Din Mastodon-profil 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..2219599c57653d 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 @@ -150,30 +150,30 @@ vi: title: Đăng nhập bằng OAuth 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: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 - admin:read:ip_blocks: đọc thông tin nhạy cảm của tất cả các IP chặn + admin:read:accounts: đọc thông tin nhạy cảm của mọi tài khoản + admin:read:canonical_email_blocks: đọc thông tin nhạy cảm của mọi khối email biến thể + admin:read:domain_allows: đọc thông tin nhạy cảm của mọi máy chủ liên hợp + admin:read:domain_blocks: đọc thông tin nhạy cảm của mọi máy chủ chặn + admin:read:email_domain_blocks: đọc thông tin nhạy cảm của mọi tên miền email chặn + admin:read:ip_blocks: đọc thông tin nhạy cảm của mọi IP chặn admin:read:reports: đọc thông tin của các báo cáo và các tài khoản bị báo cáo admin:write: sửa đổi tất cả dữ liệu trên máy chủ admin:write:accounts: áp đặt hành động kiểm duyệt trên tài khoản - admin:write:canonical_email_blocks: áp đặt kiểm duyệt đối với chặn email + admin:write:canonical_email_blocks: áp đặt kiểm duyệt đối với chặn email biến thể admin:write:domain_allows: áp đặt kiểm duyệt đối với các email cho phép admin:write:domain_blocks: áp đặt kiểm duyệt đối với các tên miền chặn admin:write:email_domain_blocks: áp đặt kiểm duyệt đối với các tên miền email chặn admin:write:ip_blocks: áp đặt kiểm duyệt với các IP chặn admin:write:reports: áp đặt kiểm duyệt với các báo cáo crypto: dùng mã hóa đầu cuối - follow: sửa đổi các mối quan hệ tài khoản - profile: chỉ đọc thông tin tài khoản cơ bản + follow: sửa đổi các mối quan hệ + profile: chỉ xem thông tin tài khoản cơ bản push: nhận thông báo đẩy read: đọc mọi dữ liệu tài khoản read:accounts: xem thông tin tài khoản read:blocks: xem những người đã chặn read:bookmarks: xem tút đã lưu - read:favourites: xem lượt thích + read:favourites: xem tút đã thích read:filters: xem bộ lọc read:follows: xem những người theo dõi read:lists: xem danh sách @@ -182,7 +182,7 @@ vi: read:reports: xem báo cáo của bạn read:search: tìm kiếm read:statuses: xem toàn bộ tút - write: sửa đổi mọi dữ liệu tài khoản của bạn + write: sửa đổi mọi dữ liệu tài khoản write:accounts: sửa đổi trang hồ sơ write:blocks: chặn người và máy chủ write:bookmarks: sửa đổi những tút lưu @@ -194,5 +194,5 @@ vi: write:media: tải lên tập tin write:mutes: ẩn người và thảo luận write:notifications: xóa thông báo - write:reports: báo cáo người khác + write:reports: báo cáo write:statuses: đăng tút diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml index ee8c0cf13aa098..08f9885894d0d3 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: @@ -167,7 +167,7 @@ zh-CN: admin:write:reports: 对举报执行管理操作 crypto: 使用端到端加密 follow: 关注或屏蔽用户 - profile: 仅读取你账户中的个人资料信息 + profile: 仅读取你账号的个人资料信息 push: 接收你的账户的推送通知 read: 读取你的账户数据 read:accounts: 查看账号信息 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..0df31b246f9d7e 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} @@ -950,6 +953,7 @@ el: used_by_over_week: one: Χρησιμοποιήθηκε από ένα άτομο την τελευταία εβδομάδα other: Χρησιμοποιήθηκε από %{count} άτομα την τελευταία εβδομάδα + title: Προτάσεις και τάσεις trending: Τάσεις warning_presets: add_new: Πρόσθεση νέου @@ -1034,7 +1038,9 @@ el: guide_link_text: Μπορεί να συνεισφέρει ο οποιοσδήποτε. sensitive_content: Ευαίσθητο περιεχόμενο application_mailer: + notification_preferences: Αλλαγή προτιμήσεων email salutation: "%{name}," + settings: 'Αλλαγή προτιμήσεων email: %{link}' unsubscribe: Κατάργηση εγγραφής view: 'Προβολή:' view_profile: Προβολή προφίλ @@ -1081,6 +1087,7 @@ el: or_log_in_with: Ή συνδέσου με privacy_policy_agreement_html: Έχω διαβάσει και συμφωνώ με την πολιτική απορρήτου progress: + confirm: Επιβεβαίωση email details: Τα στοιχεία σας review: Η αξιολόγησή μας rules: Αποδοχή κανόνων @@ -1120,6 +1127,8 @@ el: view_strikes: Προβολή προηγούμενων ποινών εναντίον του λογαριασμού σας too_fast: Η φόρμα υποβλήθηκε πολύ γρήγορα, προσπαθήστε ξανά. use_security_key: Χρήση κλειδιού ασφαλείας + author_attribution: + example_title: Δείγμα κειμένου challenge: confirm: Συνέχεια hint_html: "Συμβουλή: Δεν θα σου ζητήσουμε τον κωδικό ασφαλείας σου ξανά για την επόμενη ώρα." @@ -1313,20 +1322,6 @@ el: merge_long: Διατήρηση των εγγράφων που υπάρχουν και προσθήκη των νέων overwrite: Αντικατάσταση overwrite_long: Αντικατάσταση των υπαρχόντων εγγράφων με τις καινούργιες - overwrite_preambles: - blocking_html: Πρόκειται να αντικαταστήσεις τη λίστα αποκλεισμών με έως και %{total_items} λογαριασμούς από το %{filename}. - bookmarks_html: Πρόκειται να αντικαταστήσεις τους σελιδοδείκτες σου με έως και %{total_items} αναρτήσεις από το %{filename}. - domain_blocking_html: Πρόκειται να αντικαταστήσεις τη λίστα αποκλεισμών τομέων με έως και %{total_items} τομείς από το %{filename}. - following_html: Πρόκειται να ακολουθήσεις μέχρι %{total_items} λογαριασμούς από το %{filename} και να σταματήσεις να ακολουθείς οποιονδήποτε άλλο. - lists_html: Πρόκειται να αντικαταστήσεις τις λίστες σου με περιεχόμενο του %{filename}. Μέχρι %{total_items} λογαριασμοί θα προστεθούν σε νέες λίστες. - muting_html: Πρόκειται να αντικαταστήσεις τη λίστα λογαριασμών σε σίγαση με έως και %{total_items} λογαριασμούς από το %{filename}. - preambles: - blocking_html: Πρόκειται να αποκλείσεις έως και %{total_items} λογαριασμούς από το %{filename}. - bookmarks_html: Πρόκειται να προσθέσεις μέχρι και %{total_items} αναρτήσεις από το %{filename} στους σελιδοδείκτες σου. - domain_blocking_html: Πρόκειται να αποκλείσεις έως και %{total_items} τομείς από το %{filename}. - following_html: Πρόκειται να ακολουθήσεις έως και %{total_items} λογαριασμούς από το %{filename}. - lists_html: Πρόκειται να προσθέσεις μέχρι και %{total_items} λογαριασμούς από το %{filename} στις λίστες σου. Θα δημιουργηθούν νέες λίστες αν δεν υπάρχει λίστα για προσθήκη. - muting_html: Πρόκειται να κάνεις σίγαση σε έως και %{total_items} λογαριασμούς από το %{filename}. preface: Μπορείς να εισάγεις τα δεδομένα που έχεις εξάγει από άλλο διακομιστή, όπως τη λίστα των ατόμων που ακολουθείς ή έχεις αποκλείσει. recent_imports: Πρόσφατες Εισαγωγές states: @@ -1339,7 +1334,10 @@ el: time_started: Ξεκίνησε στις titles: blocking: Εισαγωγή αποκλεισμένων λογαριασμών + bookmarks: Εισαγωγή σελιδοδεικτών + domain_blocking: Εισαγωγή αποκλεισμένων τομέων following: Εισαγωγή λογαριασμών που ακολουθείτε + lists: Εισαγωγή λιστών type: Τύπος εισαγωγής type_groups: destructive: Μπλοκ & σίγαση @@ -1348,6 +1346,7 @@ el: bookmarks: Σελιδοδείκτες domain_blocking: Λίστα αποκλεισμένων τομέων following: Λίστα ατόμων που ακολουθείτε + lists: Λίστες muting: Λίστα αποσιωπήσεων upload: Μεταμόρφωση invites: @@ -1362,6 +1361,7 @@ el: '86400': 1 μέρα expires_in_prompt: Ποτέ generate: Δημιουργία συνδέσμου πρόσκλησης + invalid: Αυτή η πρόσκληση δεν είναι έγκυρη invited_by: 'Σε προσκάλεσε ο/η:' max_uses: one: 1 χρήσης @@ -1385,6 +1385,11 @@ el: failed_sign_in_html: Αποτυχημένη προσπάθεια σύνδεσης με %{method} από %{ip} (%{browser}) successful_sign_in_html: Επιτυχής σύνδεση με %{method} από %{ip} (%{browser}) title: Ιστορικό ελέγχου ταυτότητας + mail_subscriptions: + unsubscribe: + action: Ναι, κατάργηση συνδρομής + complete: Η συνδρομή καταργήθηκε + title: Κατάργηση συνδρομής media_attachments: validations: images_and_video: Δεν γίνεται να προσθέσεις βίντεο σε ανάρτηση που ήδη περιέχει εικόνες @@ -1464,6 +1469,7 @@ el: update: subject: "%{name} επεξεργάστηκε μια ανάρτηση" notifications: + email_events: Συμβάντα για ειδοποιήσεις μέσω email email_events_hint: 'Επέλεξε συμβάντα για τα οποία θέλεις να λαμβάνεις ειδοποιήσεις μέσω email:' number: human: @@ -1504,12 +1510,18 @@ el: other: Άλλες posting_defaults: Προεπιλογές ανάρτησης public_timelines: Δημόσιες ροές + privacy: + privacy: Απόρρητο + search: Αναζήτηση privacy_policy: title: Πολιτική Απορρήτου reactions: errors: limit_reached: Το όριο διαφορετικών αντιδράσεων ξεπεράστηκε unrecognized_emoji: δεν είναι ένα αναγνωρισμένο emoji + redirects: + prompt: Αν εμπιστεύεστε αυτόν τον σύνδεσμο, κάντε κλικ σε αυτόν για να συνεχίσετε. + title: Αποχωρείτε από το %{instance}. relationships: activity: Δραστηριότητα λογαριασμού confirm_follow_selected_followers: Είσαι βέβαιος ότι θες να ακολουθήσεις τους επιλεγμένους ακόλουθους; @@ -1545,6 +1557,9 @@ el: over_daily_limit: Έχεις υπερβεί το όριο των %{limit} προγραμματισμένων αναρτήσεων για εκείνη τη μέρα over_total_limit: Έχεις υπερβεί το όριο των %{limit} προγραμματισμένων αναρτήσεων too_soon: Η προγραμματισμένη ημερομηνία πρέπει να είναι στο μέλλον + self_destruct: + lead_html: Δυστυχώς, το %{domain} κλείνει οριστικά. Αν είχατε λογαριασμό εκεί, δεν θα μπορείτε να συνεχίσετε τη χρήση του, αλλά μπορείτε ακόμα να ζητήσετε ένα αντίγραφο ασφαλείας των δεδομένων σας. + title: Αυτός ο διακομιστής κλείνει οριστικά sessions: activity: Τελευταία δραστηριότητα browser: Φυλλομετρητής @@ -1601,11 +1616,12 @@ el: delete: Διαγραφή λογαριασμού development: Ανάπτυξη edit_profile: Επεξεργασία προφίλ - export: Εξαγωγή δεδομένων + export: Εξαγωγή featured_tags: Παρεχόμενες ετικέτες import: Εισαγωγή import_and_export: Εισαγωγή και εξαγωγή migrate: Μετακόμιση λογαριασμού + notifications: Ειδοποιήσεις μέσω email preferences: Προτιμήσεις profile: Προφίλ relationships: Ακολουθείς και σε ακολουθούν @@ -1613,6 +1629,12 @@ el: strikes: Παραπτώματα από ομάδα συντονισμού two_factor_authentication: Πιστοποίηση 2 παραγόντων webauthn_authentication: Κλειδιά ασφαλείας + severed_relationships: + download: Λήψη (%{count}) + event_type: + account_suspension: Αναστολή λογαριασμού (%{target_name}) + domain_block: Αναστολή διακομιστή (%{target_name}) + type: Συμβάν statuses: attached: audio: @@ -1695,11 +1717,13 @@ el: contrast: Mastodon (Υψηλή αντίθεση) default: Mastodon (Σκοτεινό) mastodon-light: Mastodon (Ανοιχτόχρωμο) + system: Αυτόματο (θέμα συστήματος) time: formats: default: "%b %d, %Y, %H:%M" month: "%b %Y" time: "%H:%M" + with_time_zone: "%d %b %Y, %H:%M %Z" two_factor_authentication: add: Προσθήκη disable: Απενεργοποίηση 2FA @@ -1787,6 +1811,10 @@ el: feature_action: Μάθε περισσότερα feature_audience: Το Mastodon σού παρέχει μια μοναδική δυνατότητα διαχείρισης του κοινού σου χωρίς μεσάζοντες. Το Mastodon όταν αναπτύσσεται στη δική σου υποδομή σού επιτρέπει να ακολουθείς και να ακολουθείσαι από οποιονδήποτε άλλο συνδεδεμένο διακομιστή Mastodon και κανείς δεν τον ελέγχει, εκτός από σένα. feature_audience_title: Χτίσε το κοινό σου με σιγουριά + post_action: Σύνθεση + share_action: Κοινοποίηση + share_title: Μοιραστείτε το προφίλ σας στο Mastodon + sign_in_action: Σύνδεση subject: Καλώς ήρθες στο Mastodon title: Καλώς όρισες, %{name}! users: @@ -1796,7 +1824,10 @@ el: otp_lost_help_html: Αν χάσεις πρόσβαση και στα δύο, μπορείς να επικοινωνήσεις με %{email} signed_in_as: 'Έχεις συνδεθεί ως:' verification: + here_is_how: Δείτε πώς verification: Πιστοποίηση + verified_links: Οι επαληθευμένοι σύνδεσμοι σας + website_verification: Επαλήθευση ιστοτόπου webauthn_credentials: add: Προσθήκη νέου κλειδιού ασφαλείας create: diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 577978ce88d54f..fb284479f2ab58 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -875,6 +875,9 @@ en-GB: 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. @@ -1162,7 +1165,6 @@ en-GB: use_security_key: Use security key author_attribution: example_title: Sample text - hint_html: Control how you're credited when links are shared on Mastodon. more_from_html: More from %{name} s_blog: "%{name}'s Blog" title: Author attribution @@ -1363,19 +1365,43 @@ en-GB: overwrite: Overwrite overwrite_long: Replace current records with the new ones overwrite_preambles: - blocking_html: You are about to replace your block list with up to %{total_items} accounts from %{filename}. - bookmarks_html: You are about to replace your bookmarks with up to %{total_items} posts from %{filename}. - domain_blocking_html: You are about to replace your domain block list with up to %{total_items} domains from %{filename}. - following_html: You are about to follow up to %{total_items} accounts from %{filename} and stop following anyone else. - lists_html: You are about to replace your lists with contents of %{filename}. Up to %{total_items} accounts will be added to new lists. - muting_html: You are about to replace your list of muted accounts with up to %{total_items} accounts from %{filename}. + blocking_html: + one: You are about to replace your block list with up to %{count} account from %{filename}. + other: You are about to replace your block list with up to %{count} accounts from %{filename}. + bookmarks_html: + one: You are about to replace your bookmarks with up to %{count} post from %{filename}. + other: You are about to replace your bookmarks with up to %{count} posts from %{filename}. + domain_blocking_html: + one: You are about to replace your domain block list with up to %{count} domain from %{filename}. + other: You are about to replace your domain block list with up to %{count} domains from %{filename}. + following_html: + one: You are about to follow up to %{count} account from %{filename} and stop following anyone else. + other: You are about to follow up to %{count} accounts from %{filename} and stop following anyone else. + lists_html: + one: You are about to replace your lists with contents of %{filename}. Up to %{count} account will be added to new lists. + other: You are about to replace your lists with contents of %{filename}. Up to %{count} accounts will be added to new lists. + muting_html: + one: You are about to replace your list of muted account with up to %{count} account from %{filename}. + other: You are about to replace your list of muted accounts with up to %{count} accounts from %{filename}. preambles: - blocking_html: You are about to block up to %{total_items} accounts from %{filename}. - bookmarks_html: You are about to add up to %{total_items} posts from %{filename} to your bookmarks. - domain_blocking_html: You are about to block up to %{total_items} domains from %{filename}. - following_html: You are about to follow up to %{total_items} accounts from %{filename}. - lists_html: You are about to add up to %{total_items} accounts from %{filename} to your lists. New lists will be created if there is no list to add to. - muting_html: You are about to mute up to %{total_items} accounts from %{filename}. + blocking_html: + one: You are about to block up to %{count} account from %{filename}. + other: You are about to block up to %{count} accounts from %{filename}. + bookmarks_html: + one: You are about to add up to %{count} post from %{filename} to your bookmarks. + other: You are about to add up to %{count} posts from %{filename} to your bookmarks. + domain_blocking_html: + one: You are about to block up to %{count} domain from %{filename}. + other: You are about to block up to %{count} domains from %{filename}. + following_html: + one: You are about to follow up to %{count} account from %{filename}. + other: You are about to follow up to %{count} accounts from %{filename}. + lists_html: + one: You are about to add up to %{count} account from %{filename} to your lists. New lists will be created if there is no list to add to. + other: You are about to add up to %{count} accounts from %{filename} to your lists. New lists will be created if there is no list to add to. + muting_html: + one: You are about to mute up to %{count} account from %{filename}. + other: You are about to mute up to %{count} accounts from %{filename}. preface: You can import data that you have exported from another server, such as a list of the people you are following or blocking. recent_imports: Recent imports states: @@ -1692,7 +1718,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 3e0eb76b7a0d86..9bdd020d25e028 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -21,6 +21,7 @@ en: one: Post other: Posts posts_tab_heading: Posts + self_follow_error: Following your own account is not allowed admin: account_actions: action: Perform action @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ en: use_security_key: Use security key author_attribution: example_title: Sample text - hint_html: Control how you're credited when links are shared on Mastodon. + hint_html: Are you writing news or blog articles outside of Mastodon? Control how you get credited when they are shared on Mastodon. + instructions: 'Make sure this code is in your article''s HTML:' more_from_html: More from %{name} s_blog: "%{name}'s Blog" + then_instructions: Then, add the domain name of the publication in the field below. title: Author attribution challenge: confirm: Continue @@ -1364,19 +1370,43 @@ en: overwrite: Overwrite overwrite_long: Replace current records with the new ones overwrite_preambles: - blocking_html: You are about to replace your block list with up to %{total_items} accounts from %{filename}. - bookmarks_html: You are about to replace your bookmarks with up to %{total_items} posts from %{filename}. - domain_blocking_html: You are about to replace your domain block list with up to %{total_items} domains from %{filename}. - following_html: You are about to follow up to %{total_items} accounts from %{filename} and stop following anyone else. - lists_html: You are about to replace your lists with contents of %{filename}. Up to %{total_items} accounts will be added to new lists. - muting_html: You are about to replace your list of muted accounts with up to %{total_items} accounts from %{filename}. + blocking_html: + one: You are about to replace your block list with up to %{count} account from %{filename}. + other: You are about to replace your block list with up to %{count} accounts from %{filename}. + bookmarks_html: + one: You are about to replace your bookmarks with up to %{count} post from %{filename}. + other: You are about to replace your bookmarks with up to %{count} posts from %{filename}. + domain_blocking_html: + one: You are about to replace your domain block list with up to %{count} domain from %{filename}. + other: You are about to replace your domain block list with up to %{count} domains from %{filename}. + following_html: + one: You are about to follow up to %{count} account from %{filename} and stop following anyone else. + other: You are about to follow up to %{count} accounts from %{filename} and stop following anyone else. + lists_html: + one: You are about to replace your lists with contents of %{filename}. Up to %{count} account will be added to new lists. + other: You are about to replace your lists with contents of %{filename}. Up to %{count} accounts will be added to new lists. + muting_html: + one: You are about to replace your list of muted account with up to %{count} account from %{filename}. + other: You are about to replace your list of muted accounts with up to %{count} accounts from %{filename}. preambles: - blocking_html: You are about to block up to %{total_items} accounts from %{filename}. - bookmarks_html: You are about to add up to %{total_items} posts from %{filename} to your bookmarks. - domain_blocking_html: You are about to block up to %{total_items} domains from %{filename}. - following_html: You are about to follow up to %{total_items} accounts from %{filename}. - lists_html: You are about to add up to %{total_items} accounts from %{filename} to your lists. New lists will be created if there is no list to add to. - muting_html: You are about to mute up to %{total_items} accounts from %{filename}. + blocking_html: + one: You are about to block up to %{count} account from %{filename}. + other: You are about to block up to %{count} accounts from %{filename}. + bookmarks_html: + one: You are about to add up to %{count} post from %{filename} to your bookmarks. + other: You are about to add up to %{count} posts from %{filename} to your bookmarks. + domain_blocking_html: + one: You are about to block up to %{count} domain from %{filename}. + other: You are about to block up to %{count} domains from %{filename}. + following_html: + one: You are about to follow up to %{count} account from %{filename}. + other: You are about to follow up to %{count} accounts from %{filename}. + lists_html: + one: You are about to add up to %{count} account from %{filename} to your lists. New lists will be created if there is no list to add to. + other: You are about to add up to %{count} accounts from %{filename} to your lists. New lists will be created if there is no list to add to. + muting_html: + one: You are about to mute up to %{count} account from %{filename}. + other: You are about to mute up to %{count} accounts from %{filename}. preface: You can import data that you have exported from another server, such as a list of the people you are following or blocking. recent_imports: Recent imports states: @@ -1694,7 +1724,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..3d63ecd01d6604 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -19,17 +19,21 @@ eo: following: Vi devas sekvi la homon, kiun vi volas proponi posts: one: Afiŝo - other: Mesaĝoj + other: Afiŝoj posts_tab_heading: Afiŝoj + self_follow_error: Sekvi vian propran konton ne estas permesita 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 +48,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} @@ -56,6 +61,7 @@ eo: demote: Degradi destroyed_msg: Datumoj de %{username} nun enviciĝis por esti forigita baldaǔ disable: Frostigi + disable_sign_in_token_auth: Malebligu retpoŝtan ĵeton-aŭtentikigon disable_two_factor_authentication: Malŝalti 2FA-n disabled: Frostigita display_name: Montrata nomo @@ -64,6 +70,7 @@ eo: email: Retpoŝto email_status: Stato de retpoŝto enable: Malfrostigi + enable_sign_in_token_auth: Ebligu retpoŝtan ĵeton-aŭtentikigon enabled: Ebligita enabled_msg: Sukcese malfrostigis konton de %{username} followers: Sekvantoj @@ -76,8 +83,8 @@ eo: joined: Aliĝis location: all: Ĉiuj - local: Lokaj - remote: Foraj + local: Loka + remote: Fora title: Loko login_status: Ensaluta stato media_attachments: Plurmediaj aldonaĵoj @@ -128,6 +135,7 @@ eo: resubscribe: Reaboni role: Rolo search: Serĉi + search_same_email_domain: Aliaj uzantoj kun la sama retpoŝta domajno search_same_ip: Aliaj uzantoj kun la sama IP security: Sekureco security_measures: @@ -168,21 +176,26 @@ eo: approve_appeal: Aprobis Apelacion approve_user: Aprobi Uzanton assigned_to_self_report: Atribui Raporton + change_email_user: Ŝanĝu retpoŝton por uzanto change_role_user: Ŝanĝi Rolon de Uzanton confirm_user: Konfirmi uzanton create_account_warning: Krei averton create_announcement: Krei Anoncon + create_canonical_email_block: Krei retpoŝtan blokon create_custom_emoji: Krei Propran Emoĝion create_domain_allow: Krei Domajnan Permeson create_domain_block: Krei Blokadon De Domajno + create_email_domain_block: Krei retpoŝtan domajnan blokon create_ip_block: Krei IP-regulon create_unavailable_domain: Krei Nehaveblan Domajnon create_user_role: Krei Rolon demote_user: Malpromocii Uzanton destroy_announcement: Forigi Anoncon + destroy_canonical_email_block: Forigi retpoŝtan blokon destroy_custom_emoji: Forigi Propran Emoĝion destroy_domain_allow: Forigi Domajnan Permeson destroy_domain_block: Forigi blokadon de domajno + destroy_email_domain_block: Forigi retpoŝtan domajnan blokon destroy_instance: Forigi Domajnon destroy_ip_block: Forigi IP-regulon destroy_status: Forigi Afiŝon @@ -214,18 +227,22 @@ eo: update_custom_emoji: Ĝisdatigi proprajn emoĝiojn update_domain_block: Ĝigdatigi domajnan blokadon update_ip_block: Krei IP-regulon + update_report: Ĝisdatigo de Raporto update_status: Ĝisdatigi afiŝon update_user_role: Ĝisdatigi rolon actions: approve_appeal_html: "%{name} aprobis apelacion kontraŭ moderiga decido de %{target}" approve_user_html: "%{name} aprobis registriĝon de %{target}" assigned_to_self_report_html: "%{name} asignis signalon %{target} al si mem" + change_email_user_html: "%{name} ŝanĝis retadreson de uzanto %{target}" change_role_user_html: "%{name} ŝanĝis rolon de %{target}" + confirm_user_html: "%{name} konfirmis retadreson de uzanto %{target}" create_account_warning_html: "%{name} sendis averton al %{target}" create_announcement_html: "%{name} kreis novan anoncon %{target}" create_custom_emoji_html: "%{name} alŝutis novan emoĝion %{target}" create_domain_allow_html: "%{name} aldonis domajnon %{target} al la blanka listo" create_domain_block_html: "%{name} blokis domajnon %{target}" + create_email_domain_block_html: "%{name} blokis retpoŝtan domajnon %{target}" create_ip_block_html: "%{name} kreis regulon por IP %{target}" create_unavailable_domain_html: "%{name} ĉesis sendon al domajno %{target}" create_user_role_html: "%{name} kreis rolon de %{target}" @@ -234,6 +251,7 @@ eo: destroy_custom_emoji_html: "%{name} forigis emoĝion %{target}" destroy_domain_allow_html: "%{name} forigis domajnon %{target} el la blanka listo" destroy_domain_block_html: "%{name} malblokis domajnon %{target}" + destroy_email_domain_block_html: "%{name} malblokis retpoŝtan domajnon %{target}" destroy_instance_html: "%{name} forigis domajnon %{target}" destroy_ip_block_html: "%{name} forigis regulon por IP %{target}" destroy_status_html: "%{name} forigis mesaĝojn de %{target}" @@ -271,6 +289,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 +427,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,8 +436,10 @@ eo: new: create: Aldoni domajnon resolve: Solvi domajnon + title: Bloki novan retpoŝtan domajnon not_permitted: Ne permesita resolved_through_html: Solvis tra %{domain} + title: Blokis retpoŝtajn domajnojn export_domain_allows: new: title: Importi domajnpermesojn @@ -568,7 +590,11 @@ 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 + already_suspended_badges: + local: Jam malakceptita sur ĉi tiu servilo + remote: Jam malakceptita sur ilia servilo are_you_sure: Ĉu vi certas? assign_to_self: Asigni al mi assigned: Asignita kontrolanto @@ -604,6 +630,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 @@ -716,6 +743,7 @@ eo: desc_html: Ĉi tio dependas de eksteraj hCaptcha-skriptoj, kiuj povas esti problemo pri sekureco kaj privateco. Ankaŭ, ĝi povas igi la registran procezon multe malpli alirebla por iuj homoj (precipe homoj kun handikapoj). Pro ĉi tiuj kialoj, bonvolu konsideri alternativajn rimedojn kiel registradon per aprobo aŭ per invito. title: Postuli novajn uzantojn solvi CAPTCHA por konfirmi sian konton content_retention: + danger_zone: Danĝera zono preamble: Regi kiel uzantogenerita enhavo konservitis en Mastodon. title: Enhavkonservo default_noindex: @@ -800,6 +828,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 +840,14 @@ eo: message_html: Vi ne difinis iujn servilajn regulojn. sidekiq_process_check: message_html: Neniu Sidekiq-procezo por la %{value} vico + software_version_check: + action: Vidi disponeblajn ĝisdatigojn + message_html: Mastodon-ĝisdatigo disponeblas. + software_version_critical_check: + action: Vidi disponeblajn ĝisdatigojn + message_html: Grava ĝisdatigo de Mastodon disponeblas, bonvolu ĝisdatigi kiel eble plej rapide. + 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 +855,31 @@ 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 + open: Vidu publike + reset: Restartigi 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_allow_provider: Ĉu vi certas, ke vi volas permesi elektitajn provizantojn? + confirm_disallow: Ĉu vi certas, ke vi volas malpermesi elektitajn ligilojn? + confirm_disallow_provider: Ĉu vi certas, ke vi volas malpermesi elektitajn provizantojn? 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 +903,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 @@ -882,6 +937,7 @@ eo: used_by_over_week: one: Uzita de 1 persono ekde lasta semajno other: Uzita de %{count} personoj ekde lasta semajno + title: Rekomendoj kaj Tendencoj trending: Popularaĵoj warning_presets: add_new: Aldoni novan @@ -921,6 +977,8 @@ eo: body: "%{target} apelacias kontroldecido de %{action_taken_by} de %{date}, kiu estas %{type}. Ĝi skribis:" next_steps: Vi povas aprobi apelacion por malfari kontroldecidon au ignori. subject: "%{username} apelacias kontroldecidon ĉe %{instance}" + new_critical_software_updates: + body: Novaj gravaj versioj de Mastodon estis publikigitaj, vi eble volas ĝisdatigi kiel eble plej baldaŭ! new_pending_account: body: La detaloj de la nova konto estas ĉi-sube. Vi povas akcepti aŭ malakcepti tiun aliĝilon. subject: Nova konto atendas por recenzo en %{instance} (%{username}) @@ -928,6 +986,9 @@ 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! + subject: Novaj versioj de Mastodon disponeblas por %{instance}! new_trends: body: 'La eroj bezonas kontrolon antau ol ili povas montritas publike:' new_trending_links: @@ -956,7 +1017,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 @@ -973,10 +1036,14 @@ eo: apply_for_account: Peti konton captcha_confirmation: help_html: Se vi havas problemojn solvi la CAPTCHA, vi povas kontakti nin per %{email} kaj ni povas helpi vin. + hint_html: Nur unu plia afero! Ni devas konfirmi, ke vi estas homo (tio estas por ke ni povu konservi la spamon ekstere!). Solvu la CAPTCHA sube kaj alklaku "Daŭrigu". 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 +1064,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 @@ -1019,6 +1087,7 @@ eo: set_new_password: Elekti novan pasvorton setup: link_not_received: Ĉu vi ne ricevis ligilon? + new_confirmation_instructions_sent: Vi ricevos novan retpoŝton kun la konfirma ligilo post kelkaj minutoj! title: Kontrolu vian retpoŝta enirkesto sign_in: preamble_html: Ensalutu per via detaloj de %{domain}. Se via konto gastigantigas sur malsama servilo, vi ne povas ensaluti ĉi tie. @@ -1033,6 +1102,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 +1302,13 @@ 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 + scheduled: Planitaj unconfirmed: Nekonfirmita + status: Stato success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite titles: following: Importado de sekvaj kontoj @@ -1424,6 +1502,8 @@ eo: errors: limit_reached: Limito de malsamaj reagoj atinginta unrecognized_emoji: ne estas rekonita emoĝio + redirects: + prompt: Se vi fidas ĉi tiun ligon, alklaku ĝin por daŭrigi. relationships: activity: Konta aktiveco confirm_follow_selected_followers: Ĉu vi certas ke vi volas sekvi la elektitajn sekvantojn? @@ -1518,11 +1598,12 @@ eo: delete: Konta forigo development: Evoluigado edit_profile: Redakti profilon - export: Eksporti datumojn + export: Eksporti featured_tags: Elstarigitaj kradvortoj import: Enporti import_and_export: Importi kaj eksporti migrate: Konta migrado + notifications: Retpoŝtaj sciigoj preferences: Preferoj profile: Profilo relationships: Sekvatoj kaj sekvantoj @@ -1530,6 +1611,12 @@ eo: strikes: Kontroladmonoj two_factor_authentication: Dufaktora aŭtentigo webauthn_authentication: Sekurecaj ŝlosiloj + severed_relationships: + download: Elŝuti (%{count}) + event_type: + user_domain_block: Vi blokis %{target_name} + lost_followers: Perditaj sekvantoj + type: Evento statuses: attached: audio: @@ -1689,7 +1776,25 @@ 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_recent_count: + one: "%{people} homo en la pasintaj 2 tagoj" + other: "%{people} homoj en la pasintaj 2 tagoj" + hashtags_title: Popularaj kradvortoj + hashtags_view_more: Vidi pli da popularaj kradvortoj + post_action: Redakti + post_step: Salutu la mondon per teksto, fotoj, filmetoj aŭ balotenketoj. + post_title: Faru vian unuan afiŝon + share_action: Kundividi + share_step: Sciigu viajn amikojn kiel trovi vin sur Mastodon. + share_title: Kunhavigu vian Mastodon-profilon + 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..a27ba1a5484448 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -21,6 +21,7 @@ es-AR: one: Mensaje other: Mensajes posts_tab_heading: Mensajes + self_follow_error: No está permitido seguir tu propia cuenta admin: account_actions: action: Ejecutar acción @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ es-AR: use_security_key: Usar la llave de seguridad author_attribution: example_title: Texto de ejemplo - hint_html: Controlá cómo se te da crédito cuando los enlaces son compartidos en Mastodon. + hint_html: "¿Escribes noticias o artículos de blog fuera de Mastodon? Controla cómo se te acredita cuando se comparten en Mastodon." + instructions: 'Asegúrate de que este código está en el HTML de tu artículo:' more_from_html: Más de %{name} s_blog: Blog de %{name} + then_instructions: A continuación, añade el nombre de dominio de la publicación en el campo inferior. title: Atribución del autor challenge: confirm: Continuar @@ -1363,19 +1369,43 @@ es-AR: overwrite: Sobrescribir overwrite_long: Reemplazar registros actuales con los nuevos overwrite_preambles: - blocking_html: Estás a punto de reemplazar tu lista de bloqueos por hasta %{total_items} cuentas provenientes de %{filename}. - bookmarks_html: Estás a punto de reemplazar tus marcadores por hasta %{total_items} mensajes provenientes de %{filename}. - domain_blocking_html: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta %{total_items} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. - lists_html: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se agregarán hasta %{total_items} cuentas a listas nuevas. - muting_html: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{total_items} cuentas provenientes de %{filename}. + blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos por hasta %{count} cuenta provenientes de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos por hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Estás a punto de reemplazar tus marcadores por hasta %{count} mensaje provenientes de %{filename}. + other: Estás a punto de reemplazar tus marcadores por hasta %{count} mensajes provenientes de %{filename}. + domain_blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{count} dominio provenientes de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir hasta %{count} cuenta provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. + lists_html: + one: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se agregarán hasta %{count} cuenta a listas nuevas. + other: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se agregarán hasta %{count} cuentas a listas nuevas. + muting_html: + one: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{count} cuenta provenientes de %{filename}. + other: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{count} cuentas provenientes de %{filename}. preambles: - blocking_html: Estás a punto de bloquear hasta %{total_items} cuentas provenientes de %{filename}. - bookmarks_html: Está a punto de agregar hasta %{total_items} mensajes provenientes de %{filename} a tus marcadores. - domain_blocking_html: Estás a punto de bloquear hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta cuentas%{total_items} provenientes de %{filename}. - lists_html: Estás a punto de agregar hasta %{total_items} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay lista a cual agregar. - muting_html: Estás a punto de silenciar hasta %{total_items} cuentas provenientes de %{filename}. + blocking_html: + one: Estás a punto de bloquear hasta %{count} cuenta provenientes de %{filename}. + other: Estás a punto de bloquear hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Está a punto de agregar hasta %{count} mensaje provenientes de %{filename} a tus marcadores. + other: Está a punto de agregar hasta %{count} mensajes provenientes de %{filename} a tus marcadores. + domain_blocking_html: + one: Estás a punto de bloquear hasta %{count} dominio provenientes de %{filename}. + other: Estás a punto de bloquear hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir hasta %{count} cuenta provenientes de %{filename}. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename}. + lists_html: + one: Estás a punto de agregar hasta %{count} cuenta desde %{filename} a tus listas. Se crearán nuevas listas si no hay lista a cuál agregar. + other: Estás a punto de agregar hasta %{count} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay lista a cuál agregar. + muting_html: + one: Estás a punto de silenciar hasta %{count} cuenta provenientes de %{filename}. + other: Estás a punto de silenciar hasta %{count} cuentas provenientes de %{filename}. preface: Podés importar ciertos datos que exportaste desde otro servidor, como una lista de las cuentas que estás siguiendo o bloqueando. recent_imports: Importaciones recientes states: @@ -1692,7 +1722,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..fef805680a3227 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -21,6 +21,7 @@ es-MX: one: Toot other: Toots posts_tab_heading: Toots + self_follow_error: No se permite seguir tu propia cuenta admin: account_actions: action: Realizar acción @@ -180,21 +181,21 @@ es-MX: confirm_user: Confirmar Usuario create_account_warning: Crear Advertencia create_announcement: Crear Anuncio - create_canonical_email_block: Crear Bloqueo de Correo Electrónico + create_canonical_email_block: Crear bloqueo de correo electrónico create_custom_emoji: Crear Emoji Personalizado create_domain_allow: Crear Permiso de Dominio create_domain_block: Crear Bloqueo de Dominio - create_email_domain_block: Crear Bloqueo de Dominio de Correo Electrónico + create_email_domain_block: Crear bloqueo de dominio de correo electrónico create_ip_block: Crear regla IP create_unavailable_domain: Crear Dominio No Disponible create_user_role: Crear rol demote_user: Degradar Usuario destroy_announcement: Eliminar Anuncio - destroy_canonical_email_block: Eliminar Bloqueo de Correo Electrónico + destroy_canonical_email_block: Eliminar bloqueo de correo electrónico destroy_custom_emoji: Eliminar Emoji Personalizado destroy_domain_allow: Eliminar Permiso de Dominio destroy_domain_block: Eliminar Bloqueo de Dominio - destroy_email_domain_block: Eliminar Bloqueo de Dominio de Correo Electrónico + destroy_email_domain_block: Eliminar bloqueo de dominio de correo electrónico destroy_instance: Purgar dominio destroy_ip_block: Eliminar regla IP destroy_status: Eliminar Estado @@ -240,7 +241,7 @@ es-MX: confirm_user_html: "%{name} confirmó la dirección de correo electrónico del usuario %{target}" create_account_warning_html: "%{name} envió una advertencia a %{target}" create_announcement_html: "%{name} ha creado un nuevo anuncio %{target}" - create_canonical_email_block_html: "%{name} bloqueó el correo electrónico con el hash %{target}" + create_canonical_email_block_html: "%{name} ha bloqueado el correo electrónico con el hash %{target}" create_custom_emoji_html: "%{name} subió un nuevo emoji %{target}" create_domain_allow_html: "%{name} permitió la federación con el dominio %{target}" create_domain_block_html: "%{name} bloqueó el dominio %{target}" @@ -250,7 +251,7 @@ es-MX: create_user_role_html: "%{name} creó el rol %{target}" demote_user_html: "%{name} degradó al usuario %{target}" destroy_announcement_html: "%{name} eliminó el anuncio %{target}" - destroy_canonical_email_block_html: "%{name} desbloqueó el correo electrónico con el hash %{target}" + destroy_canonical_email_block_html: "%{name} ha desbloqueado el correo electrónico con el hash %{target}" destroy_custom_emoji_html: "%{name} eliminó el emoji %{target}" destroy_domain_allow_html: "%{name} bloqueó la federación con el dominio %{target}" destroy_domain_block_html: "%{name} desbloqueó el dominio %{target}" @@ -262,10 +263,10 @@ es-MX: destroy_user_role_html: "%{name} eliminó el rol %{target}" disable_2fa_user_html: "%{name} desactivó el requisito de dos factores para el usuario %{target}" disable_custom_emoji_html: "%{name} desactivó el emoji %{target}" - disable_sign_in_token_auth_user_html: "%{name} ha deshabilitado la autenticación por token de correo electrónico para %{target}" + disable_sign_in_token_auth_user_html: "%{name} desactivó la autenticación por token de correo electrónico para %{target}" disable_user_html: "%{name} deshabilitó el inicio de sesión para el usuario %{target}" enable_custom_emoji_html: "%{name} activó el emoji %{target}" - enable_sign_in_token_auth_user_html: "%{name} ha habilitado la autenticación por token de correo electrónico para %{target}" + enable_sign_in_token_auth_user_html: "%{name} activó autenticación por token de correo electrónico para %{target}" enable_user_html: "%{name} habilitó el inicio de sesión para el usuario %{target}" memorialize_account_html: "%{name} convirtió la cuenta de %{target} en una página in memoriam" promote_user_html: "%{name} promoción al usuario %{target}" @@ -273,7 +274,7 @@ es-MX: reject_user_html: "%{name} rechazó el registro de %{target}" remove_avatar_user_html: "%{name} eliminó el avatar de %{target}" reopen_report_html: "%{name} reabrió el informe %{target}" - resend_user_html: "%{name} ha reenviado el correo de confirmación para %{target}" + resend_user_html: "%{name} reenvió correo electrónico de confirmación para %{target}" reset_password_user_html: "%{name} reinició la contraseña del usuario %{target}" resolve_report_html: "%{name} resolvió el informe %{target}" sensitive_account_html: "%{name} marcó la multimedia de %{target} como sensible" @@ -604,7 +605,7 @@ es-MX: suspend_description_html: La cuenta y todos sus contenidos serán inaccesibles y eventualmente eliminados, e interactuar con ella será imposible. Reversible durante 30 días. Cierra todos los reportes contra esta cuenta. actions_description_html: Decide qué medidas tomar para resolver esta denuncia. Si tomas una acción punitiva contra la cuenta denunciada, se le enviará a dicha cuenta una notificación por correo electrónico, excepto cuando se seleccione la categoría Spam. actions_description_remote_html: Decide qué medidas tomar para resolver este reporte. Esto solo afectará a la forma en que tu servidor se comunica con esta cuenta remota y gestiona su contenido. - actions_no_posts: Este informe no tiene ningún mensaje asociado para eliminar + actions_no_posts: Este informe no tiene ninguna publicación asociada para eliminar add_to_report: Añadir más al reporte already_suspended_badges: local: Ya suspendido en este servidor @@ -801,7 +802,7 @@ es-MX: destroyed_msg: "¡Carga del sitio eliminada con éxito!" software_updates: critical_update: Crítico — por favor actualiza rápidamente - description: Se recomienda mantener actualizada tu instalación de Mastodon para beneficiarte de las últimas correcciones y características. Además, a veces es crítico actualizar Mastodon de manera oportuna para evitar problemas de seguridad. Por estas razones, Mastodon comprueba si hay actualizaciones cada 30 minutos, y te notificará de acuerdo a tus preferencias de notificación por correo electrónico. + description: Se recomienda mantener tu instalación de Mastodon actualizada para beneficiarte de las últimas correcciones y características. Además, a veces es crítico actualizar Mastodon a tiempo para evitar problemas de seguridad. Por estas razones, Mastodon busca actualizaciones cada 30 minutos, y le notificará de acuerdo a sus preferencias de notificación por correo electrónico. documentation_link: Saber más release_notes: Notas de la versión title: Actualizaciones disponibles @@ -875,6 +876,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 las actualizaciones disponibles + message_html: Ya está 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. @@ -1162,9 +1166,11 @@ es-MX: use_security_key: Usar la clave de seguridad author_attribution: example_title: Texto de ejemplo - hint_html: Controla cómo se te dará atribución cuando se compartan enlaces en Mastodon. + hint_html: "¿Estás escribiendo artículos de noticias o blogs fuera de Mastodon? Controla cómo te acreditan cuando se comparten en Mastodon." + instructions: 'Asegúrate de que este código esté en el HTML de tu artículo:' more_from_html: Más de %{name} s_blog: Blog de %{name} + then_instructions: A continuación, añade el nombre de dominio de la publicación en el campo inferior. title: Atribución del autor challenge: confirm: Continuar @@ -1203,7 +1209,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. @@ -1363,19 +1369,43 @@ es-MX: overwrite: Sobrescribir overwrite_long: Reemplazar registros actuales con los nuevos overwrite_preambles: - blocking_html: Estás a punto de reemplazar tu lista de bloqueos por hasta %{total_items} cuentas provenientes de %{filename}. - bookmarks_html: Estás a punto de reemplazar tus marcadores por hasta %{total_items} publicaciones provenientes de %{filename}. - domain_blocking_html: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta %{total_items} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. - lists_html: Estás a punto de reemplazar tus listas con contenidos de %{filename}. %{total_items} cuentas se añadirán a listas nuevas. - muting_html: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{total_items} cuentas proveninetes de %{filename}. + blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos por %{count} cuenta proveniente de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos por hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Estás a punto de reemplazar tus marcadores por %{count} publicación proveniente de %{filename}. + other: Estás a punto de reemplazar tus marcadores por hasta %{count} publicaciones provenientes de %{filename}. + domain_blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos de dominio por %{count} dominio proveniente de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir a %{count} cuenta proveniente de %{filename} y dejar de seguir a cualquier otra cuenta. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. + lists_html: + one: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se añadirá %{count} cuenta a una nueva lista. + other: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se añadirán %{count} cuentas a nuevas listas. + muting_html: + one: Estás a punto de reemplazar tu lista de cuentas silenciadas con %{count} cuenta proveninete de %{filename}. + other: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{count} cuentas provenientes de %{filename}. preambles: - blocking_html: Estás a punto de bloquear hasta %{total_items} cuentas proveninetes de %{filename}. - bookmarks_html: Estás a punto de añadir hasta %{total_items} publicaciones proveninetes de %{filename} a tus marcadores. - domain_blocking_html: Estás a punto de bloquear hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta cuentas%{total_items} provenientes de %{filename}. - lists_html: Estás a punto de añadir %{total_items} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay listas para añadirlas. - muting_html: Estás a punto de silenciar hasta %{total_items} cuentas provenientes de %{filename}. + blocking_html: + one: Estás a punto de bloquear a %{count} cuenta proveninete de %{filename}. + other: Estás a punto de bloquear hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Está a punto de añadir %{count} publicación proveniente de %{filename} a tus marcadores. + other: Está a punto de añadir hasta %{count} publicaciones provenientes de %{filename} a tus marcadores. + domain_blocking_html: + one: Estás a punto de bloquear %{count} dominio proveniente de %{filename}. + other: Estás a punto de bloquear hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir a %{count} cuenta proveniente de %{filename}. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename}. + lists_html: + one: Estás a punto de añadir %{count} cuenta desde %{filename} a tus listas. Se creará una nueva listas si no hay listas donde añadirla. + other: Estás a punto de añadir %{count} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay listas donde añadirlas. + muting_html: + one: Estás a punto de silenciar a %{count} cuenta proveniente de %{filename}. + other: Estás a punto de silenciar hasta %{count} cuentas provenientes de %{filename}. preface: Puedes importar ciertos datos, como todas las personas que estás siguiendo o bloqueando en tu cuenta en esta instancia, desde archivos exportados de otra instancia. recent_imports: Importaciones recientes states: @@ -1450,8 +1480,8 @@ es-MX: emails: notification_emails: favourite: correos de notificación de favoritos - follow: correos de notificación de nuevos seguidores - follow_request: correos de notificación de solicitud de seguidor + follow: correos electrónicos de notificación de seguimiento + follow_request: correos electrónicos de solicitud de seguimiento mention: correos de notificación de menciones reblog: correos de notificación de impulsos resubscribe_html: Si te has dado de baja por error, puedes volver a darte de alta desde tus ajustes de notificaciones por correo. @@ -1529,9 +1559,9 @@ es-MX: poll: subject: Una encuesta de %{name} ha terminado reblog: - body: "%{name} ha retooteado tu estado:" - subject: "%{name} ha retooteado tu estado" - title: Nueva difusión + body: 'Tu publicación fue impulsada por %{name}:' + subject: "%{name} ha impulsado tu publicación" + title: Nuevo impulso status: subject: "%{name} acaba de publicar" update: @@ -1692,7 +1722,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 @@ -1743,7 +1773,7 @@ es-MX: direct: Las publicaciones que son visibles solo para los usuarios mencionados no pueden fijarse limit: Ya has fijado el número máximo de publicaciones ownership: El toot de alguien más no puede fijarse - reblog: Un boost no puede fijarse + reblog: No se puede fijar una publicación impulsada title: "%{name}: «%{quote}»" visibilities: direct: Directa @@ -1759,9 +1789,9 @@ es-MX: exceptions: Excepciones explanation: Debido a que la eliminación de mensajes es una operación costosa, esto se hace lentamente, a lo largo de un tiempo, cuando el servidor no está ocupado. Por este motivo, puede que tus publicaciones sean borradas algo después de que alcancen el umbral de tiempo especificado. ignore_favs: Ignorar favoritos - ignore_reblogs: Ignorar reblogueos + ignore_reblogs: Ignorar impulsos interaction_exceptions: Excepciones basadas en interacciones - interaction_exceptions_explanation: Ten en cuenta que no hay garantía de que se eliminen las publicaciones que están por debajo de los umbrales de favoritos o de reblogueos si los han superado en algún momento. + interaction_exceptions_explanation: Ten en cuenta que no se garantiza la eliminación de las publicaciones si bajan del umbral de favoritos o de impulso después de haberlos superado una vez. keep_direct: Mantener mensajes directos keep_direct_hint: No elimina ninguno de tus mensajes directos keep_media: Mantener publicaciones con multimedia adjunto @@ -1786,7 +1816,7 @@ es-MX: min_age_label: Umbral de tiempo min_favs: Mantener mensajes con un número de favoritos mayor que min_favs_hint: No borra ninguna de las publicaciones que hayan recibido al menos esta cantidad de favoritos. Deja en blanco para eliminar publicaciones sin importar el número de favoritos - min_reblogs: Mantener publicaciones reblogueadas más de + min_reblogs: Mantener publicaciones impulsadas más de min_reblogs_hint: No borra ninguna de las publicaciones que hayan sido reblogueadas más de este número de veces. Deja en blanco para eliminar publicaciones sin importar el número de reblogueos stream_entries: sensitive_content: Contenido sensible @@ -1894,7 +1924,7 @@ es-MX: checklist_subtitle: 'Comencemos en esta nueva frontera social:' checklist_title: Lista de bienvenida edit_profile_action: Personalizar - edit_profile_step: Aumenta tus interacciones con un perfil completo. + edit_profile_step: Aumenta tus interacciones completando tu perfil. edit_profile_title: Personaliza tu perfil explanation: Aquí hay algunos consejos para empezar feature_action: Leer más diff --git a/config/locales/es.yml b/config/locales/es.yml index 2815ada77957ce..8690c1cdfb57c4 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -21,6 +21,7 @@ es: one: Publicación other: Publicaciones posts_tab_heading: Publicaciones + self_follow_error: No está permitido seguir tu propia cuenta admin: account_actions: action: Realizar acción @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ es: use_security_key: Usar la clave de seguridad author_attribution: example_title: Texto de ejemplo - hint_html: Controla cómo se te dará atribución cuando se compartan enlaces en Mastodon. + hint_html: "¿Escribes noticias o artículos de blog fuera de Mastodon? Controla cómo se te acredita cuando se comparten en Mastodon." + instructions: 'Asegúrate de que este código está en el HTML de tu artículo:' more_from_html: Más de %{name} s_blog: Blog de %{name} + then_instructions: A continuación, añade el nombre de dominio de la publicación en el campo inferior. title: Atribución del autor challenge: confirm: Continuar @@ -1363,19 +1369,43 @@ es: overwrite: Sobrescribir overwrite_long: Reemplazar registros actuales con los nuevos overwrite_preambles: - blocking_html: Estás a punto de reemplazar tu lista de bloqueos por hasta %{total_items} cuentas provenientes de %{filename}. - bookmarks_html: Estás a punto de reemplazar tus marcadores por hasta %{total_items} publicaciones provenientes de %{filename}. - domain_blocking_html: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta %{total_items} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. - lists_html: Estás a punto de reemplazar tus listas con contenidos de %{filename}. Se añadirán %{total_items} cuentas a nuevas listas. - muting_html: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{total_items} cuentas proveninetes de %{filename}. + blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos por %{count} cuenta proveniente de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos por hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Estás a punto de reemplazar tus marcadores por %{count} publicación proveniente de %{filename}. + other: Estás a punto de reemplazar tus marcadores por hasta %{count} publicaciones provenientes de %{filename}. + domain_blocking_html: + one: Estás a punto de reemplazar tu lista de bloqueos de dominio por %{count} dominio proveniente de %{filename}. + other: Estás a punto de reemplazar tu lista de bloqueos de dominio por hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir a %{count} cuenta proveniente de %{filename} y dejar de seguir a cualquier otra cuenta. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename} y dejar de seguir a cualquier otra cuenta. + lists_html: + one: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se añadirá %{count} cuenta a una nueva lista. + other: Estás a punto de reemplazar tus listas con el contenido de %{filename}. Se añadirán %{count} cuentas a nuevas listas. + muting_html: + one: Estás a punto de reemplazar tu lista de cuentas silenciadas con %{count} cuenta proveninete de %{filename}. + other: Estás a punto de reemplazar tu lista de cuentas silenciadas con hasta %{count} cuentas provenientes de %{filename}. preambles: - blocking_html: Estás a punto de bloquear hasta %{total_items} cuentas proveninetes de %{filename}. - bookmarks_html: Está a punto de añadir hasta %{total_items} publicaciones proveninetes de %{filename} a tus marcadores. - domain_blocking_html: Estás a punto de bloquear hasta %{total_items} dominios provenientes de %{filename}. - following_html: Estás a punto de seguir hasta cuentas%{total_items} provenientes de %{filename}. - lists_html: Estás a punto de añadir %{total_items} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay listas para añadirlas. - muting_html: Estás a punto de silenciar hasta %{total_items} cuentas provenientes de %{filename}. + blocking_html: + one: Estás a punto de bloquear a %{count} cuenta proveninete de %{filename}. + other: Estás a punto de bloquear hasta %{count} cuentas provenientes de %{filename}. + bookmarks_html: + one: Está a punto de añadir %{count} publicación proveniente de %{filename} a tus marcadores. + other: Está a punto de añadir hasta %{count} publicaciones provenientes de %{filename} a tus marcadores. + domain_blocking_html: + one: Estás a punto de bloquear %{count} dominio proveniente de %{filename}. + other: Estás a punto de bloquear hasta %{count} dominios provenientes de %{filename}. + following_html: + one: Estás a punto de seguir a %{count} cuenta proveniente de %{filename}. + other: Estás a punto de seguir hasta %{count} cuentas provenientes de %{filename}. + lists_html: + one: Estás a punto de añadir %{count} cuenta desde %{filename} a tus listas. Se creará una nueva listas si no hay listas donde añadirla. + other: Estás a punto de añadir %{count} cuentas desde %{filename} a tus listas. Se crearán nuevas listas si no hay listas donde añadirlas. + muting_html: + one: Estás a punto de silenciar a %{count} cuenta proveniente de %{filename}. + other: Estás a punto de silenciar hasta %{count} cuentas provenientes de %{filename}. preface: Puedes importar ciertos datos, como todas las personas que estás siguiendo o bloqueando en tu cuenta en esta instancia, desde archivos exportados de otra instancia. recent_imports: Importaciones recientes states: @@ -1692,7 +1722,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..1a679af87f1f87 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -21,6 +21,7 @@ et: one: Postitus other: Postitused posts_tab_heading: Postitused + self_follow_error: Omaenda konto jälgimine ei ole lubatud admin: account_actions: action: Täida tegevus @@ -875,6 +876,9 @@ et: message_html: Serverireegleid pole defineeritud. sidekiq_process_check: message_html: Ühtegi Sidekiq protsessi pole %{value} järjekorra jaoks. Sidekiq seadistus vajab üle vaatamist + software_version_check: + action: Vaata saadaval uuendusi + message_html: Mastodoni uuendus on saadaval. software_version_critical_check: action: Vaata saadaolevaid uuendusi message_html: Saadaval on Mastodoni kriitiline uuendus, uuenda nii kiiresti kui võimalik. @@ -1162,7 +1166,6 @@ et: use_security_key: Kasuta turvavõtit author_attribution: example_title: Näidistekst - hint_html: Määra, kuidas sind krediteeritakse, kui linke Mastodonis jagatakse. more_from_html: Rohkem kasutajalt %{name} s_blog: Kasutaja %{name} blogi title: Autori tunnustamine @@ -1363,19 +1366,43 @@ et: overwrite: Kirjuta üle overwrite_long: Vaheta praegused andmed uute vastu overwrite_preambles: - blocking_html: Oled asendamas oma blokeeringute loetelu kuni %{total_items} kontoga kohast %{filename}. - bookmarks_html: Oled asendamas oma järjehoidjaid kuni %{total_items} postitusega kohast %{filename}. - domain_blocking_html: Oled asendamas oma domeenide blokeeringute loetelu kuni %{total_items} domeeniga kohast %{filename}. - following_html: Oled jälgima hakkamas kuni %{total_items} kontot kohast %{filename} ja lõpetad kõigi teiste jälgimise. - lists_html: Oled asendamas oma loetelusid faili %{filename} sisuga. Uutesse loeteludesse lisatakse kuni %{total_items} kontot. - muting_html: Oled asendamas oma vaigistatud kontode loetelu kuni %{total_items} kontoga kohast %{filename}. + blocking_html: + one: Oled asendamas oma blokeeringute loetelu faili %{filename} sisuga, milles on kuni %{count} konto. + other: Oled asendamas oma blokeeringute loetelu faili %{filename} sisuga, milles on kuni %{count} kontot. + bookmarks_html: + one: Oled asendamas oma järjehoidjad faili %{filename} sisuga, milles on kuni %{count} postitus. + other: Oled asendamas oma järjehoidjad faili %{filename} sisuga, milles on kuni %{count} postitust. + domain_blocking_html: + one: Oled asendamas oma domeenide blokeeringu loetelu faili %{filename} sisuga, milles on kuni %{count} domeen. + other: Oled asendamas oma domeenide blokeeringu loetelu faili %{filename} sisuga, milles on kuni %{count} domeen. + following_html: + one: Oled jälgima hakkamas kuni %{count} kontot failist %{filename} ja lõpetad kõigi teiste jälgimise. + other: Oled jälgima hakkamas kuni %{count} kontot failist %{filename} ja lõpetad kõigi teiste jälgimise. + lists_html: + one: Oled asendamas oma loetelusid faili %{filename} sisuga. Uutesse loeteludesse lisatakse kuni %{count} konto. + other: Oled asendamas oma loetelusid faili %{filename} sisuga. Uutesse loeteludesse lisatakse kuni %{count} kontot. + muting_html: + one: Oled asendamas oma vaigistatud kontode loetelu faili %{filename} sisuga, milles on kuni %{count} konto. + other: Oled asendamas oma vaigistatud kontode loetelu faili %{filename} sisuga, milles on kuni %{count} kontot. preambles: - blocking_html: Oled blokeerimas kuni %{total_items} kontoga kohast %{filename}. - bookmarks_html: Oled lisamas kuni %{total_items} postitust kohast %{filename} to your bookmarks. - domain_blocking_html: Oled blokeerimas kuni %{total_items} domeeni kohast %{filename}. - following_html: Oled jälgima hakkamas kuni %{total_items} kontot kohast %{filename}. - lists_html: Oled lisamas oma loeteludesse failist %{filename} kuni %{total_items} kontot. Kui pole loetelusi, kuhu lisada, luuakse uued loetelud. - muting_html: Oled vaigistamas kuni %{total_items} kontot kohast %{filename}. + blocking_html: + one: Oled blokeerimas kuni %{count} konto failist %{filename}. + other: Oled blokeerimas kuni %{count} kontot failist %{filename}. + bookmarks_html: + one: Oled lisamas kuni %{count} postituse failist %{filename} oma järjehoidjatesse. + other: Oled lisamas kuni %{count} postitust failist %{filename} oma järjehoidjatesse. + domain_blocking_html: + one: Oled blokeerimas kuni %{count} domeeni failist %{filename}. + other: Oled blokeerimas kuni %{count} domeeni failist %{filename}. + following_html: + one: Oled jälgima hakkamas kuni %{count} konto failist %{filename}. + other: Oled jälgima hakkamas kuni %{count} kontot failist %{filename}. + lists_html: + one: Oled lisamas oma loeteludesse failist %{filename} kuni %{count} konto. Kui pole loetelusi, kuhu lisada, luuakse uued loetelud. + other: Oled lisamas oma loeteludesse failist %{filename} kuni %{count} kontot. Kui pole loetelusi, kuhu lisada, luuakse uued loetelud. + muting_html: + one: Oled vaigistamas kuni %{count} konto failist %{filename}. + other: Oled vaigistamas kuni %{count} kontot failist %{filename}. preface: Saad importida mistahes andmeid, mis on eksporditud teisest serverist. Näiteks nimekirja inimestest, keda jälgid ja keda blokeerid. recent_imports: Viimati imporditud states: @@ -1692,7 +1719,7 @@ et: delete: Konto kustutamine development: Arendus edit_profile: Muuda profiili - export: Andmete eksportimine + export: Eksport 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..e9c3be2d24a492 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -1276,20 +1276,6 @@ eu: merge_long: Mantendu dauden erregistroak eta gehitu berriak overwrite: Gainidatzi overwrite_long: Ordeztu oraingo erregistroak berriekin - overwrite_preambles: - blocking_html: "Blokeatutakoen zerrenda %{filename} fitxategiak dituen %{total_items} kontuekin ordeztear zaude." - bookmarks_html: "Laster-markak %{filename} fitxategiak dituen %{total_items} argitalpenekin ordeztear zaude." - domain_blocking_html: "Blokeatutako domeinuen zerrenda %{filename} fitxategiak dituen %{total_items} domeinuekin ordeztear zaude." - following_html: "%{filename} fitxategiak dituen %{total_items} kontuei jarraitzear zaude; gainontzekoak jarraitzeari utziko diozu." - lists_html: "Zerrendak %{filename} fitxategiak duen edukiarekin ordeztear zaude. %{total_items} kontu gehituko dira zerrenda berrietara." - muting_html: "Mutututako kontuen zerrenda %{filename} fitxategiak dituen %{total_items} kontuekin ordeztear zaude." - preambles: - blocking_html: "%{filename} fitxategiak dituen %{total_items} kontuak blokeatzear zaude." - bookmarks_html: "%{filename} fitxategiak dituen %{total_items} argitalpenei laster-marka jartzear zaude." - domain_blocking_html: "%{filename} fitxategiak dituen %{total_items} domeinuak blokeatzear zaude." - following_html: "%{filename} fitxategiak dituen %{total_items} konturi jarraitzear zaude." - lists_html: "%{filename} fitxategiak dituen %{total_items} kontu zerrendetan gehitzear zaude. Zerrenda berriak sortuko dira zerrendarik ez badago." - muting_html: "%{filename} fitxategiak dituen %{total_items} kontuak mututzear zaude." preface: Beste zerbitzari bateko datuak inportatu ditzakezu, esaterako jarraitzen duzun edo blokeatu duzun jendearen zerrenda. recent_imports: Azken inportazioak states: @@ -1592,7 +1578,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..3083bc13cbcdd9 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -963,6 +963,7 @@ fa: example_title: متن نمونه more_from_html: بیش‌تر از %{name} s_blog: بلاگ %{name} + title: اعتباردهی به نگارنده challenge: confirm: ادامه hint_html: "نکته: ما در یک ساعت آینده گذرواژه‌تان را از شما نخواهیم پرسید." @@ -1294,6 +1295,7 @@ fa: update: subject: "%{name} فرسته‌ای را ویرایست" notifications: + email_events: رویدادها برای آگاهی‌های رایانامه‌ای email_events_hint: 'گزینش رویدادهایی که می‌خواهید برایشان آگاهی دریافت کنید:' number: human: @@ -1338,6 +1340,7 @@ fa: privacy: hint_html: "شخصی‌سازی چگونگی پیدا شدن فرسته‌ها و نمایه‌تان. ویژگی‌های متعدّدی در ماستودون می‌توانند هنگام به کار افتادن در رسیدن به مخاطبینی گسترده‌تر یاریتان کنند. کمی وقت برای بازبینی این تنظیمات گذاشته تا مطمئن شوید برایتان مناسبند." privacy: محرمانگی + privacy_hint_html: واپایش میزان باز شدن به نفع دیگران. افراد نمایه‌های جالب و کاره‌های باحال را با مرور پی‌گرفتگان دیگران و دیدن کاره‌هایی که از آن‌ها می‌فرستند پیدا می‌کنند. با این حال شاید بخواهید پنهان نگهشان دارید. reach: دسترسی reach_hint_html: واپایش این که می‌خواهید به دست افراد جدید قابل کشف و پی‌گیری باشید یا نه. می‌خواهید فرسته‌هایتان روی صفحهٔ کشف ظاهر شوند؟ می‌خواهید دیگر افراد در پیشنهادهای پی‌گیریشان ببینندتان؟ می‌خواهید پی‌گیران جدید را به طور خودکار بپذیرید یا روی هرکدامشان واپایش داشته باشید؟ search: جست‌وجو @@ -1438,7 +1441,7 @@ fa: delete: پاک‌کردن حساب development: فرابری edit_profile: ویرایش نمایه - export: برون‌سپاری داده‌ها + export: برون‌ریزی featured_tags: برچسب‌های برگزیده import: درون‌ریزی import_and_export: درون‌ریزی و برون‌بری @@ -1447,12 +1450,21 @@ fa: preferences: ترجیحات profile: نمایه relationships: پیگیری‌ها و پیگیران + severed_relationships: ارتباط‌های قطع شده statuses_cleanup: حذف فرستهٔ خودکار strikes: شکایت‌های مدیریتی two_factor_authentication: ورود دومرحله‌ای webauthn_authentication: کلیدهای امنیتی severed_relationships: download: بارگیری (%{count}) + event_type: + account_suspension: تعلیق حساب (%{target_name}) + domain_block: تعلیق کارساز (%{target_name}) + user_domain_block: "%{target_name} را مسدود کردید" + lost_followers: پی‌گیرندگان از دست رفته + lost_follows: پی‌گرفته‌ّای از دست رفته + preamble: وقتی دامنه‌ای را مسدود کرده یا ناظرانتان تصمیم به تعلیق کارسازی دوردست می‌گیرند، ممکن است پی‌گیران و پی‌گرفته‌هایتان را از دست بدهید. با این حال قادرید سیاهه‌هایی از ارتباط‌های قطع شده را برای بررسی و درون‌ریزی احتمالی روی کارسازی دیگر بار بگیرید. + purged: اطّلاعات دربارهٔ این کارساز به دست مدیران کارسازتان پاک سازی شده. type: رویداد statuses: attached: @@ -1536,6 +1548,7 @@ fa: contrast: ماستودون (سایه‌روشن بالا) default: ماستودون (تیره) mastodon-light: ماستودون (روشن) + system: خودکار (استفاده از زمینهٔ سامانه) time: formats: default: "%d %b %Y, %H:%M" @@ -1617,6 +1630,7 @@ fa: instructions_html: کد زیر را رونوشت کرده و در HTML پایگاه وبتان جایگذاری کنید. سپس نشانی پایگاه وبتان را از زبانهٔ «ویرایش نمایه» در یکی از زمینه‌های اضافی روی نمایه‌تان افزوده و تغییرات را ذخیره کنید. verification: تأیید verified_links: "‏پیوندهای تأییدشده‌ شما" + website_verification: تأیید پایگاه وب webauthn_credentials: add: افزودن کلید امنیتی create: diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 5df82bff9fa440..2f9a76c80d4d24 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -21,6 +21,7 @@ fi: one: Julkaisu other: viestiä posts_tab_heading: Julkaisut + self_follow_error: Oman tilisi seuraaminen ei ole sallittua admin: account_actions: action: Suorita toimi @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ fi: use_security_key: Käytä suojausavainta author_attribution: example_title: Esimerkkiteksti - hint_html: Määrää, kuinka tulet tunnustetuksi, kun Mastodonissa jaetaan linkkejä. + hint_html: Kirjoitatko uutisia tai blogitekstejä Mastodonin ulkopuolella? Määrää, kuinka tulet tunnustetuksi, kun niitä jaetaan Mastodonissa. + instructions: 'Varmista, että artikkelisi HTML:ssä on tämä koodi:' more_from_html: Lisää tekijältä %{name} s_blog: Käyttäjän %{name} blogi + then_instructions: Lisää sitten julkaisun verkkotunnus seuraavaan tekstikenttään. title: Tekijän tunnustus challenge: confirm: Jatka @@ -1363,19 +1369,43 @@ fi: overwrite: Korvaa overwrite_long: Korvaa nykyiset tietueet uusilla overwrite_preambles: - blocking_html: Olet aikeissa korvata estoluettelosi kaikkiaan %{total_items} tilillä tiedostosta %{filename}. - bookmarks_html: Olet aikeissa korvata kirjanmerkkisi kaikkiaan %{total_items} julkaisulla tiedostosta %{filename}. - domain_blocking_html: Olet aikeissa korvata verkkotunnusten estoluettelosi kaikkiaan %{total_items} verkkotunnuksella tiedostosta %{filename}. - following_html: Olet aikeissa seurata kaikkiaan %{total_items} tiliä tiedostosta %{filename} ja lopettaa kaikkien muiden seuraamisen. - lists_html: Olet aikeissa korvata listojasi tiedoston %{filename} sisällöllä. Uusiin listoihin lisätään kaikkiaan %{total_items} tiliä. - muting_html: Olet aikeissa korvata mykistettyjen tilien luettelosi kaikkiaan %{total_items} tilillä tiedostosta %{filename}. + blocking_html: + one: Olet aikeissa korvata estoluettelosi kaikkiaan %{count} tilillä tiedostosta %{filename}. + other: Olet aikeissa korvata estoluettelosi kaikkiaan %{count} tilillä tiedostosta %{filename}. + bookmarks_html: + one: Olet aikeissa korvata kirjanmerkkisi kaikkiaan %{count} julkaisulla tiedostosta %{filename}. + other: Olet aikeissa korvata kirjanmerkkisi kaikkiaan %{count} julkaisulla tiedostosta %{filename}. + domain_blocking_html: + one: Olet aikeissa korvata verkkotunnusten estoluettelosi kaikkiaan %{count} verkkotunnuksella tiedostosta %{filename}. + other: Olet aikeissa korvata verkkotunnusten estoluettelosi kaikkiaan %{count} verkkotunnuksella tiedostosta %{filename}. + following_html: + one: Olet aikeissa seurata kaikkiaan %{count} tiliä tiedostosta %{filename} ja lopettaa kaikkien muiden seuraamisen. + other: Olet aikeissa seurata kaikkiaan %{count} tiliä tiedostosta %{filename} ja lopettaa kaikkien muiden seuraamisen. + lists_html: + one: Olet aikeissa korvata listojasi tiedoston %{filename} sisällöllä. Uusiin listoihin lisätään kaikkiaan %{count} tili. + other: Olet aikeissa korvata listojasi tiedoston %{filename} sisällöllä. Uusiin listoihin lisätään kaikkiaan %{count} tiliä. + muting_html: + one: Olet aikeissa korvata mykistettyjen tilien luettelosi kaikkiaan %{count} tilillä tiedostosta %{filename}. + other: Olet aikeissa korvata mykistettyjen tilien luettelosi kaikkiaan %{count} tilillä tiedostosta %{filename}. preambles: - blocking_html: Olet aikeissa estää kaikkiaan %{total_items} tiliä tiedostosta %{filename}. - bookmarks_html: Olet aikeissa lisätä kaikkiaan %{total_items} julkaisua tiedostosta %{filename}kirjanmerkkeihisi. - domain_blocking_html: Olet aikeissa estää kaikkiaan %{total_items} verkkotunnusta tiedostosta %{filename}. - following_html: Olet aikeissa seurata kaikkiaan %{total_items} tiliä tiedostosta %{filename}. - lists_html: Olet aikeissa lisätä listoihisi kaikkiaan %{total_items} tiliä tiedostosta %{filename}. Uusia listoja luodaan, jos sopivaa kohdelistaa ei ole olemassa. - muting_html: Olet aikeissa mykistää kaikkiaan %{total_items} tiliä tiedostosta %{filename}. + blocking_html: + one: Olet aikeissa estää kaikkiaan %{count} tilin tiedostosta %{filename}. + other: Olet aikeissa estää kaikkiaan %{count} tiliä tiedostosta %{filename}. + bookmarks_html: + one: Olet aikeissa lisätä kaikkiaan %{count} julkaisun tiedostosta %{filename}kirjanmerkkeihisi. + other: Olet aikeissa lisätä kaikkiaan %{count} julkaisua tiedostosta %{filename}kirjanmerkkeihisi. + domain_blocking_html: + one: Olet aikeissa estää kaikkiaan %{count} verkkotunnuksen tiedostosta %{filename}. + other: Olet aikeissa estää kaikkiaan %{count} verkkotunnusta tiedostosta %{filename}. + following_html: + one: Olet aikeissa seurata kaikkiaan %{count} tiliä tiedostosta %{filename}. + other: Olet aikeissa seurata kaikkiaan %{count} tiliä tiedostosta %{filename}. + lists_html: + one: Olet aikeissa lisätä listoihisi kaikkiaan %{count} tilin tiedostosta %{filename}. Uusia listoja luodaan, jos sopivaa kohdelistaa ei ole olemassa. + other: Olet aikeissa lisätä listoihisi kaikkiaan %{count} tiliä tiedostosta %{filename}. Uusia listoja luodaan, jos sopivaa kohdelistaa ei ole olemassa. + muting_html: + one: Olet aikeissa mykistää kaikkiaan %{count} tilin tiedostosta %{filename}. + other: Olet aikeissa mykistää kaikkiaan %{count} tiliä tiedostosta %{filename}. preface: Voit tuoda toiselta palvelimelta viemiäsi tietoja, kuten seuraamiesi tai estämiesi käyttäjien luettelon. recent_imports: Viimeksi tuotu states: @@ -1692,7 +1722,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 @@ -1937,7 +1967,7 @@ fi: signed_in_as: 'Kirjautunut tilillä:' verification: extra_instructions_html: Vinkki: Verkkosivustollasi oleva linkki voi olla myös näkymätön. Olennainen osuus on rel="me", joka estää toiseksi henkilöksi tekeytymisen verkkosivustoilla, joilla on käyttäjien luomaa sisältöä. Voit käyttää jopa link-elementtiä sivun head-osassa elementin a sijaan, mutta HTML:n pitää olla käytettävissä ilman JavaScript-koodin suorittamista. - here_is_how: Näin voit tehdä sen + here_is_how: Näin se onnistuu hint_html: "Henkilöllisyyden vahvistaminen on Mastodonissa jokaisen käyttäjän ulottuvilla. Se perustuu avoimiin standardeihin ja on maksutonta nyt ja aina. Tarvitset vain henkilökohtaisen verkkosivuston, jonka perusteella sinut voidaan tunnistaa. Kun teet linkin tuolle verkkosivulle profiilistasi, tarkistamme, että verkkosivustolla on linkki takaisin profiiliisi, ja näytämme profiilissasi visuaalisen ilmaisimen." instructions_html: Kopioi ja liitä seuraava koodi verkkosivustosi HTML-lähdekoodiin. Lisää sitten verkkosivustosi osoite johonkin profiilisi lisäkentistä ”Muokkaa profiilia” -välilehdellä ja tallenna muutokset. verification: Vahvistus diff --git a/config/locales/fo.yml b/config/locales/fo.yml index ce21aa3be7c44f..3ade3007f44a56 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -21,6 +21,7 @@ fo: one: Uppslag other: Uppsløg posts_tab_heading: Uppsløg + self_follow_error: Tað er ikki loyvt at fylgja tíni egnu kontu admin: account_actions: action: Frem atgerð @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ fo: use_security_key: Brúka trygdarlykil author_attribution: example_title: Tekstadømi - hint_html: Kanna, hvussu tú verður viðurkend/ur, tá ið onnur deila slóðir á Mastodon. + hint_html: Skrivar tú tíðindi ella greinar til bloggin uttanfyri Mastodon? Her kanst tú stýra, hvussu tú verður tilsipað/ur, tá ið títt tilfar verður deilt á Mastodon. + instructions: 'Tryggja tær, at henda kota er í HTML''inum á tíni grein:' more_from_html: Meiri frá %{name} s_blog: Bloggurin hjá %{name} + then_instructions: Skriva síðani økisnavnið, har tað verður lagt út, í teigin niðanfyri. title: Ískoyti høvundans challenge: confirm: Hald á @@ -1362,20 +1368,6 @@ fo: merge_long: Varðveit verandi teigarøð og legg nýggjar afturat overwrite: Skriva omaná overwrite_long: Legg nýggj teigarøð inn fyri tey verandi - overwrite_preambles: - blocking_html: Tú ert í ferð við at útskifta blokeringslistan hjá tær við upp til %{total_items} kontum frá %{filename}. - bookmarks_html: Tú ert í ferð við at útskifta tíni bókamerki við upp til %{total_items} postum frá %{filename}. - domain_blocking_html: Tú ert í ferð við at útskifta navnaøkisblokeringslistan hjá tær við upp til %{total_items} navnaøkjum frá %{filename}. - following_html: Tú ert í ferð við at fylgja upp til %{total_items} kontum frá %{filename} og at gevast at fylgja øðrum. - lists_html: Tú ert í ferð við at skifta listarnar hjá tær út við tað, sum er í %{filename}. Upp til %{total_items} kontur verða lagdar afturat nýggjum listum. - muting_html: Tú ert í ferð við at útskifta listan hjá tær við doyvdum kontum við upp til %{total_items} kontum frá %{filename}. - preambles: - blocking_html: Tú ert í ferð við at blokera upp til %{total_items} kontur frá %{filename}. - bookmarks_html: Tú ert í ferð við at leggja upp til %{total_items} postar frá %{filename} afturat tínum bókamerkjum. - domain_blocking_html: Tú ert í ferð við at blokera upp til %{total_items} navnaøki frá %{filename}. - following_html: Tú ert í ferð við at fylgja upp til %{total_items} kontur frá %{filename}. - lists_html: Tú ert í ferð við at leggja upp til %{total_items} kontur frá %{filename} afturat tínum listum. Nýggir listar verða stovnaðir, um eingin listi er at leggja afturat. - muting_html: Tú ert í ferð við at doyva upp til %{total_items} kontur frá %{filename}. preface: Tú kanst innlesa dátur, sum tú hevur útlisið frá einum øðrum ambætara, so sum listar av fólki, sum tú fylgir ella blokerar. recent_imports: Feskar innflytingar states: @@ -1692,7 +1684,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..3c771d4c6430ff 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -21,6 +21,7 @@ fr-CA: one: Message other: Messages posts_tab_heading: Messages + self_follow_error: Il n'est pas possible de suivre votre propre compte admin: account_actions: action: Effectuer l'action @@ -262,8 +263,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 +879,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. @@ -1163,7 +1169,6 @@ fr-CA: use_security_key: Utiliser la clé de sécurité author_attribution: example_title: Exemple de texte - hint_html: Déterminez la façon dont vous êtes crédité lorsque des liens sont partagés sur Mastodon. more_from_html: Plus via %{name} s_blog: Blog de %{name} title: Attribution de l'auteur·e @@ -1364,19 +1369,43 @@ fr-CA: overwrite: Écraser overwrite_long: Remplacer les enregistrements actuels par les nouveaux overwrite_preambles: - blocking_html: Vous allez remplacer votre liste de blocages par jusqu'à %{total_items} comptes tirés de %{filename}. - bookmarks_html: Vous allez remplacer vos signets par jusqu'à %{total_items} posts tirés de %{filename}. - domain_blocking_html: Vous allez remplacer votre liste de blocages de domaines par jusqu'à %{total_items} domaines tirés de %{filename}. - following_html: Vous allez suivre jusqu’à %{total_items} comptes depuis %{filename} et arrêter de suivre n’importe qui d’autre. - lists_html: Vous allez remplacer vos listes par le contenu de %{filename}. Jusqu'à %{total_items} comptes seront ajoutés à de nouvelles listes. - muting_html: Vous allez remplacer votre liste de comptes masqués par jusqu'à %{total_items} comptes tirés de %{filename}. + blocking_html: + one: Vous allez remplacer votre liste de blocage par près de %{count} compte tiré de %{filename}. + other: Vous allez remplacer votre liste de blocage par près de %{count} comptes tirés de %{filename}. + bookmarks_html: + one: Vous allez remplacer vos signets par près de %{count} post tiré de %{filename}. + other: Vous allez remplacer vos signets par près de %{count} posts tirés de %{filename}. + domain_blocking_html: + one: Vous allez remplacer votre liste de blocage de domaines par près de %{count} domaine tiré de %{filename}. + other: Vous allez remplacer votre liste de blocage de domaines par près de %{count} domaines tirés de %{filename}. + following_html: + one: Vous allez suivre jusqu’à %{count} compte depuis %{filename} et arrêter de suivre n’importe qui d’autre. + other: Vous allez suivre jusqu’à %{count} comptes depuis %{filename} et arrêter de suivre n’importe qui d’autre. + lists_html: + one: Vous allez remplacer vos listes par le contenu de %{filename}. Près de %{count} compte sera ajouté à de nouvelles listes. + other: Vous allez remplacer vos listes par le contenu de %{filename}. Près de %{count} comptes seront ajoutés à de nouvelles listes. + muting_html: + one: Vous allez remplacer votre liste de comptes masqués par près de %{count} compte tiré de %{filename}. + other: Vous allez remplacer votre liste de comptes masqués par près de %{count} comptes tirés de %{filename}. preambles: - blocking_html: Vous allez bloquer jusqu'à %{total_items} comptes tirés de %{filename}. - bookmarks_html: Vous allez ajouter jusqu'à %{total_items} messages de %{filename} à vos signets. - domain_blocking_html: Vous allez bloquer jusqu'à %{total_items} domaines tirés de %{filename}. - following_html: Vous allez suivre jusqu'à %{total_items} comptes tirés de %{filename}. - lists_html: Vous allez ajouter jusqu'à %{total_items} comptes depuis %{filename} à vos listes. De nouvelles listes seront créées s'il n'y a aucune liste à laquelle les ajouter. - muting_html: Vous allez masquer jusqu'à %{total_items} comptes tirés de %{filename}. + blocking_html: + one: Vous allez bloquer près de %{count} compte tiré de %{filename}. + other: Vous allez bloquer près de %{count} comptes tirés de %{filename}. + bookmarks_html: + one: Vous allez ajouter près de %{count} message de %{filename} à vos signets. + other: Vous allez ajouter près de %{count} messages de %{filename} à vos signets. + domain_blocking_html: + one: Vous allez bloquer près de %{count} domaine tiré de %{filename}. + other: Vous allez bloquer près de %{count} domaines tirés de %{filename}. + following_html: + one: Vous allez suivre près de %{count} compte tiré de %{filename}. + other: Vous allez suivre près de %{count} comptes tirés de %{filename}. + lists_html: + one: Vous allez ajouter près de %{count} compte depuis %{filename} à vos listes. De nouvelles listes seront créées si besoin. + other: Vous allez ajouter près de %{count} comptes depuis %{filename} à vos listes. De nouvelles listes seront créées si besoin. + muting_html: + one: Vous allez masquer près de %{count} compte tiré de %{filename}. + other: Vous allez masquer près de %{count} comptes tirés de %{filename}. preface: Vous pouvez importer certaines données que vous avez exporté d’un autre serveur, comme une liste des personnes que vous suivez ou bloquez sur votre compte. recent_imports: Importations récentes states: @@ -1447,6 +1476,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 +1722,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..58fc63fc1baaea 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -21,6 +21,7 @@ fr: one: Message other: Messages posts_tab_heading: Messages + self_follow_error: Il n'est pas possible de suivre votre propre compte admin: account_actions: action: Effectuer l'action @@ -262,8 +263,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 +430,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 +879,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. @@ -1163,7 +1169,6 @@ fr: use_security_key: Utiliser la clé de sécurité author_attribution: example_title: Exemple de texte - hint_html: Déterminez la façon dont vous êtes crédité lorsque des liens sont partagés sur Mastodon. more_from_html: Plus via %{name} s_blog: Blog de %{name} title: Attribution de l'auteur·e @@ -1364,19 +1369,43 @@ fr: overwrite: Écraser overwrite_long: Remplacer les enregistrements actuels par les nouveaux overwrite_preambles: - blocking_html: Vous allez remplacer votre liste de blocage par près de %{total_items} comptes tirés de %{filename}. - bookmarks_html: Vous allez remplacer vos signets par près de %{total_items} posts tirés de %{filename}. - domain_blocking_html: Vous allez remplacer votre liste de blocage de domaines par près de %{total_items} domaines tirés de %{filename}. - following_html: Vous allez suivre jusqu’à %{total_items} comptes depuis %{filename} et arrêter de suivre n’importe qui d’autre. - lists_html: Vous allez remplacer vos listes par le contenu de %{filename}. Près de %{total_items} comptes seront ajoutés à de nouvelles listes. - muting_html: Vous allez remplacer votre liste de comptes masqués par près de %{total_items} comptes tirés de %{filename}. + blocking_html: + one: Vous allez remplacer votre liste de blocage par près de %{count} compte tiré de %{filename}. + other: Vous allez remplacer votre liste de blocage par près de %{count} comptes tirés de %{filename}. + bookmarks_html: + one: Vous allez remplacer vos signets par près de %{count} post tiré de %{filename}. + other: Vous allez remplacer vos signets par près de %{count} posts tirés de %{filename}. + domain_blocking_html: + one: Vous allez remplacer votre liste de blocage de domaines par près de %{count} domaine tiré de %{filename}. + other: Vous allez remplacer votre liste de blocage de domaines par près de %{count} domaines tirés de %{filename}. + following_html: + one: Vous allez suivre jusqu’à %{count} compte depuis %{filename} et arrêter de suivre n’importe qui d’autre. + other: Vous allez suivre jusqu’à %{count} comptes depuis %{filename} et arrêter de suivre n’importe qui d’autre. + lists_html: + one: Vous allez remplacer vos listes par le contenu de %{filename}. Près de %{count} compte sera ajouté à de nouvelles listes. + other: Vous allez remplacer vos listes par le contenu de %{filename}. Près de %{count} comptes seront ajoutés à de nouvelles listes. + muting_html: + one: Vous allez remplacer votre liste de comptes masqués par près de %{count} compte tiré de %{filename}. + other: Vous allez remplacer votre liste de comptes masqués par près de %{count} comptes tirés de %{filename}. preambles: - blocking_html: Vous allez bloquer près de %{total_items} comptes tirés de %{filename}. - bookmarks_html: Vous allez ajouter près de %{total_items} messages de %{filename} à vos signets. - domain_blocking_html: Vous allez bloquer près de %{total_items} domaines tirés de %{filename}. - following_html: Vous allez suivre près de %{total_items} comptes tirés de %{filename}. - lists_html: Vous allez ajouter près de %{total_items} comptes depuis %{filename} à vos listes. De nouvelles listes seront créées si besoin. - muting_html: Vous allez masquer près de %{total_items} comptes tirés de %{filename}. + blocking_html: + one: Vous allez bloquer près de %{count} compte tiré de %{filename}. + other: Vous allez bloquer près de %{count} comptes tirés de %{filename}. + bookmarks_html: + one: Vous allez ajouter près de %{count} message de %{filename} à vos signets. + other: Vous allez ajouter près de %{count} messages de %{filename} à vos signets. + domain_blocking_html: + one: Vous allez bloquer près de %{count} domaine tiré de %{filename}. + other: Vous allez bloquer près de %{count} domaines tirés de %{filename}. + following_html: + one: Vous allez suivre près de %{count} compte tiré de %{filename}. + other: Vous allez suivre près de %{count} comptes tirés de %{filename}. + lists_html: + one: Vous allez ajouter près de %{count} compte depuis %{filename} à vos listes. De nouvelles listes seront créées si besoin. + other: Vous allez ajouter près de %{count} comptes depuis %{filename} à vos listes. De nouvelles listes seront créées si besoin. + muting_html: + one: Vous allez masquer près de %{count} compte tiré de %{filename}. + other: Vous allez masquer près de %{count} comptes tirés de %{filename}. preface: Vous pouvez importer certaines données que vous avez exporté d’un autre serveur, comme une liste des personnes que vous suivez ou bloquez sur votre compte. recent_imports: Récents imports states: @@ -1447,6 +1476,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 +1722,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..8ccedd2be17753 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -24,6 +24,8 @@ fy: admin: account_actions: action: Aksje útfiere + already_silenced: Dizze account is al beheind. + already_suspended: Dizze account is al opskort. title: Moderaasjemaatregelen tsjin %{acct} nimme account_moderation_notes: create: Lit in opmerking efter @@ -45,6 +47,7 @@ fy: title: E-mailadres foar %{username} wizigje change_role: changed_msg: Rol mei sukses wizige! + edit_roles: Brûkersrollen beheare label: Rol wizigje no_role: Gjin rol title: Rol fan %{username} wizigje @@ -601,6 +604,7 @@ fy: suspend_description_html: De account en alle ynhâld sil net tagonklik wêze en úteinlik fuortsmiten wurde, en ynteraksje hjirmei sil net mooglik wêze. Binnen 30 dagen werom te draaien. Dit slút alle rapportaazjes oer dizze account. actions_description_html: Beslis hokker maatregel nommen wurde moat om dizze rapportaazje op te lossen. Wannear’t jo in (straf)maatregel tsjin it rapportearre account nimme, kriget de account in e-mailmelding, behalve wannear’t de spam-kategory keazen is. actions_description_remote_html: Beslút hokker aksje nommen wurde moat om dizze rapportaazje ôf te hanneljen. Dit hat allinnich ynfloed op hoe’t jo server kommunisearret mei dizze eksterne account en omgiet mei de ynhâld. + actions_no_posts: Dit rapport hat gjin byhearrende berjochten om fuort te smiten add_to_report: Mear oan de rapportaazje tafoegje already_suspended_badges: local: Al opskoarte op dizze server @@ -871,6 +875,9 @@ fy: message_html: Jo hawwe foar dizze server gjin regels opsteld. sidekiq_process_check: message_html: Der draait gjin Sidekiq-proses foar de wachtrige(n) %{value}. Kontrolearje jo Sidekiq-konfiguraasje + software_version_check: + action: Beskikbere fernijingen besjen + message_html: Der is in Mastodon-fernijing beskikber. software_version_critical_check: action: Beskikbere fernijingen besjen message_html: Der is in kritike fernijing foar Mastodon beskikber. Wurkje sa gau as mooglik by. @@ -1156,6 +1163,11 @@ fy: view_strikes: Besjoch de earder troch moderatoaren fêststelde skeiningen dy’t jo makke hawwe too_fast: Formulier is te fluch yntsjinne. Probearje it nochris. use_security_key: Befeiligingskaai brûke + author_attribution: + example_title: Faorbyldtekst + more_from_html: Mear fan %{name} + s_blog: Weblog fan %{name} + title: Auteur-attribúsje challenge: confirm: Trochgean hint_html: "Tip: Wy freegje jo it kommende oere net mear nei jo wachtwurd." @@ -1353,19 +1365,43 @@ fy: overwrite: Oerskriuwe overwrite_long: Aktuele gegevens mei de nije gegevens ferfange overwrite_preambles: - blocking_html: Jo steane op it punt om jo blokkearlist mei mear as %{total_items} accounts fan %{filename} te ferfangen. - bookmarks_html: Jo steane op it punt om jo blêdwizers mei mear as %{total_items} artikelen fan %{filename} te ferfangen. - domain_blocking_html: Jo steane op it punt om jo domeinblokkearlist mei mear as %{total_items} domeinen fan %{filename} te ferfangen. - following_html: Jo steane op it punt om %{total_items} accounts út %{filename} te folgjen en te stopjen mei folgjen fan alle oaren. - lists_html: Jo steane op it punt jo listen te ferfangen troch ynhâld fan %{filename}. Oant %{total_items} accounts sille oan nije listen tafoege wurde. - muting_html: Jo steane op it punt om jo list mei negearre accounts mei mear as %{total_items} accounts fan %{filename} út te ferfangen. + blocking_html: + one: Jo steane op it punt om jo blokkearlist mei mear as %{count} account fan %{filename} te ferfangen. + other: Jo steane op it punt om jo blokkearlist mei mear as %{count} accounts fan %{filename} te ferfangen. + bookmarks_html: + one: Jo steane op it punt om jo blêdwizers mei mear as %{count} artikel fan %{filename} te ferfangen. + other: Jo steane op it punt om jo blêdwizers mei mear as %{count} artikelen fan %{filename} te ferfangen. + domain_blocking_html: + one: Jo steane op it punt om jo domeinblokkearlist mei mear as %{count} domein fan %{filename} te ferfangen. + other: Jo steane op it punt om jo domeinblokkearlist mei mear as %{count} domeinen fan %{filename} te ferfangen. + following_html: + one: Jo steane op it punt om %{count} account út %{filename} te folgjen en te stopjen mei folgjen fan alle oaren. + other: Jo steane op it punt om %{count} accounts út %{filename} te folgjen en te stopjen mei folgjen fan alle oaren. + lists_html: + one: Jo steane op it punt jo listen te ferfangen troch ynhâld fan %{filename}. Oant %{count} account sille oan nije listen tafoege wurde. + other: Jo steane op it punt jo listen te ferfangen troch ynhâld fan %{filename}. Oant %{count} accounts sille oan nije listen tafoege wurde. + muting_html: + one: Jo steane op it punt om jo list mei negearre accounts mei mear as %{count} account fan %{filename} út te ferfangen. + other: Jo steane op it punt om jo list mei negearre accounts mei mear as %{count} accounts fan %{filename} út te ferfangen. preambles: - blocking_html: Jo steane op it punt om %{total_items} accounts fan %{filename} út te blokkearjen. - bookmarks_html: Jo steane op it punt om %{total_items} berjochten fan %{filename} út oan jo blêdwizers ta te foegjen. - domain_blocking_html: Jo steane op it punt om %{total_items} domeinen fan %{filename} út te blokkearjen. - following_html: Jo steane op it punt om %{total_items} accounts fan %{filename} út te folgjen. - lists_html: Jo steane op it punt om oant %{total_items} accounts fan %{filename} ta te foegjen oan jo listen. Nije listen wurde oanmakke as der gjin list is om oan ta te foegjen. - muting_html: Jo steane op it punt om %{total_items} accounts fan %{filename} út te negearjen. + blocking_html: + one: Jo steane op it punt om %{count} account fan %{filename} út te blokkearjen. + other: Jo steane op it punt om %{count} accounts fan %{filename} út te blokkearjen. + bookmarks_html: + one: Jo steane op it punt om %{count} berjocht fan %{filename} út oan jo blêdwizers ta te foegjen. + other: Jo steane op it punt om %{count} berjochten fan %{filename} út oan jo blêdwizers ta te foegjen. + domain_blocking_html: + one: Jo steane op it punt om %{count} domein fan %{filename} út te blokkearjen. + other: Jo steane op it punt om %{count} domeinen fan %{filename} út te blokkearjen. + following_html: + one: Jo steane op it punt om %{count} account fan %{filename} út te folgjen. + other: Jo steane op it punt om %{count} accounts fan %{filename} út te folgjen. + lists_html: + one: Jo steane op it punt om oant %{count} account fan %{filename} ta te foegjen oan jo listen. Nije listen wurde oanmakke as der gjin list is om oan ta te foegjen. + other: Jo steane op it punt om oant %{count} accounts fan %{filename} ta te foegjen oan jo listen. Nije listen wurde oanmakke as der gjin list is om oan ta te foegjen. + muting_html: + one: Jo steane op it punt om %{count} account fan %{filename} út te negearjen. + other: Jo steane op it punt om %{count} accounts fan %{filename} út te negearjen. preface: Jo kinne bepaalde gegevens, lykas de minsken dy’t jo folgje of blokkearre hawwe, nei jo account op dizze server ymportearje. Jo moatte dizze gegevens wol earst op de oarspronklike server eksportearje. recent_imports: Resinte ymports states: @@ -1932,6 +1968,7 @@ fy: instructions_html: Kopiearje en plak de ûndersteande koade yn de HTML fan jo website. Foegje dernei it adres fan jo website ta oan ien fan de ekstra fjilden op jo profyl op it ljepblêd ‘Profyl bewurkje’ en bewarje de wizigingen. verification: Ferifikaasje verified_links: Jo ferifiearre keppelingen + website_verification: Website-ferifikaasje webauthn_credentials: add: Nije befeiligingskaai tafoegje create: diff --git a/config/locales/ga.yml b/config/locales/ga.yml index a6369354cd8a56..0657f827d1b293 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -27,6 +27,7 @@ ga: other: Postálacha two: Postálacha posts_tab_heading: Postálacha + self_follow_error: Ní cheadaítear do chuntas féin a leanúint admin: account_actions: action: Déan gníomh @@ -917,6 +918,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. @@ -1216,7 +1220,6 @@ ga: use_security_key: Úsáid eochair shlándála author_attribution: example_title: Téacs samplach - hint_html: Rialú conas a chuirtear chun sochair tú nuair a roinntear naisc ar Mastodon. more_from_html: Tuilleadh ó %{name} s_blog: Blag %{name} title: Leithdháil an údair @@ -1438,19 +1441,79 @@ ga: overwrite: Forscríobh overwrite_long: Cuir na cinn nua in ionad na dtaifead reatha overwrite_preambles: - blocking_html: Tá tú ar tí do liosta bloc a chur in ionad suas le %{total_items} cuntas ó %{filename}. - bookmarks_html: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{total_items} postáil ó %{filename}. - domain_blocking_html: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{total_items} fearainn ó %{filename}. - following_html: Tá tú ar tí leanúint suas go dtí %{total_items} cuntas ó %{filename} agus stop a leanúint aon duine eile. - lists_html: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{total_items} cuntas le liostaí nua. - muting_html: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{total_items} cuntas ó %{filename}. + blocking_html: + few: Tá tú ar tí do liosta bloc a chur in ionad suas le %{count} cuntais ó %{filename}. + many: Tá tú ar tí do liosta bloc a chur in ionad suas le %{count} cuntais ó %{filename}. + one: Tá tú ar tí do liosta bloc a chur in ionad suas le %{count} cuntas ó %{filename}. + other: Tá tú ar tí do liosta bloc a chur in ionad suas le %{count} cuntais ó %{filename}. + two: Tá tú ar tí do liosta bloc a chur in ionad suas le %{count} cuntais ó %{filename}. + bookmarks_html: + few: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{count} postáil ó %{filename}. + many: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{count} postáil ó %{filename}. + one: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{count} postáil ó %{filename}. + other: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{count} postáil ó %{filename}. + two: Tá tú ar tí do leabharmharcanna a chur in ionad suas le %{count} postáil ó %{filename}. + domain_blocking_html: + few: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{count} fearainn ó %{filename}. + many: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{count} fearainn ó %{filename}. + one: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{count} fearainn ó %{filename}. + other: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{count} fearainn ó %{filename}. + two: Tá tú ar tí do liosta bloc fearainn a chur in ionad suas le %{count} fearainn ó %{filename}. + following_html: + few: Tá tú ar tí leanúint suas go dtí %{count} cuntas ó %{filename} agus stop ag leanúint aon duine eile. + many: Tá tú ar tí leanúint suas go dtí %{count} cuntas ó %{filename} agus stop ag leanúint aon duine eile. + one: Tá tú ar tí leanúint suas go dtí %{count} chuntais ó %{filename} agus stop a leanúint aon duine eile. + other: Tá tú ar tí leanúint suas go dtí %{count} cuntas ó %{filename} agus stop ag leanúint aon duine eile. + two: Tá tú ar tí leanúint suas go dtí %{count} cuntas ó %{filename} agus stop ag leanúint aon duine eile. + lists_html: + few: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{count} cuntais le liostaí nua. + many: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{count} cuntais le liostaí nua. + one: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{count} cuntas le liostaí nua. + other: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{count} cuntais le liostaí nua. + two: Tá tú ar tí do liostaí a chur in ionad inneachair %{filename}. Cuirfear suas le %{count} cuntais le liostaí nua. + muting_html: + few: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{count} cuntais ó %{filename}. + many: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{count} cuntais ó %{filename}. + one: Tá tú ar tí do liosta cuntais balbhaithe a chur in ionad suas le %{count} cuntas ó %{filename}. + other: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{count} cuntais ó %{filename}. + two: Tá tú ar tí do liosta cuntas balbhaithe a chur in ionad suas le %{count} cuntais ó %{filename}. preambles: - blocking_html: Tá tú ar tí bloc suas le %{total_items} cuntas ó %{filename}. - bookmarks_html: Tá tú ar tí %{total_items} postáil ó %{filename} a chur le do leabharmharcanna. - domain_blocking_html: Tá tú ar tí bloc suas le %{total_items} fearainn ó %{filename}. - following_html: Tá tú ar tí leanúint suas go dtí %{total_items} cuntas ó %{filename}. - lists_html: Tá tú ar tí %{total_items} cuntas ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. - muting_html: Tá tú ar tí balbhú suas le %{total_items} cuntas ó %{filename}. + blocking_html: + few: Tá tú ar tí bhac suas le %{count} cuntais ó %{filename}. + many: Tá tú ar tí bhac suas le %{count} cuntais ó %{filename}. + one: Tá tú ar tí bac suas go dtí %{count} cuntas ó %{filename}. + other: Tá tú ar tí bhac suas le %{count} cuntais ó %{filename}. + two: Tá tú ar tí bhac suas le %{count} cuntais ó %{filename}. + bookmarks_html: + few: Tá tú ar tí %{count} postáil ó %{filename} a chur le do leabharmharcanna. + many: Tá tú ar tí %{count} postáil ó %{filename} a chur le do leabharmharcanna. + one: Tá tú ar tí %{count} postáil ó %{filename} a chur le do leabharmharcanna. + other: Tá tú ar tí %{count} postáil ó %{filename} a chur le do leabharmharcanna. + two: Tá tú ar tí %{count} postáil ó %{filename} a chur le do leabharmharcanna. + domain_blocking_html: + few: Tá tú ar tí bhac suas le %{count} bhfearainn ó %{filename}. + many: Tá tú ar tí bhac suas le %{count} bhfearainn ó %{filename}. + one: Tá tú ar tí bac suas go dtí %{count} fearann ó %{filename}. + other: Tá tú ar tí bhac suas le %{count} bhfearainn ó %{filename}. + two: Tá tú ar tí bhac suas le %{count} bhfearainn ó %{filename}. + following_html: + few: Tá tú ar tí leanúint suas go dtí %{count} cuntais ó %{filename}. + many: Tá tú ar tí leanúint suas go dtí %{count} cuntais ó %{filename}. + one: Tá tú ar tí leanúint suas go dtí %{count} cuntas ó %{filename}. + other: Tá tú ar tí leanúint suas go dtí %{count} cuntais ó %{filename}. + two: Tá tú ar tí leanúint suas go dtí %{count} cuntais ó %{filename}. + lists_html: + few: Tá tú ar tí %{count} cuntais ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + many: Tá tú ar tí %{count} cuntais ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + one: Tá tú ar tí cuntas %{count} ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + other: Tá tú ar tí %{count} cuntais ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + two: Tá tú ar tí %{count} cuntais ó %{filename} a chur le do liostaí. Cruthófar liostaí nua mura bhfuil aon liosta le cur leis. + muting_html: + few: Tá tú ar tí balbhú suas le %{count} cuntais ó %{filename}. + many: Tá tú ar tí balbhú suas le %{count} cuntais ó %{filename}. + one: Tá tú ar tí balbhú suas go dtí %{count} cuntas ó %{filename}. + other: Tá tú ar tí balbhú suas le %{count} cuntais ó %{filename}. + two: Tá tú ar tí balbhú suas le %{count} cuntais ó %{filename}. preface: Is féidir leat sonraí a d’easpórtáil tú a allmhairiú ó fhreastalaí eile, mar shampla liosta de na daoine a bhfuil tú ag leanúint nó ag cur bac orthu. recent_imports: Allmhairí le déanaí states: @@ -1770,7 +1833,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..3495a070ecfe57 100644 --- a/config/locales/gd.yml +++ b/config/locales/gd.yml @@ -25,6 +25,7 @@ gd: other: Postaichean two: Postaichean posts_tab_heading: Postaichean + self_follow_error: Chan fhaod thu an cunntas agad fhèn a leantainn admin: account_actions: action: Gabh an gnìomh @@ -903,6 +904,9 @@ gd: message_html: Cha do mhìnich thu riaghailtean an fhrithealaiche fhathast. sidekiq_process_check: message_html: Chan eil pròiseas Sidekiq sam bith a ruith dhan chiutha/dha na ciuthan %{value}. Thoir sùil air an rèiteachadh Sidekiq agad + software_version_check: + action: Faic na h-ùrachaidhean a tha ri fhaighinn + message_html: Tha ùrachadh Mastodon ri fhaighinn. software_version_critical_check: action: Faic na h-ùrachaidhean a tha ri fhaighinn message_html: Tha ùrachadh èiginneach air Mastodon ri fhaighinn, ùraich cho luath ’s a ghabhas. @@ -1021,7 +1025,7 @@ gd: delete: Sguab às edit_preset: Deasaich rabhadh ro-shuidhichte empty: Cha do mhìnich thu ro-sheataichean rabhaidhean fhathast. - title: Ro-sheataichean rabhaidhean + title: Rabhaidhean ro-shocraichte webhooks: add_new: Cuir puing-dheiridh ris delete: Sguab às @@ -1198,7 +1202,6 @@ gd: use_security_key: Cleachd iuchair tèarainteachd author_attribution: example_title: Ball-sampaill teacsa - hint_html: Stùirich mar a thèid iomradh a thoirt ort nuair a thèid ceangal a cho-roinneadh air Mastodon. more_from_html: Barrachd o %{name} s_blog: Bloga aig %{name} title: Aithris air an ùghdar @@ -1413,19 +1416,67 @@ gd: overwrite: Sgrìobh thairis air overwrite_long: Cuir na reacordan ùra an àite na feadhna a tha ann overwrite_preambles: - blocking_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a chur an àite liosta nam bacaidhean agad. - bookmarks_html: Tha thu an impis suas ri %{total_items} post(aichean) o %{filename} a chur an àite nan comharra-lìn agad. - domain_blocking_html: Tha thu an impis suas ri %{total_items} àrainn(ean) o %{filename} a chur an àite liosta nam bacaidhean àrainne agad. - following_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a leantainn agus sguiridh tu a leantainn duine sam bith eile. - lists_html: Tha thu an impis susbaint %{filename} a chur an àite nan liostaichean agad. Thèid suas ri %{total_items}cunntas(an) a chur ri liostaichean ùra. - muting_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a chur an àite liosta nan cunntasan mùchte agad. + blocking_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a chur an àite liosta nam bacaidhean agad. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur an àite liosta nam bacaidhean agad. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a chur an àite liosta nam bacaidhean agad. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur an àite liosta nam bacaidhean agad. + bookmarks_html: + few: Tha thu an impis suas ri %{count} postaichean o %{filename} a chur an àite nan comharra-lìn agad. + one: Tha thu an impis suas ri %{count} phost o %{filename} a chur an àite nan comharra-lìn agad. + other: Tha thu an impis suas ri %{count} post o %{filename} a chur an àite nan comharra-lìn agad. + two: Tha thu an impis suas ri %{count} phost o %{filename} a chur an àite nan comharra-lìn agad. + domain_blocking_html: + few: Tha thu an impis suas ri %{count} àrainnean o %{filename} a chur an àite liosta nam bacaidhean àrainne agad. + one: Tha thu an impis suas ri %{count} àrainn o %{filename} a chur an àite liosta nam bacaidhean àrainne agad. + other: Tha thu an impis suas ri %{count} àrainn o %{filename} a chur an àite liosta nam bacaidhean àrainne agad. + two: Tha thu an impis suas ri %{count} àrainn o %{filename} a chur an àite liosta nam bacaidhean àrainne agad. + following_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a leantainn agus sguiridh tu a leantainn duine sam bith eile. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a leantainn agus sguiridh tu a leantainn duine sam bith eile. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a leantainn agus sguiridh tu a leantainn duine sam bith eile. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a leantainn agus sguiridh tu a leantainn duine sam bith eile. + lists_html: + few: Tha thu an impis susbaint %{filename} a chur an àite nan liostaichean agad. Thèid suas ri %{count} cunntasan a chur ri liostaichean ùra. + one: Tha thu an impis susbaint %{filename} a chur an àite nan liostaichean agad. Thèid suas ri %{count} chunntas a chur ri liostaichean ùra. + other: Tha thu an impis susbaint %{filename} a chur an àite nan liostaichean agad. Thèid suas ri %{count} cunntas a chur ri liostaichean ùra. + two: Tha thu an impis susbaint %{filename} a chur an àite nan liostaichean agad. Thèid suas ri %{count} chunntas a chur ri liostaichean ùra. + muting_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a chur an àite liosta nan cunntasan mùchte agad. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur an àite liosta nan cunntasan mùchte agad. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a chur an àite liosta nan cunntasan mùchte agad. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur an àite liosta nan cunntasan mùchte agad. preambles: - blocking_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a bhacadh. - bookmarks_html: Tha thu an impis suas ri %{total_items} post(aichean) o %{filename} a chur ris na h-annsachdan agad. - domain_blocking_html: Tha thu an impis suas ri %{total_items} àrainn(ean) o %{filename} a bhacadh. - following_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a leantainn. - lists_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a chur ris na liostaichean agad. Thèid liostaichean ùra a chruthachadh mur eil liostaichean ann airson nan cunntasan a chur ris. - muting_html: Tha thu an impis suas ri %{total_items} cunntas(an) o %{filename} a mhùchadh. + blocking_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a bhacadh. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a bhacadh. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a bhacadh. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a bhacadh. + bookmarks_html: + few: Tha thu an impis suas ri %{count} postaichean o %{filename} a chur ris na h-annsachdan agad. + one: Tha thu an impis suas ri %{count} phost o %{filename} a chur ris na h-annsachdan agad. + other: Tha thu an impis suas ri %{count} post o %{filename} a chur ris na h-annsachdan agad. + two: Tha thu an impis suas ri %{count} phost o %{filename} a chur ris na h-annsachdan agad. + domain_blocking_html: + few: Tha thu an impis suas ri %{count} àrainnean o %{filename} a bhacadh. + one: Tha thu an impis suas ri %{count} àrainn o %{filename} a bhacadh. + other: Tha thu an impis suas ri %{count} àrainn o %{filename} a bhacadh. + two: Tha thu an impis suas ri %{count} àrainn o %{filename} a bhacadh. + following_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a leantainn. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a leantainn. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a leantainn. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a leantainn. + lists_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a chur ris na liostaichean agad. Thèid liostaichean ùra a chruthachadh mur eil liostaichean ann airson nan cunntasan a chur ris. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur ris na liostaichean agad. Thèid liostaichean ùra a chruthachadh mur eil liostaichean ann airson nan cunntasan a chur ris. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a chur ris na liostaichean agad. Thèid liostaichean ùra a chruthachadh mur eil liostaichean ann airson nan cunntasan a chur ris. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a chur ris na liostaichean agad. Thèid liostaichean ùra a chruthachadh mur eil liostaichean ann airson nan cunntasan a chur ris. + muting_html: + few: Tha thu an impis suas ri %{count} cunntasan o %{filename} a mhùchadh. + one: Tha thu an impis suas ri %{count} chunntas o %{filename} a mhùchadh. + other: Tha thu an impis suas ri %{count} cunntas o %{filename} a mhùchadh. + two: Tha thu an impis suas ri %{count} chunntas o %{filename} a mhùchadh. preface: "’S urrainn dhut dàta ion-phortadh a dh’às-phortaich thu o fhrithealaiche eile, can liosta nan daoine a leanas tu no a tha thu a’ bacadh." recent_imports: Ion-phortaidhean o chionn goirid states: @@ -1744,7 +1795,7 @@ gd: delete: Sguabadh às cunntais development: Leasachadh edit_profile: Deasaich a’ phròifil - export: Às-phortadh dàta + export: Às-phortadh 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..a4f63a50e06247 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -21,6 +21,7 @@ gl: one: Publicación other: Publicacións posts_tab_heading: Publicacións + self_follow_error: Non está permitido seguir a túa propia conta admin: account_actions: action: Executar acción @@ -543,7 +544,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 +603,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 +876,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. @@ -1162,9 +1166,11 @@ gl: use_security_key: Usa chave de seguridade author_attribution: example_title: Texto de mostra - hint_html: Controla o xeito en que te acreditan cando se comparten ligazóns en Mastodon. + hint_html: Escribes novas ou artigos nun blog alleos a Mastodon? Xestiona o xeito en que podes dar crédito da túa autoría cando os compartes en Mastodon. + instructions: 'Pon coidado en que este código apareza no HTML do teu artigo:' more_from_html: Máis de %{name} s_blog: Blog de %{name} + then_instructions: Despois engade o nome de dominio da publicación no campo inferior. title: Atribución da autoría challenge: confirm: Continuar @@ -1363,19 +1369,43 @@ gl: overwrite: Sobreescribir overwrite_long: Sustituír rexistros actuais cos novos overwrite_preambles: - blocking_html: Vas substituír a lista de bloqueos por %{total_items} contas desde %{filename}. - bookmarks_html: Vas substituír os marcadores por %{total_items} publicacións desde %{filename}. - domain_blocking_html: Vas substituír a lista de dominios bloqueados por %{total_items} dominios desde %{filename}. - following_html: Vas seguir estas %{total_items} contas desde %{filename} e deixar de seguir a todas as outras contas. - lists_html: Vas substituír as túas listas co contido de %{filename}. Vanse engadir %{total_items} contas ás novas listas. - muting_html: Vas substituír a lista de contas acaladas por %{total_items} contas desde %{filename}. + blocking_html: + one: Vas substituír a lista de bloqueos por %{count} conta desde %{filename}. + other: Vas substituír a lista de bloqueos por %{count} contas desde %{filename}. + bookmarks_html: + one: Vas substituír os marcadores por %{count} publicación desde %{filename}. + other: Vas substituír os marcadores por %{count} publicacións desde %{filename}. + domain_blocking_html: + one: Vas substituír a lista de dominios bloqueados por %{count} dominio desde %{filename}. + other: Vas substituír a lista de dominios bloqueados por %{count} dominios desde %{filename}. + following_html: + one: Vas seguir a %{count} conta desde %{filename} e deixar de seguir a todas as outras contas. + other: Vas seguir a %{count} contas desde %{filename} e deixar de seguir a todas as outras contas. + lists_html: + one: Vas substituír as túas listas co contido de %{filename}. Vaise engadir %{count} conta ás novas listas. + other: Vas substituír as túas listas co contido de %{filename}. Vanse engadir %{count} contas ás novas listas. + muting_html: + one: Vas substituír a lista de contas acaladas por %{count} conta desde %{filename}. + other: Vas substituír a lista de contas acaladas por %{count} contas desde %{filename}. preambles: - blocking_html: Vas bloquear estas %{total_items} contas desde %{filename}. - bookmarks_html: Vas engadir %{total_items} publicacións desde %{filename} aos teus marcadores. - domain_blocking_html: Vas bloquear estes %{total_items} dominios desde %{filename}. - following_html: Vas seguir estas %{total_items} contas desde %{filename}. - lists_html: Vas engadir %{total_items} contas desde %{filename} ás túas listas. Crearánse novas listas se non hai listas ás que engadilas. - muting_html: Vas acalar estas %{total_items} contas desde %{filename}. + blocking_html: + one: Vas bloquear a %{count} conta desde %{filename}. + other: Vas bloquear a %{count} contas desde %{filename}. + bookmarks_html: + one: Vas engadir %{count} publicación desde %{filename} aos teus marcadores. + other: Vas engadir %{count} publicacións desde %{filename} aos teus marcadores. + domain_blocking_html: + one: Vas bloquear a %{count} dominio desde %{filename}. + other: Vas bloquear a %{count} dominios desde %{filename}. + following_html: + one: Vas seguir a %{count} conta desde %{filename}. + other: Vas seguir a %{count} contas desde %{filename}. + lists_html: + one: Vas engadir %{count} conta desde %{filename} ás túas listas. Crearánse novas listas se non hai listas ás que engadilas. + other: Vas engadir %{count} contas desde %{filename} ás túas listas. Crearánse novas listas se non hai listas ás que engadilas. + muting_html: + one: Vas acalar a %{count} conta desde %{filename}. + other: Vas acalar a %{count} contas desde %{filename}. preface: Podes importar os datos que exportaches doutro servidor, tales como a lista de usuarias que estás a seguir ou bloquear. recent_imports: Importacións recentes states: @@ -1692,7 +1722,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 @@ -1757,11 +1787,11 @@ gl: enabled: Borrar automáticamente publicacións antigas enabled_hint: Borra automáticamente as túas publicacións unha vez acadan certa lonxevidade, a menos que cumpran algunha destas excepcións exceptions: Excepcións - explanation: Como o borrado de publicacións consume moitos recursos, esta faise aos poucos cando o servidor non ten moita carga de traballo. Así, a eliminación das túas publicacións podería ser lixeiramente posterior a cando lle correspondería por idade. + explanation: O borrado de publicacións vaise facendo aos poucos cando o servidor non ten moito traballo, é unha tarefa que consume moitos recursos. Así, a eliminación das túas publicacións podería ser lixeiramente posterior a cando lle correspondería por antigüidade. ignore_favs: Ignorar favoritas ignore_reblogs: Ignorar promocións interaction_exceptions: Excepcións baseadas en interaccións - interaction_exceptions_explanation: Ten en conta que non hai garantía de que se eliminen as túas publicacións se baixan do límite de promocións e favorecementos se nalgún momento o superaron. + interaction_exceptions_explanation: Ten en conta que non hai garantía de que se eliminen as túas publicacións se baixan do límite de promocións ou favorecementos se nalgún momento o tivese superado. keep_direct: Manter mensaxes directas keep_direct_hint: Non borrar ningunha das túas mensaxes directas keep_media: Manter publicacións que conteñen multimedia diff --git a/config/locales/he.yml b/config/locales/he.yml index 13a1f6f05d30d3..10b4611b9ac5c8 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -25,6 +25,7 @@ he: other: הודעות two: הודעותיים posts_tab_heading: הודעות + self_follow_error: בלתי אפשרי לך לעקוב אחרי חשבונך admin: account_actions: action: בצע/י פעולה @@ -903,6 +904,9 @@ he: message_html: לא הוגדרו שום כללי שרת. sidekiq_process_check: message_html: שום הליכי Sidekiq לא רצים עבור %{value} תור(ות). בחנו בבקשה את הגדרות Sidekiq + software_version_check: + action: ראו עדכונים זמינים + message_html: עדכון מסטודון זמין כעת. software_version_critical_check: action: ראו עדכונים זמינים message_html: יצא עדכון קריטי למסטודון, נא לעדכן את תוכנת מסטודון בהקדם האפשרי. @@ -1198,9 +1202,11 @@ he: use_security_key: שימוש במפתח אבטחה author_attribution: example_title: טקסט לדוגמה - hint_html: בחירה איך תקבלו קרדיטציה כאשר קישורים משותפים דרך מסטודון. + hint_html: האם יש לך בלוג או טור חדשות שמתפרסם מחוץ למסטודון? ניתן לשלוט איך יוצג הקרדיט שלך כשמשתפים את הלינק במסטודון. + instructions: 'ודאו כי הקוד הזה נכלל בקוד ה־HTML של המאמרים שלכם:' more_from_html: עוד מאת %{name} s_blog: הבלוג של %{name} + then_instructions: לאחר מכן, הוסיפו את שם המתחם של האתר המפרסם בשדה למטה. title: ייחוס למפרסם challenge: confirm: המשך @@ -1413,19 +1419,67 @@ he: overwrite: דריסה overwrite_long: החלף רשומות נוכחיות בחדשות overwrite_preambles: - blocking_html: אתם עומדים להחליף את רשימת החסימות עד כדי %{total_items} חשבונות מהקובץ %{filename}. - bookmarks_html: אתם עומדים להחליף את רשימת הסימניות עד כדי %{total_items} הודעות מהקובץ %{filename}. - domain_blocking_html: אתם עומדים להחליף את רשימת חסימות השרתים עד כדי %{total_items} שרתים מהקובץ %{filename}. - following_html: אתם עומדים לעקוב עד כדי %{total_items} חשבונות מהקובץ %{filename} ובמקביל להפסיק מעקב אחרי כל משתמש אחר. - lists_html: הפעולה הבאה תחליף את רשימותיך בתוכן של %{filename}. עד %{total_items} חשבונות יתווספו לרשימות חדשות. - muting_html: אתם עומדים להחליף את רשימת ההשתקות עד כדי %{total_items} חשבונות מהקובץ %{filename}. + blocking_html: + many: אתם עומדים להחליף את רשימת החסימות עד כדי %{count} חשבונות מהקובץ %{filename}. + one: אתם עומדים להחליף את רשימת החסימות %{count} בחשבון אחד מהקובץ %{filename}. + other: אתם עומדים להחליף את רשימת החסימות עד כדי %{count} חשבונות מהקובץ %{filename}. + two: אתם עומדים להחליף את רשימת החסימות בעד שני חשבונות מהקובץ %{filename}. + bookmarks_html: + many: אתם עומדים להחליף את רשימת הסימניות עד כדי %{count} הודעות מהקובץ %{filename}. + one: אתם עומדים להחליף את רשימת הסימניות בהודעה אחת מהקובץ %{filename}. + other: אתם עומדים להחליף את רשימת הסימניות עד כדי %{count} הודעות מהקובץ %{filename}. + two: אתם עומדים להחליף את רשימת הסימניות עד כדי שתי הודעות מהקובץ %{filename}. + domain_blocking_html: + many: אתם עומדים להחליף את רשימת חסימות השרתים עד כדי %{count} שרתים מהקובץ %{filename}. + one: אתם עומדים להחליף את רשימת חסימות השרתים בשרת אחד מהקובץ %{filename}. + other: אתם עומדים להחליף את רשימת חסימות השרתים עד כדי %{count} שרתים מהקובץ %{filename}. + two: אתם עומדים להחליף את רשימת חסימות השרתים עד כדי שני שרתים מהקובץ %{filename}. + following_html: + many: אתם עומדים לעקוב אחרי עד כדי %{count} חשבונות מהקובץ %{filename} ובמקביל להפסיק מעקב אחרי כל משתמש אחר. + one: אתם עומדים לעקוב אחרי חשבון אחד מהקובץ %{filename} ובמקביל להפסיק מעקב אחרי כל משתמש אחר. + other: אתם עומדים לעקוב אחרי עד כדי %{count} חשבונות מהקובץ %{filename} ובמקביל להפסיק מעקב אחרי כל משתמש אחר. + two: אתם עומדים לעקוב אחרי עד כדי שני חשבונות מהקובץ %{filename} ובמקביל להפסיק מעקב אחרי כל משתמש אחר. + lists_html: + many: הפעולה הבאה תחליף את רשימותיך בתוכן של %{filename}. עד %{count} חשבונות יתווספו לרשימות חדשות. + one: הפעולה הבאה תחליף את רשימותיך בתוכן של %{filename}. עד חשבון אחד יתווסף לרשימות חדשות. + other: הפעולה הבאה תחליף את רשימותיך בתוכן של %{filename}. עד %{count} חשבונות יתווספו לרשימות חדשות. + two: הפעולה הבאה תחליף את רשימותיך בתוכן של %{filename}. עד שני חשבונות יתווספו לרשימות חדשות. + muting_html: + many: אתם עומדים להחליף את רשימת ההשתקות בעד כדי %{count} חשבונות מהקובץ %{filename}. + one: אתם עומדים להחליף את רשימת ההשתקות בחשבון אחד מהקובץ %{filename}. + other: אתם עומדים להחליף את רשימת ההשתקות בעד כדי %{count} חשבונות מהקובץ %{filename}. + two: אתם עומדים להחליף את רשימת ההשתקות בעד כדי שני חשבונות מהקובץ %{filename}. preambles: - blocking_html: אתם עומדים לחסום עד %{total_items} חשבונות מהקובץ %{filename}. - bookmarks_html: אתם עומדים להוסיף עד %{total_items} הודעות מהקובץ %{filename} לרשימת הסימניות שלכם. - domain_blocking_html: אתם עומדים לחסום עד כדי %{total_items} שרתים מהקובץ %{filename}. - following_html: אתם עומדים לעקוב אחרי עד %{total_items} חשבונות מהקובץ %{filename}. - lists_html: הפעולה הבאה תוסיף עד %{total_items} חשבונות מהקובץ %{filename} אל הרשימות שלך. רשימות חדשות יווצרו אם עוד לא קיימת רשימה להוסיף אליה. - muting_html: אתם עומדים להשתיק עד %{total_items} חשבונות מהקובץ %{filename}. + blocking_html: + many: אתם עומדים לחסום עד %{count} חשבונות מהקובץ %{filename}. + one: אתם עומדים לחסוםחשבון אחד מהקובץ %{filename}. + other: אתם עומדים לחסום עד %{count} חשבונות מהקובץ %{filename}. + two: אתם עומדים לחסום עד שני חשבונות מהקובץ %{filename}. + bookmarks_html: + many: אתם עומדים להוסיף עד %{count} הודעות מהקובץ %{filename} לרשימת הסימניות שלכם. + one: אתם עומדים להוסיףהודעה אחת מהקובץ %{filename} לרשימת הסימניות שלכם. + other: אתם עומדים להוסיף עד %{count} הודעות מהקובץ %{filename} לרשימת הסימניות שלכם. + two: אתם עומדים להוסיף עד שתי הודעות מהקובץ %{filename} לרשימת הסימניות שלכם. + domain_blocking_html: + many: אתם עומדים לחסום עד כדי %{count} שרתים מהקובץ %{filename}. + one: אתם עומדים לחסום עד שרת אחד מהקובץ %{filename}. + other: אתם עומדים לחסום עד כדי %{count} שרתים מהקובץ %{filename}. + two: אתם עומדים לחסום עד כדי שני שרתים מהקובץ %{filename}. + following_html: + many: אתם עומדים לעקוב אחרי עד %{count} חשבונות מהקובץ %{filename}. + one: אתם עומדים לעקוב אחרי עד חשבון אחד מהקובץ %{filename}. + other: אתם עומדים לעקוב אחרי עד %{count} חשבונות מהקובץ %{filename}. + two: אתם עומדים לעקוב אחרי עד שני חשבונות מהקובץ %{filename}. + lists_html: + many: הפעולה הבאה תוסיף עד %{count} חשבונות מהקובץ %{filename} אל הרשימות שלך. רשימות חדשות יווצרו אם עוד לא קיימת רשימה להוסיף אליה. + one: הפעולה הבאה תוסיף עד חשבון אחד מהקובץ %{filename} אל הרשימות שלך. רשימות חדשות יווצרו אם עוד לא קיימת רשימה להוסיף אליה. + other: הפעולה הבאה תוסיף עד %{count} חשבונות מהקובץ %{filename} אל הרשימות שלך. רשימות חדשות יווצרו אם עוד לא קיימת רשימה להוסיף אליה. + two: הפעולה הבאה תוסיף עד שני חשבונות מהקובץ %{filename} אל הרשימות שלך. רשימות חדשות יווצרו אם עוד לא קיימת רשימה להוסיף אליה. + muting_html: + many: אתם עומדים להשתיק עד %{count} חשבונות מהקובץ %{filename}. + one: אתם עומדים להשתיק עד חשבון אחד מהקובץ %{filename}. + other: אתם עומדים להשתיק עד %{count} חשבונות מהקובץ %{filename}. + two: אתם עומדים להשתיק עד שני חשבונות מהקובץ %{filename}. preface: ניתן ליבא מידע מסויים כגון כל הנעקבים או המשתמשים החסומים לתוך חשבונך על שרת זה, מתוך קבצים שנוצרו על ידי יצוא משרת אחר כגון רשימת הנעקבים והחסומים שלך. recent_imports: ייבואים אחרונים states: @@ -1744,7 +1798,7 @@ he: delete: מחיקת חשבון development: פיתוח edit_profile: עריכת פרופיל - export: יצוא מידע + 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..4f18e3b4d4861d 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -21,6 +21,7 @@ hu: one: Bejegyzés other: Bejegyzés posts_tab_heading: Bejegyzés + self_follow_error: A saját fiók nem követhető admin: account_actions: action: Művelet végrehajtása @@ -875,6 +876,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. @@ -1162,7 +1166,6 @@ hu: use_security_key: Biztonsági kulcs használata author_attribution: example_title: Mintaszöveg - hint_html: Szabályozd, hogyan hivatkoznak rád, amikor linket osztanak meg Mastodonon. more_from_html: 'Több tőle: %{name}' s_blog: "%{name} blogja" title: Szerző forrásmegjelölése @@ -1363,19 +1366,43 @@ hu: overwrite: Felülírás overwrite_long: Lecseréljük újakkal a jelenlegi bejegyzéseket overwrite_preambles: - blocking_html: 'Arra készülsz, hogy lecseréld a letiltási listát legfeljebb %{total_items} fiókra a következőből: %{filename}.' - bookmarks_html: 'Arra készülsz, hogy lecseréld a könyvjelzőket legfeljebb %{total_items} bejegyzésre a következőből: %{filename}.' - domain_blocking_html: 'Arra készülsz, hogy lecseréld a domain letiltási listát legfeljebb %{total_items} domainre a következőből: %{filename}.' - following_html: 'Arra készülsz, hogy legfeljebb %{total_items} fiókot kövess a következőből: %{filename}, és abbahagyd mindenki más követését.' - lists_html: Arra készülsz, hogy a listákat lecseréld a %{filename} tartalmával. Legfeljebb %{total_items} fiók kerül fel az új listákra. - muting_html: 'Arra készülsz, hogy lecseréld a némított fiókok listáját legfeljebb %{total_items} fiókra a következőből: %{filename}.' + blocking_html: + one: 'Arra készülsz, hogy lecseréld a letiltási listát legfeljebb %{count} fiókra a következőből: %{filename}.' + other: 'Arra készülsz, hogy lecseréld a letiltási listát legfeljebb %{count} fiókra a következőből: %{filename}.' + bookmarks_html: + one: 'Arra készülsz, hogy lecseréld a könyvjelzőket legfeljebb %{count} bejegyzésre a következőből: %{filename}.' + other: 'Arra készülsz, hogy lecseréld a könyvjelzőket legfeljebb %{count} bejegyzésre a következőből: %{filename}.' + domain_blocking_html: + one: 'Arra készülsz, hogy lecseréld a domain letiltási listát legfeljebb %{count} domainre a következőből: %{filename}.' + other: 'Arra készülsz, hogy lecseréld a domain letiltási listát legfeljebb %{count} domainre a következőből: %{filename}.' + following_html: + one: 'Arra készülsz, hogy legfeljebb %{count} fiókot kövess a következőből: %{filename}, és abbahagyd mindenki más követését.' + other: 'Arra készülsz, hogy legfeljebb %{count} fiókot kövess a következőből: %{filename}, és abbahagyd mindenki más követését.' + lists_html: + one: Arra készülsz, hogy a listákat lecseréld a %{filename} tartalmával. Legfeljebb %{count} fiók kerül fel az új listákra. + other: Arra készülsz, hogy a listákat lecseréld a %{filename} tartalmával. Legfeljebb %{count} fiók kerül fel az új listákra. + muting_html: + one: 'Arra készülsz, hogy lecseréld a némított fiókok listáját legfeljebb %{count} fiókra a következőből: %{filename}.' + other: 'Arra készülsz, hogy lecseréld a némított fiókok listáját legfeljebb %{count} fiókra a következőből: %{filename}.' preambles: - blocking_html: 'Arra készülsz, hogy legfeljebb %{total_items} fiókot letilts a következőből: %{filename}.' - bookmarks_html: 'Arra készülsz, hogy legfeljebb %{total_items} bejegyzést adj hozzá a könyvjelzőkhöz a következőből: %{filename}.' - domain_blocking_html: 'Arra készülsz, hogy legfeljebb %{total_items} domaint letilts a következőből: %{filename}.' - following_html: 'Arra készülsz, hogy legfeljebb %{total_items} fiókot kövess a következőből: %{filename}.' - lists_html: Arra készülsz, hogy legfeljebb %{total_items} fiókot hozzáadj a %{filename} fájlból a listákhoz. Új listák jönnek létre, ha nincs hozzáadható lista. - muting_html: 'Arra készülsz, hogy legfeljebb %{total_items} fiókot némíts a következőből: %{filename}.' + blocking_html: + one: 'Arra készülsz, hogy legfeljebb %{count} fiókot letilts a következőből: %{filename}.' + other: 'Arra készülsz, hogy legfeljebb %{count} fiókot letilts a következőből: %{filename}.' + bookmarks_html: + one: 'Arra készülsz, hogy legfeljebb %{count} bejegyzést adj hozzá a könyvjelzőkhöz a következőből: %{filename}.' + other: 'Arra készülsz, hogy legfeljebb %{count} bejegyzést adj hozzá a könyvjelzőkhöz a következőből: %{filename}.' + domain_blocking_html: + one: 'Arra készülsz, hogy legfeljebb %{count} domaint letilts a következőből: %{filename}.' + other: 'Arra készülsz, hogy legfeljebb %{count} domaint letilts a következőből: %{filename}.' + following_html: + one: 'Arra készülsz, hogy legfeljebb %{count} fiókot kövess a következőből: %{filename}.' + other: 'Arra készülsz, hogy legfeljebb %{count} fiókot kövess a következőből: %{filename}.' + lists_html: + one: Arra készülsz, hogy legfeljebb %{count} fiókot hozzáadj a %{filename} fájlból a listákhoz. Új listák jönnek létre, ha nincs hozzáadható lista. + other: Arra készülsz, hogy legfeljebb %{count} fiókot hozzáadj a %{filename} fájlból a listákhoz. Új listák jönnek létre, ha nincs hozzáadható lista. + muting_html: + one: 'Arra készülsz, hogy legfeljebb %{count} fiókot némíts a következőből: %{filename}.' + other: 'Arra készülsz, hogy legfeljebb %{count} fiókot némíts a következőből: %{filename}.' preface: Itt importálhatod egy másik kiszolgálóról lementett adataidat, például követettjeid és letiltott felhasználóid listáját. recent_imports: Legutóbbi importálások states: @@ -1692,7 +1719,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..843e8724b9efcd 100644 --- a/config/locales/ia.yml +++ b/config/locales/ia.yml @@ -21,6 +21,7 @@ ia: one: Message other: Messages posts_tab_heading: Messages + self_follow_error: Sequer tu proprie conto non es permittite admin: account_actions: action: Exequer action @@ -473,6 +474,9 @@ ia: title: Recommendationes de contos a sequer unsuppress: Restaurar recommendation de sequimento instances: + audit_log: + title: Registros de controlo recente + view_all: Vider registros de controlo integre availability: description_html: one: Si le livration al dominio falle %{count} die sin succeder, necun tentativa ulterior de livration essera facite, excepte si es recipite un livration ab le dominio. @@ -599,7 +603,9 @@ ia: resolve_description_html: Necun mesura essera prendite contra le conto denunciate, necun sanction registrate, e le reporto essera claudite. silence_description_html: Iste conto essera visibile solmente a qui ja lo seque o manualmente lo cerca, limitante gravemente su portata. Pote sempre esser revertite. Claude tote le reportos contra iste conto. suspend_description_html: Le conto e tote su contento essera inaccessibile e finalmente delite, e interager con illo essera impossibile. Reversibile intra 30 dies. Claude tote le reportos contra iste conto. + actions_description_html: Decider que mesuras prender pro resolver iste reporto. Si tu prende un mesura punitive contra le conto reportate, un aviso email les sera inviate, salvo quando le categoria Spam es seligite. actions_description_remote_html: Decide qual mesura prender pro resolver iste reporto. Isto affectara solmente le maniera in que tu servitor communica con iste conto remote e gere su contento. + actions_no_posts: Iste reporto non ha alcun message associate a deler add_to_report: Adder plus al reporto already_suspended_badges: local: Ja suspendite sur iste servitor @@ -870,6 +876,9 @@ ia: message_html: Tu non ha definite alcun regula de servitor. sidekiq_process_check: message_html: Necun processo Sidekiq es active pro le cauda(s) %{value}. Per favor verifica tu configuration de Sidekiq + software_version_check: + action: Vider le actualisationes disponibile + message_html: Un actualisation de Mastodon es disponibile. software_version_critical_check: action: Vider le actualisationes disponibile message_html: Un actualisation critic de Mastodon es disponibile. Per favor actualisa lo le plus tosto possibile. @@ -885,11 +894,18 @@ ia: tags: moderation: not_trendable: Non pro tendentia + not_usable: Non usabile pending_review: Attende revision + review_requested: Revision demandate + reviewed: Revidite title: Stato + trendable: De tendentia + unreviewed: Non revidite + usable: Usabile name: Nomine newest: Le plus nove oldest: Le plus ancian + open: Vider publicamente reset: Reinitialisar review: Revide le stato search: Cercar @@ -932,7 +948,9 @@ ia: statuses: allow: Permitter message allow_account: Permitter autor + confirm_allow: Desira tu vermente permitter le statos seligite? confirm_allow_account: Es tu secur que tu vole permitter le contos seligite? + confirm_disallow: Desira tu vermente impedir le statos seligite? confirm_disallow_account: Es tu secur que tu vole cessar de permitter le contos seligite? description_html: Istes es le messages cognoscite sur tu servitor que al momento es multo compartite e marcate como favorite. Illos pote adjutar tu usatores nove e reveniente a trovar plus personas a sequer. Necun message es monstrate publicamente usque tu approba le autor, a condition que le autor permitte que su conto es suggerite a alteres. Tu pote tamben permitter o rejectar messages singule. disallow: Non permitter message @@ -1150,6 +1168,7 @@ ia: example_title: Texto de exemplo more_from_html: Plus de %{name} s_blog: Blog de %{name} + title: Attribution de autor challenge: confirm: Continuar hint_html: "Consilio: Nos non te demandara tu contrasigno de novo in le proxime hora." @@ -1347,19 +1366,43 @@ ia: overwrite: Superscriber overwrite_long: Reimplaciar registros actual con le noves overwrite_preambles: - blocking_html: Tu es sur le puncto de reimplaciar tu lista de blocadas per usque a %{total_items} contos proveniente de %{filename}. - bookmarks_html: Tu es sur le puncto de reimplaciar tu marcapaginas per usque a %{total_items} messages desde %{filename}. - domain_blocking_html: Tu es sur le puncto de reimplaciar tu lista de blocadas de dominio per usque a %{total_items} dominios proveniente de %{filename}. - following_html: Tu es sur le puncto de sequer usque a %{total_items} contos de %{filename} e cessar de sequer tote le alteres. - lists_html: Tu es sur le puncto de reimplaciar tu listas per le contento de %{filename}. Usque a %{total_items} contos essera addite a nove listas. - muting_html: Tu es sur le puncto de reimplaciar tu lista de contos silentiate con usque a %{total_items} contos desde %{filename}. + blocking_html: + one: Tu va reimplaciar tu lista de blocada con usque %{count} conto ab %{filename}. + other: Tu va reimplaciar tu lista de blocada con usque %{count} contos ab %{filename}. + bookmarks_html: + one: Tu va reimplaciar tu marcapaginas con usque %{count} message ab %{filename}. + other: Tu va reimplaciar tu marcapaginas con usque %{count} messages ab %{filename}. + domain_blocking_html: + one: Tu va reimplaciar tu blocada lista de dominios blocate con usque %{count} dominio ab %{filename}. + other: Tu va reimplaciar tu lista de dominios blocate con usque %{count} dominios ab %{filename}. + following_html: + one: Tu va sequer usque %{count} conto ab %{filename} e cessar de sequer ulle altere. + other: Tu va sequer usque %{count} contos ab %{filename} e cessar de sequer ulle altere. + lists_html: + one: Tu va reimplaciar tu listas con contentos ab %{filename}. Usque %{count} conto sera addite al nove listas. + other: Tu va reimplaciar tu listas con contentos ab %{filename}. Usque %{count} contos sera addite a nove listas. + muting_html: + one: Tu va reimplaciar tu lista de conto silentiate con usque %{count} conto ab %{filename}. + other: Tu va reimplaciar tu lista de contos silentiate con usque %{count} contos ab %{filename}. preambles: - blocking_html: Tu es sur le puncto de blocar usque a %{total_items} contos a partir de %{filename}. - bookmarks_html: Tu es sur le puncto de adder usque a %{total_items} messages desde %{filename} a tu marcapaginas. - domain_blocking_html: Tu es sur le puncto de blocar usque a %{total_items} dominios a partir de %{filename}. - following_html: Tu es sur le puncto de sequer usque a %{total_items} contos desde %{filename}. - lists_html: Tu es sur le puncto de adder usque %{total_items} contos desde %{filename} a tu listas. Nove listas essera create si il non ha un lista al qual adder los. - muting_html: Tu es sur le puncto de silentiar usque a %{total_items} contos desde %{filename}. + blocking_html: + one: Tu va blocar usque %{count} conto ab %{filename}. + other: Tu va blocar usque %{count} contos de %{filename}. + bookmarks_html: + one: Tu va adder usque %{count} message ab %{filename} a tu marcapaginas. + other: Tu va adder usque %{count} messages ab %{filename} a tu marcapaginas. + domain_blocking_html: + one: Tu va blocar usque %{count} dominio ab %{filename}. + other: Tu va blocar usque %{count} dominios ab %{filename}. + following_html: + one: Tu va sequer usque %{count} conto ab %{filename}. + other: Tu va sequer usque %{count} contos de %{filename}. + lists_html: + one: Tu va adder usque %{count} conto ab %{filename} a tu lista. Nove listas sera create si il non ha lista a adder. + other: Tu va adder usque %{count} contos ab %{filename} a tu lista. Nove listas sera create si il non ha lista a adder. + muting_html: + one: Tu va silentiar usque %{count} conto ab %{filename}. + other: Tu va silentiar usque %{count} contos ab %{filename}. preface: Tu pote importar datos que tu ha exportate de un altere servitor, como un lista de personas que tu seque o bloca. recent_imports: Importationes recente states: @@ -1444,6 +1487,7 @@ ia: media_attachments: validations: images_and_video: Impossibile annexar un video a un message que jam contine imagines + not_found: Medios %{ids} non trovate o jam attachate a un altere message not_ready: Impossibile annexar files que non ha ancora essite processate. Retenta post un momento! too_many: Impossibile annexar plus de 4 files migrations: @@ -1675,7 +1719,7 @@ ia: delete: Deletion de conto development: Disveloppamento edit_profile: Modificar profilo - export: Exportation de datos + export: Exportar 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..94c4b7f4f0a940 100644 --- a/config/locales/ie.yml +++ b/config/locales/ie.yml @@ -1274,20 +1274,6 @@ ie: merge_long: Conservar existent registres e adjunter li novis overwrite: Remplazzar overwrite_long: Remplazzar existent registres per li novis - overwrite_preambles: - blocking_html: Tu va remplazzar tui liste de bloccat contos per til %{total_items} contos de %{filename}. - bookmarks_html: Tu va remplazzar tui marcatores per til %{total_items} postas de %{filename}. - domain_blocking_html: Tu va remplazzar tui liste de bloccat dominias per til %{total_items} dominias de %{filename}. - following_html: Tu va sequer til %{total_items} contos de %{filename} e dessequer omni altri contos. - lists_html: Tu va remplazzar tui listes per li contenete de %{filename}. Til %{total_items} contos va esser adjuntet a nov listes. - muting_html: Tu va remplazzar tui liste de silentiat contos per til %{total_items} contos de %{filename}. - preambles: - blocking_html: Tu va bloccar til %{total_items} contos de %{filename}. - bookmarks_html: Tu va adjunter til %{total_items} postas de %{filename} a tui marcatores. - domain_blocking_html: Tu va bloccar til %{total_items} dominias de %{filename}. - following_html: Tu va sequer til %{total_items} contos de %{filename}. - lists_html: Tu va adjunter til %{total_items} contos de %{filename} a tui listes. Nov listes va esser creat si ne hay un liste a quel adjunter. - muting_html: Tu va silentiar til %{total_items} contos de %{filename}. preface: Tu posse importar data quel tu ha exportat de un altri servitor, quam un liste del gente quem tu seque o blocca. recent_imports: Recent importationes states: @@ -1590,7 +1576,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..8ce5f3403bd6d3 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -1247,20 +1247,6 @@ io: merge_long: Retenez displonebla rekordi e insertez novi overwrite: Remplasez overwrite_long: Remplasez nuna rekordi per novi - overwrite_preambles: - blocking_html: Vu substitucos vua blokusolisto per til %{total_items} konti de %{filename}. - bookmarks_html: Vu substitucos vua libromarki per til %{total_items} posti de %{filename}. - domain_blocking_html: Vu substitucos vua domenoblokusolisto per til %{total_items} domeni de %{filename}. - following_html: Vu sequos til %{total_items} konti de %{filename} e haltar sequar irga altra konto. - lists_html: Vu substitucos vua listi kun la kontenaji di %{filename}. Til %{total_items} konti adjuntesos a nova listi. - muting_html: Vu substitucos vua listo di konti silencigita per til %{total_items} konti de %{filename}. - preambles: - blocking_html: Vu blokusos til %{total_items} konti de %{filename}. - bookmarks_html: Vu adjuntos %{total_items} posti de %{filename} a vua libromarki. - domain_blocking_html: Vu blokusos til %{total_items} domeni de %{filename}. - following_html: Vu sequos til %{total_items} konti de %{filename}. - lists_html: Vu adjuntos til %{total_items} konti de %{filename} a vua listi. Nova listi kreesos se ne existas listo a quo adjuntar. - muting_html: Vu silencigos til %{total_items} konti en %{filename}. preface: Tu povas importacar kelka datumi, tal quala listi de omna homi quin tu sequas o blokusas, a tua konto di ca instaluro, per dosiero exportacita de altra instaluro. recent_imports: Importacaji recenta states: @@ -1555,7 +1541,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..c50b3dd20dda02 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -21,6 +21,7 @@ is: one: Færsla other: Færslur posts_tab_heading: Færslur + self_follow_error: Ekki er leyft að fylgjast með eigin aðgangi admin: account_actions: action: Framkvæma aðgerð @@ -877,6 +878,9 @@ is: message_html: Þú hefur ekki skilgreint neinar reglur fyrir netþjón. sidekiq_process_check: message_html: Ekkert Sidekiq-ferli er í gangi fyrir %{value} biðröð/biðraðir. Endilega athugaðu Sidekiq-uppsetninguna þína + software_version_check: + action: Skoða tiltækar uppfærslur + message_html: Uppfærsla er tiltæk fyrir Mastodon. software_version_critical_check: action: Skoða tiltækar uppfærslur message_html: Áríðandi uppfærsla Mastodon er tiltæk, uppfærðu eins fljótt og auðið er. @@ -1166,9 +1170,11 @@ is: use_security_key: Nota öryggislykil author_attribution: example_title: Sýnitexti - hint_html: Stýrðu hvernig framlög þín birtast þegar tenglum er deilt á Mastodon. + hint_html: Ertu að skrifa fréttir eða bloggfærslur utan Mastodon? Stýrðu því hvernig vitnað er í þig þegar þeim er deilt á Mastodon. + instructions: 'Gakktu úr skugga um að þessi kóði sé í HTML greinarinnar þinnar:' more_from_html: Meira frá %{name} s_blog: Bloggsvæði hjá %{name} + then_instructions: Síðan skaltu bæta lénsheiti útgefandans í reitinn hér fyrir neðan. title: Framlag höfundar challenge: confirm: Halda áfram @@ -1367,19 +1373,43 @@ is: overwrite: Skrifa yfir overwrite_long: Skipta út fyrirliggjandi færslum með þeim nýju overwrite_preambles: - blocking_html: Þú er í þann mund að fara að skipta út útilokanalistanum þínum með allt að %{total_items} aðgöngum úr %{filename}. - bookmarks_html: Þú er í þann mund að fara að skipta út bókamerkjunum þínum með allt að %{total_items} færslum úr %{filename}. - domain_blocking_html: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokuð lén með allt að %{total_items} lénum úr %{filename}. - following_html: Þú er í þann mund að fara að fylgjast með allt að %{total_items} aðgöngum úr %{filename} og hætta að fylgjast með öllum öðrum. - lists_html: Þú ert í þann mund að fara að skipta út listunum þínum með efninu úr %{filename}. Allt að %{total_items} aðgöngum verður bætt við nýju listana. - muting_html: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokaða aðganga með allt að %{total_items} aðgöngum úr %{filename}. + blocking_html: + one: Þú er í þann mund að fara að skipta út útilokanalistanum þínum með allt að %{count} aðgangi úr %{filename}. + other: Þú er í þann mund að fara að skipta út útilokanalistanum þínum með allt að %{count} aðgöngum úr %{filename}. + bookmarks_html: + one: Þú er í þann mund að fara að skipta út bókamerkjunum þínum með allt að %{count} færslu úr %{filename}. + other: Þú er í þann mund að fara að skipta út bókamerkjunum þínum með allt að %{count} færslum úr %{filename}. + domain_blocking_html: + one: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokuð lén með allt að %{count} léni úr %{filename}. + other: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokuð lén með allt að %{count} lénum úr %{filename}. + following_html: + one: Þú er í þann mund að fara að fylgjast með allt að %{count} aðgangi úr %{filename} og hætta að fylgjast með öllum öðrum. + other: Þú er í þann mund að fara að fylgjast með allt að %{count} aðgöngum úr %{filename} og hætta að fylgjast með öllum öðrum. + lists_html: + one: Þú ert í þann mund að fara að skipta út listunum þínum með efninu úr %{filename}. Allt að %{count} aðgangi verður bætt við nýju listana. + other: Þú ert í þann mund að fara að skipta út listunum þínum með efninu úr %{filename}. Allt að %{count} aðgöngum verður bætt við nýju listana. + muting_html: + one: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokaða aðganga með allt að %{count} aðgangi úr %{filename}. + other: Þú er í þann mund að fara að skipta út listanum þínum yfir útilokaða aðganga með allt að %{count} aðgöngum úr %{filename}. preambles: - blocking_html: Þú er í þann mund að fara að útiloka allt að %{total_items} aðganga úr %{filename}. - bookmarks_html: Þú er í þann mund að fara að bæta við allt að %{total_items} færslum úr %{filename} við bókamerkin þín. - domain_blocking_html: Þú er í þann mund að fara að útiloka allt að %{total_items} lén úr %{filename}. - following_html: Þú er í þann mund að fara að fylgjast með allt að %{total_items} aðgöngum úr %{filename}. - lists_html: Þú ert í þann mund að fara að bæta við allt að %{total_items} aðgöngum úr %{filename} við listana þína. Nýir listar verða útbúnir ef ekki finnst neinn listi til að bæta í. - muting_html: Þú er í þann mund að fara að þagga allt að %{total_items} aðganga úr %{filename}. + blocking_html: + one: Þú ert í þann mund að útiloka allt að %{count} aðgang úr %{filename}. + other: Þú ert í þann mund að útiloka allt að %{count} aðganga úr %{filename}. + bookmarks_html: + one: Þú er í þann mund að fara að bæta við allt að %{count} færslu úr %{filename} við bókamerkin þín. + other: Þú er í þann mund að fara að bæta við allt að %{count} færslum úr %{filename} við bókamerkin þín. + domain_blocking_html: + one: Þú ert í þann mund að útiloka allt að %{count} lén úr %{filename}. + other: Þú er í þann mund að fara að útiloka allt að %{count} lén úr %{filename}. + following_html: + one: Þú ert að fara að fylgjast með allt að %{count} aðgangi úr %{filename}. + other: Þú er að fara að fylgjast með allt að %{count} aðgöngum úr %{filename}. + lists_html: + one: Þú ert í þann mund að fara að bæta við allt að %{count} aðgangi úr %{filename} við listana þína. Nýir listar verða útbúnir ef ekki finnst neinn listi til að bæta í. + other: Þú ert í þann mund að fara að bæta við allt að %{count} aðgöngum úr %{filename} við listana þína. Nýir listar verða útbúnir ef ekki finnst neinn listi til að bæta í. + muting_html: + one: Þú ert að fara að þagga niður í allt að %{count} aðgangi úr %{filename}. + other: Þú ert að fara að þagga niður í allt að %{count} aðgöngum úr %{filename}. preface: Þú getur flutt inn gögn sem þú hefur flutt út frá öðrum vefþjóni, svo sem lista yfir fólk sem þú fylgist með eða útilokar. recent_imports: Nýlega flutt inn states: @@ -1696,7 +1726,7 @@ is: delete: Eyðing notandaaðgangs development: Þróun edit_profile: Breyta notandasniði - export: Útflutningur gagna + export: Flytja út 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..e18cb0e8f68988 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -1,7 +1,7 @@ --- it: about: - about_mastodon_html: 'Il social network del futuro: Nessuna pubblicità, zero sorveglianza azienale, design etico e decentralizzazione! Sii il proprietario dei tuoi dati, con Mastodon!' + about_mastodon_html: 'Il social network del futuro: Nessuna pubblicità, zero sorveglianza aziendale, design etico e decentralizzazione! Sii il proprietario dei tuoi dati, con Mastodonte!' contact_missing: Non impostato contact_unavailable: N/D hosted_on: Mastodon ospitato su %{domain} @@ -21,6 +21,7 @@ it: one: Toot other: Toot posts_tab_heading: Toot + self_follow_error: Seguire il tuo stesso profilo non è consentito admin: account_actions: action: Esegui azione @@ -875,6 +876,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. @@ -1164,9 +1168,11 @@ it: use_security_key: Usa la chiave di sicurezza author_attribution: example_title: Testo di esempio - hint_html: Controlla come sei viene accreditato quando i link sono condivisi su Mastodon. + hint_html: Stai scrivendo notizie o articoli di blog al di fuori di Mastodon? Controlla come vieni accreditato quando vengono condivisi su Mastodon. + instructions: 'Assicurati che questo codice sia presente nell''HTML del tuo articolo:' more_from_html: Altro da %{name} s_blog: Blog di %{name} + then_instructions: Quindi, aggiungi il nome di dominio della pubblicazione nel campo sottostante. title: Attribuzione autore challenge: confirm: Continua @@ -1365,19 +1371,43 @@ it: overwrite: Sovrascrivi overwrite_long: Sostituisci record attuali con quelli nuovi overwrite_preambles: - blocking_html: Stai per sostituire la tua lista di blocchi con un massimo di %{total_items} account da %{filename}. - bookmarks_html: Stai per sostituire i tuoi segnalibri con un massimo di %{total_items} post da %{filename}. - domain_blocking_html: Stai per sostituire la tua lista di domini bloccati con un massimo di %{total_items} domini da %{filename}. - following_html: Stai per seguire fino a %{total_items} account da %{filename} e smettere di seguire chiunque altro. - lists_html: Stai per sostituire le tue liste con i contenuti di %{filename}. Fino a %{total_items} profili verranno aggiunti a nuove liste. - muting_html: Stai per sostituire la tua lista di account silenziati con un massimo di %{total_items} account da %{filename}. + blocking_html: + one: Stai per sostituire la tua lista di blocchi con %{count} account da %{filename}. + other: Stai per sostituire la tua lista di blocchi con %{count} account da %{filename}. + bookmarks_html: + one: Stai per sostituire i tuoi segnalibri con %{count} post da %{filename}. + other: Stai per sostituire i tuoi segnalibri con %{count} post da %{filename}. + domain_blocking_html: + one: Stai per sostituire la tua lista di domini bloccati con %{count} dominio da %{filename}. + other: Stai per sostituire la tua lista di domini bloccati con %{count} domini da %{filename}. + following_html: + one: Stai per seguire %{count} account da %{filename} e smettere di seguire chiunque altro. + other: Stai per seguire %{count} account da %{filename} e smettere di seguire chiunque altro. + lists_html: + one: Stai per sostituire le tue liste con il contenuto di %{filename}. Verrà aggiunto %{count} account alle nuove liste. + other: Stai per sostituire le tue liste con il contenuto di %{filename}. Verranno aggiunti %{count} account alle nuove liste. + muting_html: + one: Stai per sostituire la lista degli account silenziati con %{count} account da %{filename}. + other: Stai per sostituire la lista degli account silenziati con %{count} account da %{filename}. preambles: - blocking_html: Stai per bloccare fino a %{total_items} account da %{filename}. - bookmarks_html: Stai per aggiungere fino a %{total_items} post da %{filename} ai tuoi segnalibri. - domain_blocking_html: Stai per bloccare fino a %{total_items} domini da %{filename}. - following_html: Stai per seguire fino a %{total_items} account da %{filename}. - lists_html: Stai per aggiungere fino a %{total_items} profili da %{filename} alla tue liste. Le nuove liste saranno create se non c'è una lista a cui aggiungere. - muting_html: Stai per silenziare fino a %{total_items} account da %{filename}. + blocking_html: + one: Stai per bloccare %{count} account da %{filename}. + other: Stai per bloccare %{count} account da %{filename}. + bookmarks_html: + one: Stai per aggiungere %{count} post da %{filename} ai tuoi segnalibri. + other: Stai per aggiungere %{count} post da %{filename} ai tuoi segnalibri. + domain_blocking_html: + one: Stai per bloccare %{count} dominio da %{filename}. + other: Stai per bloccare %{count} domini da %{filename}. + following_html: + one: Stai per seguire %{count} account da %{filename}. + other: Stai per seguire %{count} account da %{filename}. + lists_html: + one: Stai per aggiungere %{count} account da %{filename} alle tue liste. Saranno create nuove liste, se non ce ne sono altre da aggiungere. + other: Stai per aggiungere %{count} account da %{filename} alle tue liste. Saranno create nuove liste, se non ce ne sono altre da aggiungere. + muting_html: + one: Stai per silenziare %{count} account da %{filename}. + other: Stai per silenziare %{count} account da %{filename}. preface: Puoi importare alcune informazioni, come le persone che segui o hai bloccato su questo server, da file creati da un'esportazione su un altro server. recent_imports: Importazioni recenti states: @@ -1694,7 +1724,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..66791a622d2fae 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -19,9 +19,12 @@ ja: posts: other: 投稿 posts_tab_heading: 投稿 + self_follow_error: 自分のアカウントをフォローすることはできません admin: account_actions: action: アクションを実行 + already_silenced: すでに制限されているアカウントです。 + already_suspended: すでに停止されているアカウントです。 title: "%{acct}さんに対してアクションを実行" account_moderation_notes: create: 書き込む @@ -43,6 +46,7 @@ ja: title: "%{username}さんのメールアドレスを変更" change_role: changed_msg: ロールを変更しました! + edit_roles: ユーザーのロールを管理 label: ロールを変更 no_role: ロールがありません title: "%{username}さんのロールを変更" @@ -229,22 +233,22 @@ ja: approve_appeal_html: "%{name}さんが%{target}さんからの抗議を承認しました" approve_user_html: "%{name}さんが%{target}さんからの登録を承認しました" assigned_to_self_report_html: "%{name}さんが通報 %{target}を自身の担当に割り当てました" - change_email_user_html: "%{name}さんが%{target}さんのメールアドレスを変更しました" + change_email_user_html: "%{name} さんが %{target} さんのメールアドレスを変更しました" change_role_user_html: "%{name}さんが%{target}さんのロールを変更しました" - confirm_user_html: "%{name}さんが%{target}さんのメールアドレスを確認済みにしました" + confirm_user_html: "%{name} さんが %{target} さんのメールアドレスを確認済みにしました" create_account_warning_html: "%{name}さんが%{target}さんに警告メールを送信しました" create_announcement_html: "%{name}さんが新しいお知らせ %{target}を作成しました" - create_canonical_email_block_html: "%{name}さんがメールアドレス (ハッシュ値: %{target}) をブロックしました" + create_canonical_email_block_html: "%{name} さんがメールアドレスのハッシュ値 %{target} をブロックしました" create_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を追加しました" create_domain_allow_html: "%{name}さんが%{target}の連合を許可しました" create_domain_block_html: "%{name}さんがドメイン %{target}をブロックしました" - create_email_domain_block_html: "%{name}さんがメールドメイン %{target} をブロックしました" + create_email_domain_block_html: "%{name} さんがメールドメイン %{target} をブロックしました" create_ip_block_html: "%{name}さんがIP %{target}のルールを作成しました" create_unavailable_domain_html: "%{name}がドメイン %{target}への配送を停止しました" create_user_role_html: "%{name}さんがロール『%{target}』を作成しました" demote_user_html: "%{name}さんが%{target}さんを降格しました" destroy_announcement_html: "%{name}さんがお知らせ %{target}を削除しました" - destroy_canonical_email_block_html: "%{name}さんがメールアドレス (ハッシュ値: %{target}) のブロックを外しました" + destroy_canonical_email_block_html: "%{name} さんがメールアドレスのハッシュ値 %{target} のブロックを外しました" destroy_custom_emoji_html: "%{name}さんがカスタム絵文字『%{target}』を削除しました" destroy_domain_allow_html: "%{name}さんが%{target}の連合許可を外しました" destroy_domain_block_html: "%{name}さんがドメイン %{target}のブロックを外しました" @@ -267,7 +271,7 @@ ja: reject_user_html: "%{name}さんが%{target}さんからの登録を拒否しました" remove_avatar_user_html: "%{name}さんが%{target}さんのアイコンを削除しました" reopen_report_html: "%{name}さんが通報 %{target}を未解決に戻しました" - resend_user_html: "%{name}さんが %{target} の確認メールを再送信しました" + resend_user_html: "%{name} さんが %{target} の確認メールを再送信しました" reset_password_user_html: "%{name}さんが%{target}さんのパスワードをリセットしました" resolve_report_html: "%{name}さんが通報 %{target}を解決済みにしました" sensitive_account_html: "%{name}さんが%{target}さんのメディアを閲覧注意にマークしました" @@ -282,7 +286,7 @@ ja: update_custom_emoji_html: "%{name}さんがカスタム絵文字 %{target}を更新しました" update_domain_block_html: "%{name}さんが%{target}のドメインブロックを更新しました" update_ip_block_html: "%{name} さんがIP %{target} のルールを更新しました" - update_report_html: "%{name}さんが通報 %{target} を更新しました" + update_report_html: "%{name} さんが通報 %{target} を更新しました" update_status_html: "%{name}さんが%{target}さんの投稿を更新しました" update_user_role_html: "%{name}さんがロール『%{target}』を変更しました" deleted_account: 削除されたアカウント @@ -589,6 +593,7 @@ ja: suspend_description_html: アカウントとそのすべての内容にアクセスできなくなり、最終的に削除され、やり取りは不可能になります。 30日以内であれば元に戻すことができます。このアカウントに対するすべての通報をクローズします。 actions_description_html: このレポートへのアクションを決定してください。アカウントへ懲罰的な措置を取った場合、Spanカテゴリが選択されている場合を除き、メール通知が送信されます。 actions_description_remote_html: この通報を解決するためのアクションを選択してください。これはあなたのサーバーがこのリモートアカウントと通信し、そのコンテンツを処理する時のみ影響します。 + actions_no_posts: 削除対象となる投稿がレポートに含まれていません add_to_report: 通報にさらに追加 already_suspended_badges: local: このサーバーで停止済み @@ -857,6 +862,9 @@ ja: 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アップデートがあります。速やかに適用してください。 @@ -1138,6 +1146,11 @@ ja: view_strikes: 過去のストライクを表示 too_fast: フォームの送信が速すぎます。もう一度やり直してください。 use_security_key: セキュリティキーを使用 + author_attribution: + example_title: サンプルテキスト + more_from_html: "%{name} のその他の情報" + s_blog: "%{name} のブログ" + title: 著者の帰属 challenge: confirm: 続ける hint_html: 以後1時間はパスワードの再入力を求めません @@ -1328,19 +1341,31 @@ ja: overwrite: 上書き overwrite_long: 現在のレコードを新しいもので置き換えます overwrite_preambles: - blocking_html: "%{filename}%{total_items}個のアカウントブロックしたアカウントリストを置き換えます。" - bookmarks_html: "%{filename}%{total_items}件の投稿ブックマークの一覧を置き換えます。" - domain_blocking_html: "%{filename}%{total_items}個のドメイン非表示にしたドメインリストを置き換えます。" - following_html: "%{filename}%{total_items}個のアカウントフォローします。また、この中に含まれていないアカウントのフォローを解除します。" - lists_html: "作成済みのリスト%{filename}の内容で置き換えます%{total_items}個のアカウントが新しいリストに追加されます。" - muting_html: "%{filename}%{total_items}個のアカウントミュートしたアカウントリストを置き換えます。" + blocking_html: + other: あなたは%{filename}から最大%{count}のアカウントブロックリストを置き換えようとしています。 + bookmarks_html: + other: あなたは%{filename}から最大%{count}の投稿ブックマークを置き換えようとしています。 + domain_blocking_html: + other: あなたは%{filename}から最大%{count}のドメインドメインブロックリストを置き換えようとしています。 + following_html: + other: あなたは%{filename}から最大%{count}のアカウントフォローし他のすべてのユーザーのフォローを解除します。 + lists_html: + other: あなたは%{filename}の内容でリストを置き換えようとしています。最大%{count}のアカウントが新しいリストに追加されます。 + muting_html: + other: あなたは%{filename}から最大%{count}のアカウントミュートアカウントのリストを置き換えようとしています。 preambles: - blocking_html: "%{filename}%{total_items}個のアカウントブロックします。" - bookmarks_html: "%{filename}%{total_items}件の投稿ブックマークに追加します。" - domain_blocking_html: "%{filename}%{total_items}個のドメイン非表示にします。" - following_html: "%{filename}%{total_items}個のアカウントフォローします。" - lists_html: "%{filename}%{total_items}個のアカウントリストに追加します。追加先のリストがない場合は新しく作成されます。" - muting_html: "%{filename}%{total_items}個のアカウントミュートします。" + blocking_html: + other: あなたは%{filename}から最大%{count}のアカウントブロックしようとしています。 + bookmarks_html: + other: あなたは%{filename}から最大%{count}の投稿ブックマークに追加しようとしています。 + domain_blocking_html: + other: あなたは%{filename}から最大%{count}のドメインブロックしようとしています。 + following_html: + other: あなたは%{filename}から最大%{count}のアカウントフォローしようとしています。 + lists_html: + other: あなたは%{filename}から最大%{count}のアカウントリストに追加しようとしています。追加するリストがない場合は新しいリストが作成されます。 + muting_html: + other: あなたは%{filename}から最大%{count}のアカウントミュートしようとしています。 preface: 他のサーバーでエクスポートされたファイルから、フォロー/ブロックした情報をこのサーバー上のアカウントにインポートできます。 recent_imports: 最近のインポート states: @@ -1656,7 +1681,7 @@ ja: delete: アカウントの削除 development: 開発 edit_profile: プロフィールを編集 - export: データのエクスポート + export: エクスポート featured_tags: 注目のハッシュタグ import: データのインポート import_and_export: インポート・エクスポート @@ -1901,6 +1926,7 @@ ja: instructions_html: 以下のコードをコピーしてwebサイトのHTMLに貼り付けます。次に「プロフィールを編集」タブから、「プロフィール補足情報」のいずれかの欄にwebサイトのURLを記入し、「変更を保存」をクリックしてください。 verification: 認証 verified_links: 確認済みリンク + website_verification: ウェブサイトの認証 webauthn_credentials: add: セキュリティキーを追加 create: 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..993488f1fc0934 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: @@ -264,6 +264,8 @@ kab: domain: Taɣult new: create: Rnu taɣult + export_domain_allows: + no_file: Ula d yiwen ufaylu ma yettwafran export_domain_blocks: no_file: Ulac afaylu yettwafernen follow_recommendations: @@ -529,6 +531,10 @@ kab: account_status: Addad n umiḍan functional: Amiḍan-inek·inem yetteddu s lekmal-is. use_security_key: Seqdec tasarut n teɣlist + author_attribution: + example_title: Amedya n weḍris + more_from_html: Ugar s ɣur %{name} + s_blog: Ablug n %{name} challenge: confirm: Kemmel invalid_password: Yir awal uffir @@ -685,6 +691,9 @@ kab: subject: Yuder-ik·ikem-id %{name} reblog: subject: "%{name} yesselha addad-ik·im" + title: Azuzer amaynut + status: + subject: "%{name} akken i d-y·t·essufeɣ" number: human: decimal_units: @@ -710,8 +719,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 +785,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..43944fe0f651cc 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -19,6 +19,7 @@ ko: posts: other: 게시물 posts_tab_heading: 게시물 + self_follow_error: 본인의 계정을 팔로우할 수는 없습니다 admin: account_actions: action: 조치 취하기 @@ -192,7 +193,7 @@ ko: destroy_domain_allow: 도메인 허용 삭제 destroy_domain_block: 도메인 차단 삭제 destroy_email_domain_block: 이메일 도메인 차단 삭제 - destroy_instance: 도메인 제거 + destroy_instance: 도메인 퍼지하기 destroy_ip_block: IP 규칙 삭제 destroy_status: 게시물 삭제 destroy_unavailable_domain: 사용 불가능한 도메인 제거 @@ -525,7 +526,7 @@ ko: title: 중재 private_comment: 비공개 주석 public_comment: 공개 주석 - purge: 제거 + purge: 퍼지 purge_description_html: 이 도메인이 영구적으로 오프라인 상태라고 생각되면, 스토리지에서 이 도메인의 모든 계정 레코드와 관련 데이터를 삭제할 수 있습니다. 이 작업은 시간이 좀 걸릴 수 있습니다. title: 연합 total_blocked_by_us: 우리에게 차단 됨 @@ -863,6 +864,9 @@ ko: message_html: 아직 서버 규칙을 정하지 않았습니다. sidekiq_process_check: message_html: "%{value} 큐에 대한 사이드킥 프로세스가 발견되지 않았습니다. 사이드킥 설정을 검토해주세요" + software_version_check: + action: 사용 가능한 업데이트 보기 + message_html: 마스토돈 업데이트가 있습니다. software_version_critical_check: action: 사용 가능한 업데이트 보기 message_html: 긴급 마스토돈 업데이트가 있으니, 가능한 서둘러 업데이트 해주세요. @@ -1146,7 +1150,6 @@ ko: use_security_key: 보안 키 사용 author_attribution: example_title: 예시 텍스트 - hint_html: 링크가 마스토돈에 공유될 때 내가 어떻게 표시될 지를 제어합니다. more_from_html: "%{name}의 게시물 더 보기" s_blog: "%{name}의 블로그" title: 작성자 기여 @@ -1340,19 +1343,31 @@ ko: overwrite: 덮어쓰기 overwrite_long: 기존 것을 모두 지우고 새로 추가 overwrite_preambles: - blocking_html: 나의 차단 목록%{filename}에서 가져온 %{total_items} 개의 계정으로 덮어 씌우려고 합니다. - bookmarks_html: 나의 북마크%{filename}에서 가져온 %{total_items} 개의 게시물로 덮어 씌우려고 합니다. - domain_blocking_html: 나의 도메인 차단 목록%{filename}에서 가져온 %{total_items} 개의 도메인으로 덮어 씌우려고 합니다. - following_html: "%{filename}에서 가져온 %{total_items} 개의 계정팔로우하고 나머지 계정을 팔로우 해제하려고 합니다." - lists_html: 나의 리스트%{filename}에서 가져온 %{total_items} 개의 계정으로 덮어 씌우려고 합니다. - muting_html: 나의 뮤트한 계정 목록%{filename}에서 가져온 %{total_items} 개의 계정으로 덮어 씌우려고 합니다. + blocking_html: + other: 나의 차단 목록%{filename}에서 가져온 %{count} 개의 계정으로 덮어 씌우려고 합니다. + bookmarks_html: + other: 나의 북마크%{filename}에서 가져온 %{count} 개의 게시물로 덮어 씌우려고 합니다. + domain_blocking_html: + other: 나의 도메인 차단 목록%{filename}에서 가져온 %{count} 개의 도메인으로 덮어 씌우려고 합니다. + following_html: + other: "%{filename}에서 가져온 %{count} 개의 계정팔로우하고 나머지 계정을 팔로우 해제하려고 합니다." + lists_html: + other: 나의 리스트%{filename}에서 가져온 %{count} 개의 계정으로 덮어 씌우려고 합니다. + muting_html: + other: 나의 뮤트한 계정 목록%{filename}에서 가져온 %{count} 개의 계정으로 덮어 씌우려고 합니다. preambles: - blocking_html: "%{filename}에서 가져온 %{total_items}개의 계정을 차단하려고 합니다." - bookmarks_html: "%{filename}에서 가져온 %{total_items}개의 게시물을 북마크에 추가하려고 합니다." - domain_blocking_html: "%{filename}에서 가져온 %{total_items}개의 도메인을 차단하려고 합니다." - following_html: "%{filename}에서 가져온 %{total_items}개의 계정을 팔로우하려고 합니다." - lists_html: "%{filename}에서 가져온 %{total_items}개의 계정을 내 리스트에 추가하려고 합니다. 추가할 리스트가 존재하지 않으면 새로 생성될 것입니다." - muting_html: "%{filename}에서 가져온 %{total_items}개의 계정을 뮤트하려고 합니다." + blocking_html: + other: "%{filename}에서 가져온 %{count}개의 계정을 차단하려고 합니다." + bookmarks_html: + other: "%{filename}에서 가져온 %{count}개의 게시물을 북마크에 추가하려고 합니다." + domain_blocking_html: + other: "%{filename}에서 가져온 %{count}개의 도메인을 차단하려고 합니다." + following_html: + other: "%{filename}에서 가져온 %{count}개의 계정을 팔로우하려고 합니다." + lists_html: + other: "%{filename}에서 가져온 %{count}개의 계정을 내 리스트에 추가하려고 합니다. 추가할 리스트가 존재하지 않으면 새로 생성될 것입니다." + muting_html: + other: "%{filename}에서 가져온 %{count}개의 계정을 뮤트하려고 합니다." preface: 다른 서버에서 내보내기 한 파일에서 팔로우 / 차단 정보를 이 계정으로 불러올 수 있습니다. recent_imports: 최근의 가져오기 states: @@ -1668,7 +1683,7 @@ ko: delete: 계정 삭제 development: 개발 edit_profile: 프로필 편집 - export: 데이터 내보내기 + export: 내보내기 featured_tags: 추천 해시태그 import: 데이터 가져오기 import_and_export: 가져오기 & 내보내기 @@ -1691,7 +1706,7 @@ ko: lost_followers: 잃은 팔로워 lost_follows: 잃은 팔로우 preamble: 내가 도메인을 차단하거나 중재진이 다른 서버를 정지하기로 결정했다면 내 팔로우와 팔로워를 잃게 됩니다. 그런 일이 일어났다면 그로 인해 단절된 관계들의 목록을 다운로드 받아 확인하고 다른 서버에서 불러올 수 있습니다. - purged: 이 서버에 대한 정보는 관리자에 의해 삭제되었습니다. + purged: 이 서버의 정보는 관리자가 퍼지하였습니다. type: 이벤트 statuses: attached: 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..ad241856a43161 100644 --- a/config/locales/lad.yml +++ b/config/locales/lad.yml @@ -46,6 +46,7 @@ lad: title: Troka la posta elektronika de %{username} change_role: changed_msg: Rolo trokado kon sukseso! + edit_roles: Administra reglas de utilizadores label: Troka rolo no_role: Sin rolo title: Troka rolo para %{username} @@ -595,6 +596,7 @@ lad: resolve_description_html: No se tomaran aksyones kontra el kuento denunsiado, no se enrejistrara el amonestamiento, i se serrara el raporto. silence_description_html: El profil sera vizivle solo para akeyos ke ya lo sigan o lo bushken manualmente, limitando seriamente su alkanse. Siempre puede ser revertido. suspend_description_html: El profil i todos sus kontenidos seran inaksesivles asta ke sean enfin supremidos. La enteraksion kon el kuento sera emposivle. Reversivle durante un tiempo de 30 diyas. + actions_description_html: Dechide kualas mizuras tomar para rezolver esta denunsia. Si tomas una aksion punitiva kontra el kuento denunsiada, se le embiara a dicho kuento un avizo por posta elektronika, ekseptado kuando se eskoja la kategoria Spam. actions_description_remote_html: Dechide ke fazer para rezolver este raporto. Esto solo va afektar komo tu sirvidor komunike kon este kuento remoto i ke faze kon su kontenido. add_to_report: Adjusta mas al raporto already_suspended_badges: @@ -697,6 +699,7 @@ lad: manage_appeals: Administra apelasiones manage_appeals_description: Permete a los utilizadores revizar apelasiones kontra aksyones de moderasyon manage_blocks: Administra blokos + manage_blocks_description: Permete a los utilizadores blokar los prokuradores de posta elektronika i los adresos IP manage_custom_emojis: Administra emojis personalizados manage_custom_emojis_description: Permete a los utilizadores editar emojis personalizados en el sirvidor manage_federation: Administra federasyon @@ -714,6 +717,7 @@ lad: manage_taxonomies: Administra etiketas manage_taxonomies_description: Permete a los utilizadores revizar el kontenido en trend i aktualizar la konfigurasyon de las etiketas manage_user_access: Administra akseso de utilizadores + manage_user_access_description: Permete a los utilizadores dezaktivar la autentifikasyon en dos pasos de otros utilizadores, trokar sus adreso de posta elektronika i restableser sus kod manage_users: Administra utilizadores manage_users_description: Permete a los utilizadores ver los peratim de otros utilizadores i realizar aksyones de moderasyon kontra eyos manage_webhooks: Administrar webhooks @@ -787,6 +791,7 @@ lad: destroyed_msg: Dosya supremida kon sukseso! software_updates: critical_update: Kritiko – por favor aktualiza pishin + description: Rekomendamos ke mantengas aktualizada tu enstalasyon de Mastodon para benefisyar de las muevas koreksyones y funksyones. Ademas, a vezes es kritiko aktualizar Mastodon punktualmente para evitar problemas de sigurita. Por estas razones, Mastodon komprova si ay aktualizasyones kada 30 minutos, i te avizara de akodro a tus preferensyas de avizos por posta elektronika. documentation_link: Ambezate mas release_notes: Notas sovre la versyon title: Aktualizasyones desponivles @@ -860,6 +865,9 @@ lad: message_html: No tienes definido dinguna regla del sirvidor. sidekiq_process_check: message_html: No ay dingun prosedura Sidekiq en egzekusion para la(s) kola(s) %{value}. Por favor, reviza tu konfigurasyon de Sidekiq + software_version_check: + action: Amostra aktualizasyones desponivles + message_html: Una aktualizasyon de Mastodon esta desponivle. software_version_critical_check: action: Amostra aktualizasyones desponivles message_html: Una aktualizasyon kritika de Mastodon esta desponivle. Por favor aktualiza pishin. @@ -874,8 +882,15 @@ 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 + reviewed: Revizado title: Estado + unreviewed: No revizado + usable: Uzavle name: Nombre + newest: Mas muevos + oldest: Mas viejos + open: Ve puvlikamente reset: Reinisya review: Estado de revizion search: Bushka @@ -1027,7 +1042,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 +1064,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 +1072,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 +1115,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. @@ -1108,12 +1129,16 @@ lad: title: Kriya kuento de Mastodon en %{domain}. status: account_status: Estado del kuento + confirming: Bekleando konfirmasyon de posta elektronika. 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 +1175,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 @@ -1307,20 +1335,6 @@ lad: merge_long: Manten rejistros egzistentes i adjusta muevos overwrite: Sobreskrive overwrite_long: Mete muevos rejistros en vez de los aktuales - overwrite_preambles: - blocking_html: Estas a punto de substituyir tu lista de blokos por asta %{total_items} kuentos de %{filename}. - bookmarks_html: Estas a punto de substituyir tus markadores por asta %{total_items} publikasyones ke vinyeron de %{filename}. - domain_blocking_html: Estas a punto de substituyir tu lista de blokos de domeno por asta %{total_items} domenos de %{filename}. - following_html: Estas a punto de segir asta %{total_items} kuentos de %{filename} i deshar de segir todos los otros kuentos. - lists_html: Estas a punto de sustituyir tus listas con el kontenido de %{filename}. Asta %{total_items} kuentos seran adjustados a muevas listas. - muting_html: Estas a punto de substituyir tu lista de kuentos silensyados por asta %{total_items} kuentos de %{filename}. - preambles: - blocking_html: Estas a punto de blokar asta %{total_items} kuentos de %{filename}. - bookmarks_html: Estas a punto de adjustar asta %{total_items} publikasyones de %{filename} a tus markadores. - domain_blocking_html: Estas a punto de blokar asta %{total_items} domenos de %{filename}. - following_html: Estas a punto de segir asta %{total_items} kuentos de %{filename}. - lists_html: Estas a punto de adjustar %{total_items} kuentos dizde %{filename} a tus listas. Se kriyaran muevas listas si no ay listas para adjustarlas. - muting_html: Estas a punto de silensyar asta %{total_items} kuentos de %{filename}. preface: Puedes importar siertos datos, komo todas las personas a las kualas estas sigiendo o blokando en tu kuento en esta instansya, dizde dosyas eksportadas de otra instansya. recent_imports: Importasyones resyentes states: @@ -1380,6 +1394,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 +1405,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 +1650,7 @@ lad: delete: Efasa kuento development: Dezvelopamiento edit_profile: Edita profil - export: Eksporta enformasyon + export: Eksporto featured_tags: Etiketas avaliadas import: Importo import_and_export: Importo i eksporto @@ -1864,6 +1880,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. @@ -1872,6 +1889,7 @@ lad: instructions_html: Kopia i apega este kodiche en el HTML de tu sitio web. Estonses, adjusta el adreso de tu sitio web en uno de los kutis adisyonales de tu profil dizde la seksyon "Edita profil" i guadra los trokamyentos. verification: Verifikasyon verified_links: Tus atadijos verifikados + website_verification: Verifikasyon de sityo web webauthn_credentials: add: Adjusta mueva yave de sigurita create: diff --git a/config/locales/lt.yml b/config/locales/lt.yml index fa07eb6f59dfc0..8ba3bad07040ab 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 @@ -814,9 +817,11 @@ lt: view_strikes: Peržiūrėti ankstesnius savo paskyros pažeidimus author_attribution: example_title: Teksto pavyzdys - hint_html: Valdyk, kaip esi nurodomas (-a), kai nuorodos bendrinamos platformoje „Mastodon“. + hint_html: Ar rašote naujienas ar tinklaraščio straipsnius už „Mastodon“ ribų? Valdykite, kaip būsite nurodomi, kai jais bus bendrinama platformoje „Mastodon“. + instructions: 'Įsitikinkite, kad šis kodas yra jūsų straipsnio HTML:' more_from_html: Daugiau iš %{name} s_blog: "%{name} tinklaraštis" + then_instructions: Tada toliau esančiame lauke įrašykite leidinio domeno vardą. title: Autoriaus (-ės) atribucija challenge: hint_html: "Patarimas: artimiausią valandą daugiau neprašysime tavo slaptažodžio." @@ -1090,7 +1095,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..908b15e851bc09 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -23,6 +23,7 @@ lv: other: Ziņas zero: Ziņu posts_tab_heading: Ziņas + self_follow_error: Nav ļauts sekot savam kontam admin: account_actions: action: Veikt darbību @@ -34,6 +35,7 @@ lv: created_msg: Moderācijas piezīme ir veiksmīgi izveidota! destroyed_msg: Moderācijas piezīme ir veiksmīgi iznīcināta! accounts: + add_email_domain_block: Liegt e-pasta domēnu approve: Apstiprināt approved_msg: Veiksmīgi apstiprināts %{username} reģistrēšanās pieteikums are_you_sure: Vai esi pārliecināts? @@ -61,6 +63,7 @@ lv: demote: Pazemināt destroyed_msg: Lietotāja %{username} dati tagad ievietoti rindā, lai tos nekavējoties izdzēstu disable: Iesaldēt + disable_sign_in_token_auth: Atspējot autentificēšanos ar e-pasta pilnvaru disable_two_factor_authentication: Atspējot 2FA disabled: Iesaldēts display_name: Parādāmais vārds @@ -69,6 +72,7 @@ lv: email: E-pasts email_status: E-pasta statuss enable: Atsaldēt + enable_sign_in_token_auth: Iespējot autentificēšanos ar e-pasta pilnvaru enabled: Iespējots enabled_msg: Veiksmīgi atsaldēts %{username} konts followers: Sekotāji @@ -180,17 +184,21 @@ lv: confirm_user: Apstiprināt lietotāju create_account_warning: Izveidot Brīdinājumu create_announcement: Izveidot Paziņojumu + create_canonical_email_block: Izveidot e-pasta liegumu create_custom_emoji: Izveidot pielāgotu emocijzīmi create_domain_allow: Izveidot Domēna Atļauju create_domain_block: Izveidot Domēna Bloku + create_email_domain_block: Izveidot e-pasta domēna liegumu create_ip_block: Izveidot IP noteikumu create_unavailable_domain: Izveidot Nepieejamu Domēnu create_user_role: Izveidot lomu demote_user: Pazemināt Lietotāju destroy_announcement: Dzēst Paziņojumu + destroy_canonical_email_block: Izdzēst e-pasta liegumu destroy_custom_emoji: Dzēst pielāgoto emocijzīmi destroy_domain_allow: Dzēst Domēna Atļauju destroy_domain_block: Dzēst Domēna Bloku + destroy_email_domain_block: Izdzēst e-pasta domēna liegumu destroy_instance: Attīrīt domēnu destroy_ip_block: Dzēst IP noteikumu destroy_status: Izdzēst Rakstu @@ -198,8 +206,10 @@ lv: destroy_user_role: Iznīcināt lomu disable_2fa_user: Atspējot 2FA disable_custom_emoji: Atspējot pielāgotu emocijzīmi + disable_sign_in_token_auth_user: Atspējot autentificēšanos ar e-pasta pilnvaru lietotājam disable_user: Atspējot Lietotāju enable_custom_emoji: Iespējot pielāgotu emocijzīmi + enable_sign_in_token_auth_user: Iespējot autentificēšanos ar e-pasta pilnvaru lietotājam enable_user: Ieslēgt Lietotāju memorialize_account: Saglabāt Kontu Piemiņai promote_user: Izceltt Lietotāju @@ -1130,6 +1140,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: @@ -1335,20 +1347,6 @@ lv: merge_long: Saglabāt esošos ierakstus un pievienot jaunus overwrite: Pārrakstīt overwrite_long: Nomainīt pašreizējos ierakstus ar jauniem - overwrite_preambles: - blocking_html: Tu gatavojies aizstāt savu bloķēto sarakstu ar līdz pat %{total_items} kontiem no %{filename}. - bookmarks_html: Tu gatavojies aizstāt savas bloķētās izlases ar līdz pat %{total_items} ziņām no %{filename}. - domain_blocking_html: Tu gatavojies aizstāt savu bloķēto domēnu sarakstu ar līdz pat %{total_items} domēniem no %{filename}. - following_html: Tu gatavojies sekot līdz pat %{total_items} kontiem no %{filename} un pārtrauksi sekot citiem. - lists_html: Tu gatavojies aizstāt savus sarakstus ar %{filename} saturu. Līdz %{total_items} kontiem tiks pievienoti jauni saraksti. - muting_html: Tu gatavojies aizstāt savu noklusināto kontu sarakstu ar līdz pat %{total_items} kontiem no %{filename}. - preambles: - blocking_html: Tu gatavojies bloķēt līdz pat %{total_items} kontiem no %{filename}. - bookmarks_html: Tu gatavojies pievienot līdz pat %{total_items} ziņām no %{filename} savām grāmatzīmēm. - domain_blocking_html: Tu gatavojies bloķēt līdz pat %{total_items} domēniem no %{filename}. - following_html: Tu gatavojies sekot līdz pat %{total_items} kontiem no %{filename}. - lists_html: Tu gatavojies pievienot līdz pat %{total_items} kontiem no %{filename} saviem sarakstiem. Jauni saraksti tiks izveidoti, ja nav saraksta, ko pievienot. - muting_html: Tu gatavojies noklusināt līdz pat %{total_items} kontiem no %{filename}. preface: Tu vari ievietot datus, kurus esi izguvis no cita servera, kā, piemēram, cilvēku sarakstu, kuriem Tu seko vai kurus bloķē. recent_imports: Nesen importēts states: @@ -1650,20 +1648,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 +1830,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/ml.yml b/config/locales/ml.yml index bdc0475a6f9086..c27e5e5467a802 100644 --- a/config/locales/ml.yml +++ b/config/locales/ml.yml @@ -4,18 +4,25 @@ ml: contact_missing: സജ്ജമാക്കിയിട്ടില്ല contact_unavailable: ലഭ്യമല്ല accounts: + followers: + one: പിന്തുടരാളി + other: പിന്തുടരുന്നവർ following: പിന്തുടരുന്നു last_active: അവസാനം സജീവമായിരുന്നത് link_verified_on: സന്ധിയുടെ ഉടമസ്ഥാവസ്‌കാശം %{date} ൽ പരിശോധിക്കപ്പെട്ടു nothing_here: ഇവിടെ ഒന്നുമില്ല! posts_tab_heading: ടൂട്ടുകൾ admin: + account_moderation_notes: + create: ഒരു കുറിപ്പു് വിടുക accounts: + add_email_domain_block: ഈ ഇ-തപാൽ മേഖല തടസ്സപെടുത്തുക approve: അംഗീകരിക്കുക are_you_sure: നിങ്ങൾക്ക് ഉറപ്പാണോ? avatar: അവതാർ by_domain: മേഖല change_email: + changed_msg: ഇ-തപാൽ ശരിയായിട്ടു് മാറ്റീ! current_email: ഇപ്പോഴത്തെ ഇലക്ട്രോണിക് കത്തിന്റെ മേൽവിലാസം label: മാറിയ ഇലക്ട്രോണിക് കത്തിന്റെ മേൽവിലാസം new_email: പുതിയ ഇലക്ട്രോണിക് കത്ത് @@ -24,6 +31,7 @@ ml: confirm: നിജപ്പെടുത്തുക confirmed: നിജപ്പെടുത്തി confirming: സ്ഥിരീകരിക്കുന്നു + custom: സ്വന്തമായ ഭേദഗതി delete: ഡാറ്റ ഇല്ലാതാക്കുക deleted: മായിച്ചു demote: തരം താഴ്ത്തുക @@ -34,7 +42,9 @@ ml: domain: മേഖല edit: തിരുത്തുക email: ഇമെയിൽ + email_status: ഇ-തപാൽ അവസ്ഥ header: തലക്കെട്ട് + inbox_url: ഇ-തപാല്പെട്ടി വിലാസം joined: ജോയിൻ ചെയ്‌തിരിക്കുന്നു location: all: എല്ലാം @@ -46,9 +56,18 @@ ml: all: എല്ലാം suspended: താൽക്കാലികമായി നിർത്തി title: മധ്യസ്ഥന്‍ + protocol: പെരുമാറ്റച്ചട്ടം + public: പൊതുവു് + remove_header: തലക്കെട്ടു് മാറ്റുക + resend_confirmation: + send: ഉറപ്പിക്കൽ-വിലാസം വീണ്ടും അയക്കുക reset: പുനഃക്രമീകരിക്കുക reset_password: പാസ്‌വേഡ് പുനഃക്രമീകരിക്കുക search: തിരയുക + security: സുരക്ഷ + security_measures: + only_password: രഹസ്യവാക്ക് മാത്രം + silence: അതിർ title: അക്കൗണ്ടുകൾ unconfirmed_email: സ്ഥിരീകരിക്കാത്ത ഇമെയിൽ username: ഉപയോക്തൃനാമം diff --git a/config/locales/ms.yml b/config/locales/ms.yml index 0c0ffb69bfc849..90493a30b685c6 100644 --- a/config/locales/ms.yml +++ b/config/locales/ms.yml @@ -1223,20 +1223,6 @@ ms: merge_long: Simpan rekod sedia ada dan tambah rekod baharu overwrite: Tulis ganti overwrite_long: Gantikan rekod semasa dengan yang baharu - overwrite_preambles: - blocking_html: Anda akan menggantikan senarai blok anda dengan sehingga %{total_items} akaun daripada %{filename}. - bookmarks_html: Anda akan menggantikan penanda halaman anda dengan sehingga %{total_items} siaran daripada %{filename}. - domain_blocking_html: Anda akan menggantikan senarai blok domain anda dengan sehingga %{total_items} domain daripada %{filename}. - following_html: Anda akan mengikuti sehingga %{total_items} akaun daripada %{filename} dan berhenti mengikuti orang lain. - lists_html: Anda akan menggantikan senarai anda dengan kandungan %{filename}. Sehingga %{total_items} akaun akan ditambahkan pada senarai baharu. - muting_html: Anda akan menggantikan senarai akaun yang diredamkan dengan sehingga %{total_items} akaun daripada %{filename}. - preambles: - blocking_html: Anda akan menyekat sehingga %{total_items} akaun daripada %{filename}. - bookmarks_html: Anda akan menambah sehingga %{total_items} pos daripada %{filename} ke penanda halaman anda. - domain_blocking_html: Anda akan menyekat sehingga %{total_items} domain daripada %{filename}. - following_html: Anda akan mengikuti sehingga %{total_items} akaun daripada %{filename}. - lists_html: Anda akan menambah sehingga %{total_items} akaun daripada %{filename} ke senarai anda. Senarai baharu akan dibuat jika tiada senarai untuk ditambah. - muting_html: Anda akan membisukan sehingga %{total_items} akaun daripada %{filename}. preface: Anda boleh mengimport data yang telah anda eksport dari server lain, seperti senarai orang yang anda ikuti atau sekat. recent_imports: Import terkini states: @@ -1529,7 +1515,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..6a330a16c7f75a 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -1222,20 +1222,6 @@ my: merge_long: ရှိပြီးသားမှတ်တမ်းများ သိမ်းဆည်းပြီး အသစ်များ ထပ်ထည့်ပါ overwrite: ထပ်ရေးရန် overwrite_long: လက်ရှိမှတ်တမ်းများကို အသစ်များဖြင့် အစားထိုးပါ - overwrite_preambles: - blocking_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ အထိ သင့်ပိတ်ဆို့စာရင်းကို အစားထိုးပါတော့မည်။ - bookmarks_html: သင်သည် %{filename} မှ %{total_items} ပို့စ်များ အထိ သင့် bookmark များကို အစားထိုးပါတော့မည်။ - domain_blocking_html: သင်သည် %{filename} မှ %{total_items} ဒိုမိန်းများ ဖြင့် သင်၏ ဒိုမိန်းပိတ်ဆို့စာရင်းကို အစားထိုးပါတော့မည်။ - following_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ အထိ စောင့်ကြည့် ပြီး အခြားမည်သူ့ကိုမျှ စောင့်မကြည့်တော့ပါ ။ - lists_html: သင်သည် %{filename} ၏ အကြောင်းအရာများဖြင့် သင့်စာရင်းများကို အစားထိုး ပါတော့မည်။ %{total_items} အကောင့်များအထိ စာရင်းအသစ်များသို့ ပေါင်းထည့်ပါမည်။ - muting_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ ဖြင့် အသံပိတ်ထားသော သင့်အကောင့်များစာရင်းကို အစားထိုးပါတော့မည်။ - preambles: - blocking_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ အထိ ပိတ်ဆို့ပါတော့မည်။ - bookmarks_html: သင်သည် %{filename} မှ %{total_items} ပို့စ်များ အထိ သင့် Bookmark များ သို့ ပေါင်းထည့်တော့မည်။ - domain_blocking_html: သင်သည် %{filename} မှ %{total_items} ဒိုမိန်းများ အထိ ပိတ်ဆို့ပါတော့မည်။ - following_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ အထိ စောင့်ကြည့် ပါတော့မည်။ - lists_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ ကို သင့် စာရင်းများ သို့ ပေါင်းထည့်ပါတော့မည်။ ထည့်ရန်စာရင်းမရှိပါက စာရင်းအသစ်များကို ဖန်တီးပါမည်။ - muting_html: သင်သည် %{filename} မှ %{total_items} အကောင့်များ အထိ အသံတိတ်ပါတော့မည်။ preface: သင်စောင့်ကြည့်နေသည့်လူများစာရင်း သို့မဟုတ် ပိတ်ပင်ထားသည့်စာရင်းကဲ့သို့သော အခြားဆာဗာတစ်ခုမှ သင်ထုတ်ယူထားသည့်အချက်အလက်များကို ပြန်လည်ထည့်သွင်းနိုင်သည်။ recent_imports: လတ်တလောထည့်သွင်းမှုများ states: @@ -1529,7 +1515,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..1af30bca98bff0 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -21,6 +21,7 @@ nl: one: Toot other: Berichten posts_tab_heading: Berichten + self_follow_error: Het volgen van je eigen account is niet toegestaan admin: account_actions: action: Actie uitvoeren @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ nl: use_security_key: Beveiligingssleutel gebruiken author_attribution: example_title: Voorbeeldtekst - hint_html: Bepaal hoe we je vermelden, wanneer jouw links op Mastodon worden gedeeld. + hint_html: Schrijf je nieuws- of blogartikelen buiten Mastodon? Bepaal hoe je geattribueerd wordt als deze gedeeld worden op Mastodon. + instructions: 'Zorg ervoor dat deze code in de HTML van je artikel zit:' more_from_html: Meer van %{name} s_blog: De weblog van %{name} + then_instructions: Voeg vervolgens de domeinnaam van de publicatie toe in het onderstaande veld. title: Auteur-attributie challenge: confirm: Doorgaan @@ -1363,19 +1369,43 @@ nl: overwrite: Overschrijven overwrite_long: Huidige gegevens met de nieuwe gegevens vervangen overwrite_preambles: - blocking_html: Je staat op het punt jouw lijst met geblokkeerde accounts te vervangen door %{total_items} accounts vanuit %{filename}. - bookmarks_html: Je staat op het punt jouw bladwijzers te vervangen door %{total_items} berichten vanuit %{filename}. - domain_blocking_html: Je staat op het punt jouw lijst met geblokkeerde domeinen te vervangen door %{total_items} domeinen vanuit %{filename}. - following_html: Je staat op het punt om %{total_items} accounts te volgen vanuit %{filename} en te stoppen met het volgen van alle andere accounts. - lists_html: Je staat op het punt je lijsten te vervangen door inhoud van %{filename}. Er worden totaal %{total_items} accounts aan nieuwe lijsten toegevoegd. - muting_html: Je staat op het punt jouw lijst met genegeerde accounts te vervangen door %{total_items} accounts vanuit %{filename}. + blocking_html: + one: Je staat op het punt om vanuit %{filename} je blokkeerlijst te vervangen met in het totaal %{count} account. + other: Je staat op het punt om vanuit %{filename} je blokkeerlijst te vervangen met in het totaal %{count} accounts. + bookmarks_html: + one: Je staat op het punt om vanuit %{filename} je bladwijzers te vervangen met in het totaal %{count} bericht. + other: Je staat op het punt om vanuit %{filename} je bladwijzers te vervangen met in het totaal %{count} berichten. + domain_blocking_html: + one: Je staat op het punt om vanuit %{filename} je lijst met geblokkeerde domeinen te vervangen met in het totaal %{count} domein. + other: Je staat op het punt om vanuit %{filename} je lijst met geblokkeerde domeinen te vervangen met in het totaal %{count} domeinen. + following_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} account te volgen en de rest te ontvolgen. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} accounts te volgen en de rest te ontvolgen. + lists_html: + one: Je staat op het punt om met de inhoud van %{filename} je lijsten te vervangen. In het totaal wordt %{count} account aan de nieuwe lijst(en) toegevoegd. + other: Je staat op het punt om met de inhoud van %{filename} je lijsten te vervangen. In het totaal worden %{count} accounts aan de nieuwe lijst(en) toegevoegd. + muting_html: + one: Je staat op het punt om vanuit %{filename} je negeerlijst te vervangen met in het totaal %{count} account. + other: Je staat op het punt om vanuit %{filename} je blokkeerlijst te vervangen met in het totaal %{count} accounts. preambles: - blocking_html: Je staat op het punt om %{total_items} accounts te blokkeren vanuit %{filename}. - bookmarks_html: Je staat op het punt om %{total_items} berichten aan je bladwijzers toe te voegen vanuit %{filename}. - domain_blocking_html: Je staat op het punt om %{total_items} accounts te negeren vanuit %{filename}. - following_html: Je staat op het punt om %{total_items} accounts te volgen vanuit %{filename}. - lists_html: Je staat op het punt om tot %{total_items} accounts van %{filename} toe te voegen aan je lijsten. Nieuwe lijsten worden aangemaakt als er geen lijst is om aan toe te voegen. - muting_html: Je staat op het punt om %{total_items} accounts te negeren vanuit %{filename}. + blocking_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} account te blokkeren. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} accounts te blokkeren. + bookmarks_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} bericht aan je bladwijzers toe te voegen. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} berichten aan je bladwijzers toe te voegen. + domain_blocking_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} domein te blokkeren. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} domeinen te blokkeren. + following_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} account te volgen. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} accounts te volgen. + lists_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} account aan je lijsten toe te voegen. Er wordt een nieuwe lijst aangemaakt wanneer er geen lijst is om het aan toe te voegen. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} accounts aan je lijsten toe te voegen. Er worden nieuwe lijsten aangemaakt wanneer er geen lijsten zijn om ze aan toe te voegen. + muting_html: + one: Je staat op het punt om vanuit %{filename} in het totaal %{count} account te negeren. + other: Je staat op het punt om vanuit %{filename} in het totaal %{count} accounts te negeren. preface: Je kunt bepaalde gegevens, zoals de mensen die jij volgt of hebt geblokkeerd, naar jouw account op deze server importeren. Je moet deze gegevens wel eerst op de oorspronkelijke server exporteren. recent_imports: Recent geïmporteerd states: @@ -1523,8 +1553,8 @@ nl: title: Nieuw volgverzoek mention: action: Reageren - body: 'Jij bent door %{name} vermeld in:' - subject: Jij bent vermeld door %{name} + body: 'Je bent door %{name} vermeld in:' + subject: Je bent vermeld door %{name} title: Nieuwe vermelding poll: subject: Een peiling van %{name} is beëindigd diff --git a/config/locales/nn.yml b/config/locales/nn.yml index dcf571a7923c46..e6edc2c4b2e18d 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -1,7 +1,7 @@ --- nn: about: - about_mastodon_html: 'Framtidas sosiale nettverk: Ingen annonsar, ingen verksemder som overvaker deg, etisk design og desentralisering! Eig idéane dine med Mastodon!' + about_mastodon_html: 'Framtidas sosiale nettverk: Ingen annonsar, ingen verksemder som overvaker deg, etisk design og desentralisering! Eig dataene dine med Mastodon!' contact_missing: Ikkje sett contact_unavailable: I/T hosted_on: "%{domain} er vert for Mastodon" @@ -21,6 +21,7 @@ nn: one: Tut other: Tut posts_tab_heading: Tut + self_follow_error: Det er ikkje tillate å følgje din eigen konto admin: account_actions: action: Utfør @@ -39,7 +40,7 @@ nn: avatar: Bilete by_domain: Domene change_email: - changed_msg: Konto-e-posten er endra! + changed_msg: E-post for konto er endra! current_email: Noverande e-post label: Byt e-post new_email: Ny e-post @@ -62,7 +63,7 @@ nn: disable: Slå av disable_sign_in_token_auth: Slå av e-post-token-autentisering disable_two_factor_authentication: Slå av 2FA - disabled: Slege av + disabled: Inaktiv display_name: Synleg namn domain: Domene edit: Rediger @@ -689,10 +690,10 @@ nn: moderation: Moderering special: Særskild delete: Slett - description_html: Med brukarrollar kan du kontrollera kva funksjonar og område av Mastodon brukarane dine har tilgong til. + description_html: Med brukarroller kan du kontrollera kva funksjonar og område av Mastodon brukarane dine har tilgang til. edit: Endr rollen '%{name}' everyone: Standard-tillatelser - everyone_full_description_html: Dette er grunnrollen som påverkar alle brukarar, jamvel dei utan ei tilsett rolle. Alle andre rollar arvar tillatingar frå denne. + everyone_full_description_html: Dette er grunnrolla som påverkar alle brukarar, jamvel dei utan ei tildelt rolle. Alle andre rollar arvar tilgangsløve frå denne. permissions_count: one: "%{count} tillatelse" other: "%{count} tillatelser" @@ -718,7 +719,7 @@ nn: manage_reports: Handtere rapporteringar manage_reports_description: Let brukarar gjennomgå rapportar og utføre modereringshandlingar i samsvar med desse manage_roles: Handsam roller - manage_roles_description: Tillet at brukarar handsamar og tilset rollar under deira eiga + manage_roles_description: Tillet at brukarar handsamar og tildeler roller som er lågare enn dera eiga manage_rules: Handtere reglar manage_rules_description: Let brukarar endre reglane for tenaren manage_settings: Handtere innstillingar @@ -737,7 +738,7 @@ nn: view_dashboard_description: Gir brukere tilgang til dashbordet og ulike metrikker view_devops: DevOps view_devops_description: Gir brukere tilgang til Sidekiq og pgHero-dashbord - title: Rollar + title: Roller rules: add_new: Legg til regel delete: Slett @@ -875,6 +876,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. @@ -1162,7 +1166,6 @@ nn: use_security_key: Bruk sikkerhetsnøkkel author_attribution: example_title: Eksempeltekst - hint_html: Kontroller korleis du blir kreditert når nokon deler lenker på Mastodon. more_from_html: Meir frå %{name} s_blog: Bloggen til %{name} title: Forfattarkreditering @@ -1363,19 +1366,9 @@ nn: overwrite: Skriv over overwrite_long: Byt ut dei noverande oppføringane med dei nye overwrite_preambles: - blocking_html: Du skal til å byta ut blokkeringslista di med opp til %{total_items} brukarkontoar frå %{filename}. - bookmarks_html: Du skal til å byta ut bokmerka dine med opp til %{total_items} innlegg frå %{filename}. - domain_blocking_html: Du skal til å byta ut domeneblokkeringslista di med opp til %{total_items} domene frå %{filename}. - following_html: Du skal til å fylgja opp til %{total_items} brukarkontoar frå %{filename} og slutta å fylgja alle andre. - lists_html: Du er i ferd med å erstatta listene dine med innhaldet i %{filename}. Opptil %{total_items} kontoar vil bli lagt til i nye lister. - muting_html: Du skal til å byta ut lista di over dempa brukarkontoar med opp til %{total_items} brukarkontoar frå %{filename}. - preambles: - blocking_html: Du skal til å blokkera opp til %{total_items} brukarkontoar frå %{filename}. - bookmarks_html: Du skal til å leggja til opp til %{total_items} innlegg frå %{filename} til bokmerka dine. - domain_blocking_html: Du skal til å blokkera opp til %{total_items} domene frå %{filename}. - following_html: Du skal til å fylgja opp til %{total_items} brukarkontoar frå %{filename}. - lists_html: Du er i ferd med å leggja til opptil %{total_items} kontoar frå %{filename} til i listene dine. Nye lister vil blir oppretta om ingen lister finst frå før. - muting_html: Du skal til å dempa opp til %{total_items} brukarkontoar frå %{filename}. + blocking_html: + one: Du skal til å byta ut blokkeringslista di med opp til %{count} brukarkonto frå %{filename}. + other: Du skal til å byta ut blokkeringslista di med opp til %{count} brukarkontoar frå %{filename}. preface: Du kan henta inn data som du har eksportert frå ein annan tenar, som t.d. ei liste over folka du fylgjer eller blokkerer. recent_imports: Siste importar states: @@ -1423,7 +1416,7 @@ nn: one: 1 bruk other: "%{count} bruk" max_uses_prompt: Inga grense - prompt: Generer og del lenkjer med andre for å gje tilgong til denne tenaren + prompt: Generer og del lenkjer med andre for å gje tilgang til denne tenaren table: expires_at: Vert ugyldig uses: Bruk @@ -1692,7 +1685,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..94986f4cae9d2d 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -1268,20 +1268,6 @@ merge_long: Behold eksisterende og legg til nye overwrite: Overskriv overwrite_long: Erstatt gjeldende med de nye - overwrite_preambles: - blocking_html: Du er i ferd med å erstatte din blokkeringsliste med inntil %{total_items} kontoer fra %{filename}. - bookmarks_html: Du er i ferd med å erstatte dine bokmerker med inntil %{total_items} innlegg fra %{filename}. - domain_blocking_html: Du er i ferd med å erstatte din domene-blokkeringsliste med inntil %{total_items} domener fra %{filename}. - following_html: Du er i ferd med å følge inntil %{total_items} kontoer fra %{filename} og slutte å følge alle andre. - lists_html: Du er i ferd med å erstatte dine lister med innholdet i %{filename}. Inntil %{total_items} kontoer legges til i nye lister. - muting_html: Du er i ferd med å erstatte listen over dempede kontoer med inntil %{total_items} kontoer fra %{filename}. - preambles: - blocking_html: Du er i ferd med å blokkere inntil %{total_items} kontoer fra %{filename}. - bookmarks_html: Du er i ferd med å legge til inntil %{total_items} innlegg fra %{filename} til dine bokmerker. - domain_blocking_html: Du er i ferd med å blokkere inntil %{total_items} domener fra %{filename}. - following_html: Du er i ferd med å følge inntil %{total_items} kontoer fra %{filename}. - lists_html: Du er i ferd med å legge inntil %{total_items} kontoer fra %{filename} til dine lister. Nye lister vil bli opprettet hvis det ikke finnes noen liste å legge til. - muting_html: Du er i ferd med å dempe inntil %{total_items} kontoer fra %{filename}. preface: Du kan importere data om brukere du følger eller blokkerer til kontoen din på denne instansen med eksportfiler fra andre instanser. recent_imports: Siste importer states: @@ -1584,7 +1570,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..d50a042a22ff5c 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -25,6 +25,7 @@ pl: one: wpis other: Wpisów posts_tab_heading: Wpisy + self_follow_error: Nie możesz obserwować swojego konta admin: account_actions: action: Wykonaj działanie @@ -903,6 +904,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. @@ -1198,9 +1202,11 @@ pl: use_security_key: Użyj klucza bezpieczeństwa author_attribution: example_title: Przykładowy tekst - hint_html: Kontroluj przypisy do twoich wpisów widoczne na Mastodonie. + hint_html: Piszesz wiadomości albo bloga poza Mastodonem? Kontroluj jak będą ci przypisywane podczas dizielenia się nimi na Mastodonie. + instructions: 'Upewnij się, że ten kod jest w HTMLu twojego artykułu:' more_from_html: Więcej od %{name} s_blog: Blog %{name} + then_instructions: Potem, dodaj domenę publikacji do pola poniżej. title: Przypis do autora challenge: confirm: Kontynuuj @@ -1412,20 +1418,6 @@ pl: merge_long: Zachowaj obecne wpisy i dodaj nowe overwrite: Nadpisz overwrite_long: Zastąp obecne wpisy nowymi - overwrite_preambles: - blocking_html: Zamierzasz zastąpić swoją listę bloków maksymalnie %{total_items} kont z %{filename}. - bookmarks_html: Zamierzasz zastąpić swoje zakładki maksymalnie %{total_items} wpisami z %{filename}. - domain_blocking_html: Zamierzasz zastąpić swoją listę bloków domen maksymalnie %{total_items} domenami z %{filename}. - following_html: Zamierzasz zaobserwować maksymalnie %{total_items} kont z %{filename} i przestać obserwować kogokolwiek innego. - lists_html: Zamierzasz zastąpić swoje listy maksymalnie %{total_items} kontami z %{filename}. - muting_html: Zamierzasz zastąpić swoją wyciszonych maksymalnie %{total_items} kontami z %{filename}. - preambles: - blocking_html: Zamierzasz zablokować maksymalnie %{total_items} kont z %{filename}. - bookmarks_html: Zamierzasz dodać maksymalnie %{total_items} wpisów do twoich zakładek z %{filename}. - domain_blocking_html: Zamierzasz zablokować maksymalnie %{total_items} domen z %{filename}. - following_html: Zamierzasz zaobserwować maksymalnie %{total_items} kont z %{filename}. - lists_html: Zamierzasz dodać maksymalnie %{total_items} kont do twoich list z %{filename}. Jeżeli nie ma list, nowe zostaną utworzone. - muting_html: Zamierzasz wyciszyć maksymalnie %{total_items} kont z %{filename}. preface: Możesz zaimportować pewne dane (np. lista kont, które obserwujesz lub blokujesz) do swojego konta na tym serwerze, korzystając z danych wyeksportowanych z innego serwera. recent_imports: Ostatnie importy states: diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 7742a80569c1c8..8b2feb5193baae 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -21,6 +21,7 @@ pt-BR: one: Publicação other: Publicações posts_tab_heading: Publicações + self_follow_error: Seguir sua conta não é permitido admin: account_actions: action: Tomar uma atitude @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ pt-BR: use_security_key: Usar chave de segurança author_attribution: example_title: Texto de amostra - hint_html: Controle como você é creditado quando links são compartilhados no Mastodon. + hint_html: Você está escrevendo notícias ou artigos de blogs fora do Mastodon? Controle como você é credenciado quando eles forem compartilhados no Mastodon. + instructions: 'Certifique-se que este código esteja no HTML do artigo:' more_from_html: Mais de %{name} s_blog: Blog do %{name} + then_instructions: Então, adicione o nome de domínio da publicação no campo abaixo. title: Atribuição de autoria challenge: confirm: Continuar @@ -1362,20 +1368,6 @@ pt-BR: merge_long: Manter os registros existentes e adicionar novos overwrite: Sobrescrever overwrite_long: Substituir os registros atuais com os novos - overwrite_preambles: - blocking_html: Você está prestes a substituir sua lista de bloqueios com até contas%{total_items} de %{filename}. - bookmarks_html: Você está prestes a substituir seus favoritos por até %{total_items} posts de %{filename}. - domain_blocking_html: Você está prestes a substituir sua lista de bloqueio de domínio com até domínios%{total_items} de %{filename}. - following_html: Você está prestes a seguir até %{total_items} contas de %{filename} e parar de seguir todos os outros. - lists_html: Você está prestes a substituir sua lista pelo conteúdo de %{filename}. Até %{total_items} contas serão adicionadas a novas listas. - muting_html: Você está prestes a substituir sua lista de contas silenciadas com até %{total_items} contas de %{filename}. - preambles: - blocking_html: Você está prestes a bloquear até %{total_items} contas de %{filename}. - bookmarks_html: Você está prestes a adicionar até %{total_items} posts de %{filename} para seus favoritos. - domain_blocking_html: Você está prestes a bloquear até %{total_items} domínios de %{filename}. - following_html: Você está prestes a seguir até %{total_items} contas de %{filename}. - lists_html: Você está prestes a adicionar até %{total_items} contas a partir de %{filename} para suas listas. Novas listas serão criadas se não houver uma para a qual adicionar. - muting_html: Você está prestes a silenciar até contas%{total_items} de %{filename}. preface: Você pode importar dados que você exportou de outro servidor, como a lista de pessoas que você segue ou bloqueou. recent_imports: Importações recentes states: @@ -1692,7 +1684,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 @@ -1885,7 +1877,7 @@ pt-BR: none: Aviso sensitive: Conta marcada como sensível silence: Conta silenciada - suspend: Conta banida + suspend: Conta suspensa welcome: apps_android_action: Disponível no Google Play apps_ios_action: Disponível na App Store diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index d6c5c4a6ff01f7..1761ec3f0c0ba8 100644 --- a/config/locales/pt-PT.yml +++ b/config/locales/pt-PT.yml @@ -1162,7 +1162,6 @@ pt-PT: use_security_key: Usar chave de segurança author_attribution: example_title: Texto de exemplo - hint_html: Controle a forma como é creditado quando as hiperligações são partilhadas no Mastodon. more_from_html: Mais de %{name} s_blog: Blog de %{name} title: Atribuição de autor @@ -1362,20 +1361,6 @@ pt-PT: merge_long: Manter os registos existentes e adicionar novos registos overwrite: Escrever por cima overwrite_long: Substituir os registos atuais pelos novos - overwrite_preambles: - blocking_html: Está prestes a substituir a sua lista de bloqueios com até %{total_items} contas de %{filename}. - bookmarks_html: Está prestes a substituir os seus marcadores com até %{total_items} publicações de %{filename}. - domain_blocking_html: Está prestes a substituir a sua lista de bloqueios de domínio com até %{total_items} domínios de %{filename}. - following_html: Está prestes a seguir até %{total_items} contas de %{filename} e parar de seguir quaisquer outras contas. - lists_html: Está prestes a substituir as suas listas pelo conteúdo de %{filename}. Até %{total_items} contas serão adicionadas a novas listas. - muting_html: Está prestes a substituir a sua lista de contas silenciadas com até %{total_items} contas de %{filename}. - preambles: - blocking_html: Está prestes a bloquear até %{total_items} contas de %{filename}. - bookmarks_html: Está prestes a adicionar até %{total_items} publicações de %{filename} aos seus marcadores. - domain_blocking_html: Está prestes a bloquear até %{total_items} domínios de %{filename}. - following_html: Está prestes a seguir até %{total_items} contas de %{filename}. - lists_html: Está prestes a adicionar até %{total_items} contas do ficheiro %{filename} para as suas listas. Novas listas serão criadas se não existir uma lista onde as adicionar. - muting_html: Está prestes a silenciar até %{total_items} contas de %{filename}. preface: Podes importar dados que tenhas exportado de outra instância, como a lista de pessoas que segues ou bloqueadas. recent_imports: Importações recentes states: @@ -1679,7 +1664,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..b7a10269fa9425 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -901,6 +901,8 @@ ru: message_html: Вы не определили правила сервера. sidekiq_process_check: message_html: Ни один Sidekiq не запущен для %{value} очереди(-ей). Пожалуйста, просмотрите настройки Sidekiq + software_version_check: + message_html: Доступно обновление для Mastodon. software_version_critical_check: action: Посмотреть доступные обновления message_html: Доступно критическое обновление Mastodon, пожалуйста, обновитесь как можно скорее. @@ -1196,7 +1198,6 @@ ru: use_security_key: Использовать ключ безопасности author_attribution: example_title: Образец текста - hint_html: Контролируйте, как вы будете отмечены при обмене ссылками на Mastodon. more_from_html: Больше от %{name} s_blog: "%{name}'S Блог" title: Авторская атрибуция @@ -1410,20 +1411,6 @@ ru: merge_long: Сохранить имеющиеся данные и добавить новые. overwrite: Перезаписать overwrite_long: Перезаписать имеющиеся данные новыми. - overwrite_preambles: - blocking_html: Вы собираетесь заменить свой блок-лист на %{total_items} аккаунтов из %{filename}. - bookmarks_html: Вы собираетесь заменить свои закладки на %{total_items} постов из %{filename}. - domain_blocking_html: Вы собираетесь заменить ваш список блокировки доменов на %{total_items} доменов из %{filename}. - following_html: Вы собираетесь следить за %{total_items} аккаунтами из %{filename} и прекратить следить за всеми остальными. - lists_html: Вы собираетесь заменить ваши списки содержимым %{filename}. До %{total_items} аккаунты будут добавлены в новые списки. - muting_html: Вы собираетесь заменить список отключенных аккаунтов на %{total_items} аккаунтов из %{filename}. - preambles: - blocking_html: Вы собираетесь заблокировать до %{total_items} аккаунтов из %{filename}. - bookmarks_html: Вы собираетесь добавить до %{total_items} постов из %{filename} в свои закладки. - domain_blocking_html: Вы собираетесь блокировать до %{total_items} доменов от %{filename}. - following_html: Вы собираетесь следовать за %{total_items} аккаунтами из %{filename}. - lists_html: Вы собираетесь добавить до %{total_items} аккаунтов от %{filename} к вашим спискам. Новые списки будут созданы, если нет списка для добавления. - muting_html: Вы собираетесь отключить до %{total_items} аккаунтов из %{filename}. preface: Вы можете загрузить некоторые данные, например, списки людей, на которых Вы подписаны или которых блокируете, в Вашу учётную запись на этом узле из файлов, экспортированных с другого узла. recent_imports: Недавно импортированное states: @@ -1741,7 +1728,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..9ab62cea71e56b 100644 --- a/config/locales/sc.yml +++ b/config/locales/sc.yml @@ -30,17 +30,25 @@ sc: created_msg: As creadu una nota de moderatzione. destroyed_msg: As cantzelladu una nota de moderatzione. accounts: + add_email_domain_block: Bloca domìniu de posta eletrònica approve: Aprova approved_msg: Sa dimanda de registru de %{username} est istada aprovada are_you_sure: Seguru? avatar: Immàgine de profilu by_domain: Domìniu change_email: + changed_msg: Indiritzu eletrònicu de su contu modificadu! current_email: Indiritzu eletrònicu atuale label: Muda s'indiritzu eletrònicu new_email: Indiritzu eletrònicu nou submit: Muda s'indiritzu eletrònicu title: Muda s'indiritzu eletrònicu de %{username} + change_role: + changed_msg: Ruolu modificadu. + edit_roles: Gesti is ruolos de utente + label: Modifica su ruolu + no_role: Nissunu ruolu + title: Modifica su ruolu de %{username} confirm: Cunfirma confirmed: Cunfirmadu confirming: Cunfirmende @@ -91,6 +99,7 @@ sc: most_recent_ip: IP prus reghente no_account_selected: Perunu contu est istadu mudadu, dae chi non nd'as seletzionadu no_limits_imposed: Sena lìmites + no_role_assigned: Nissunu ruolu assignadu not_subscribed: Sena sutiscritzione pending: De revisionare perform_full_suspension: Suspèndidu @@ -108,12 +117,19 @@ sc: removed_header_msg: S'immàgine de intestatzione de %{username} est istada bogada resend_confirmation: already_confirmed: Custa persone est giai cunfirmada + send: Torra a imbiare su ligòngiu de cunfirmatzione + success: Ligòngiu de cunfirmatzione imbiadu. reset: Reseta reset_password: Reseta sa crae resubscribe: Torra a sutascrìere + role: Ruolu search: Chirca + search_same_email_domain: Àteras persones cun su pròpiu domìniu de posta search_same_ip: Àteras persones cun sa pròpiu IP security: Seguresa + security_measures: + only_password: Crae isceti + password_and_2fa: Crae e 2FA sensitive: Sensìbile sensitized: Marcadu comente sensìbile shared_inbox_url: URL de intrada cumpartzida @@ -129,6 +145,8 @@ sc: suspension_irreversible: Is datos de custu contu sunt istados cantzellados in manera irreversìbile. Podes bogare sa suspensione a su contu pro chi si potzat impreare, ma no at a recuperare datu perunu de is chi teniat in antis. suspension_reversible_hint_html: Su contu est istadu suspèndidu, e is datos ant a èssere cantzelladu de su totu su %{date}. Finas a tando, su contu si podet ripristinare sena efetu malu perunu. Si boles cantzellare totu is datos de su contu immediatamente ddu podes fàghere inoghe in bassu. title: Contos + unblock_email: Isbloca s'indiritzu de posta eletrònica + unblocked_email_msg: Posta eletrònica de %{username} isblocada unconfirmed_email: Posta eletrònica sena cunfirmare undo_sensitized: Boga sa marcadura comente sensìbile undo_silenced: Non pòngias a sa muda @@ -143,21 +161,31 @@ sc: whitelisted: Federatzione permìtida action_logs: action_types: + approve_user: Aprova s'utente assigned_to_self_report: Assigna s'informe + change_email_user: Muda s'indiritzu eletrònicu pro s'utente + change_role_user: Muda su ruolu de s'utente confirm_user: Cunfirma s'utente create_account_warning: Crea un'avisu create_announcement: Crea un'annùntziu + create_canonical_email_block: Crea unu blocu de posta eletrònica create_custom_emoji: Crea un'emoji personalizadu create_domain_allow: Crea unu domìniu permìtidu create_domain_block: Crea unu blocu de domìniu + create_email_domain_block: Crea unu blocu de domìniu de posta eletrònica create_ip_block: Crea una règula IP + create_unavailable_domain: Crea unu domìniu no a disponimentu + create_user_role: Crea unu ruolu demote_user: Degrada s'utente destroy_announcement: Cantzella s'annùntziu + destroy_canonical_email_block: Cantzella su blocu de posta eletrònica destroy_custom_emoji: Cantzella s'emoji personalizadu destroy_domain_allow: Cantzella su domìniu permìtidu destroy_domain_block: Cantzella su blocu de domìniu + destroy_email_domain_block: Cantzella su blocu de domìniu de posta eletrònica destroy_ip_block: Cantzella sa règula IP destroy_status: Cantzella s'istadu + destroy_unavailable_domain: Cantzella su domìniu no a disponimentu disable_2fa_user: Disativa 2FA disable_custom_emoji: Disativa s'emoji personalizadu disable_user: Disativa utente @@ -165,23 +193,33 @@ sc: enable_user: Ativa utente memorialize_account: Torra in unu contu de regordu promote_user: Promove utente + reject_user: Refuda s'utente remove_avatar_user: Cantzella immàgine de profilu reopen_report: Torra a abèrrere s'informe + resend_user: Torra a imbiare messàgiu eletrònicu de cunfirmatzione reset_password_user: Reseta sa crae resolve_report: Isorve s'informe sensitive_account: Marca is cuntenutos multimediales in su contu tuo comente sensìbiles silence_account: Pone custu contu a sa muda suspend_account: Suspende custu contu unassigned_report: Boga s'assignatzione de custu informe + unblock_email_account: Isbloca s'indiritzu de posta eletrònica unsensitive_account: Boga sa marcadura "sensìbiles" a is elementos multimediales in su contu tuo unsilence_account: Boga custu contu de is contos a sa muda unsuspend_account: Boga custu contu de is contos suspèndidos update_announcement: Atualiza s'annùntziu update_custom_emoji: Atualiza s'emoji personalizadu update_domain_block: Atualiza blocu de domìniu + update_ip_block: Atualiza sa règula IP + update_report: Atualiza s'informe update_status: Atualiza s'istadu + update_user_role: Atualiza su ruolu actions: + approve_user_html: "%{name} at aprovadu su registru de %{target}" assigned_to_self_report_html: "%{name} s'est auto-assignadu s'informe %{target}" + change_email_user_html: "%{name} at mudadu s'indiritzu de posta eletrònica de s'utente %{target}" + change_role_user_html: "%{name} at mudadu su ruolu de %{target}" + confirm_user_html: "%{name} at cunfirmadu s'indiritzu de posta eletrònica de s'utente %{target}" create_account_warning_html: "%{name} at imbiadu un'avisu a %{target}" create_announcement_html: "%{name} at creadu un'annùntziu nou %{target}" create_custom_emoji_html: "%{name} at carrigadu un'emoji nou %{target}" @@ -291,6 +329,8 @@ sc: confirm_suspension: cancel: Annulla confirm: Suspende + remove_all_data: Custu at a cantzellare totu su cuntenutu, elementos multimediales e datos de profilu pro is contos de custu domìniu dae su serbidore tuo. + stop_communication: Su serbidore tuo at a tzessare sa comunicatzione cun custos serbidores. title: Cunfirma su blocu de domìniu de %{domain} created_msg: Protzessende su blocu de domìniu destroyed_msg: Su blocu de domìniu est istadu iscontzadu @@ -361,9 +401,12 @@ sc: dashboard: instance_accounts_dimension: Contos prus sighidos instance_accounts_measure: contos sarvados + instance_languages_dimension: Limbas printzipales instance_reports_measure: informes a subra de àtere + instance_statuses_measure: publicatziones sarvadas delivery: all: Totus + unavailable: No a disponimentu delivery_available: Sa cunsigna est a disponimentu empty: Perunu domìniu agatadu. known_accounts: @@ -1080,7 +1123,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.ar.yml b/config/locales/simple_form.ar.yml index b591cdca5754eb..0a665fb784d415 100644 --- a/config/locales/simple_form.ar.yml +++ b/config/locales/simple_form.ar.yml @@ -3,7 +3,6 @@ ar: simple_form: hints: account: - attribution_domains_as_text: يحمي من الإسناد الزائف. discoverable: يمكن عرض مشاركاتك العامة وملفك الشخصي أو التوصية به في مختلف مناطق ماستدون ويمكن اقتراح ملفك الشخصي على مستخدمين آخرين. display_name: اسمك الكامل أو اسمك المرح. fields: صفحتك الرئيسية، ضمائرك، عمرك، أي شيء تريده. diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml index 5e3f1af89a5299..00617c4e3cc072 100644 --- a/config/locales/simple_form.ast.yml +++ b/config/locales/simple_form.ast.yml @@ -25,11 +25,11 @@ ast: password: Usa polo menos 8 caráuteres setting_aggregate_reblogs: Nun amuesa los artículos compartíos nuevos que yá se compartieren de recién (namás afeuta a los artículos compartíos d'agora) setting_always_send_emails: Los avisos nun se suelen unviar per corréu electrónicu si uses activamente Mastodon - setting_default_sensitive: El conteníu multimedia sensible anúbrese por defeutu y pue amosase al calcar nelli - setting_display_media_default: Anubrilu cuando se marque como sensible - setting_display_media_hide_all: Anubrilu siempres - setting_display_media_show_all: Amosalu siempres - setting_use_blurhash: Los dilíos básense nos colores del conteníu multimedia anubríu mas desenfonca los detalles + setting_default_sensitive: El conteníu multimedia sensible escuéndrese por defeutu y pue amosase al calcar nelli + setting_display_media_default: Escondelu cuando se marque como sensible + setting_display_media_hide_all: Escondelu siempre + setting_display_media_show_all: Amosalu siempre + setting_use_blurhash: Los dilíos básense nos colores del conteníu multimedia escondíu mas desenfonca los detalles featured_tag: name: 'Equí tán dalgunes de les etiquetes qu''usesti apocayá:' form_admin_settings: @@ -93,7 +93,7 @@ ast: expires_in: Caduca dempués de fields: Campos adicionales header: Semeya de la testera - irreversible: Escartar en cuentes d'anubrir + irreversible: Escartar en cuentes d'esconder locale: Llingua de la interfaz max_uses: Númberu máximu d'usos new_password: Contraseña nueva @@ -103,24 +103,24 @@ ast: phrase: Pallabra clave o fras setting_advanced_layout: Activar la interfaz web avanzada setting_aggregate_reblogs: Agrupar los artículos compartíos nes llinies de tiempu - setting_always_send_emails: Unviar siempres los avisos per corréu electrónicu + setting_always_send_emails: Unviar siempre los avisos per corréu electrónicu setting_auto_play_gif: Reproducir automáticamente los GIFs setting_boost_modal: Amosar el diálogu de confirmación enantes de compartir un artículu setting_default_language: Llingua de los artículos setting_default_privacy: Privacidá de los artículos - setting_default_sensitive: Marcar siempres tol conteníu como sensible + setting_default_sensitive: Marcar siempre tol conteníu como sensible setting_delete_modal: Amosar el diálogu de confirmación enantes de desaniciar un artículu setting_disable_hover_cards: Desactivar la previsualización de perfiles al pasar el mur penriba setting_disable_swiping: Desactivar el movimientu de desplazamientu setting_display_media: Conteníu multimedia - setting_expand_spoilers: Espander siempres los artículos marcaos con alvertencies de conteníu - setting_hide_network: Anubrir les cuentes que sigas y te sigan + setting_expand_spoilers: Espander siempre los artículos marcaos con alvertencies de conteníu + setting_hide_network: Esconder les cuentes que sigas y te sigan setting_reduce_motion: Amenorgar el movimientu de les animaciones setting_system_font_ui: Usar la fonte predeterminada del sistema setting_theme: Estilu del sitiu setting_trends: Amosar les tendencies de güei setting_unfollow_modal: Amosar el diálogu de confirmación enantes de dexar de siguir a daquién - setting_use_blurhash: Facer que'l conteníu multimedia anubríu tenga dilíos coloríos + setting_use_blurhash: Facer que'l conteníu multimedia escondíu tenga dilíos coloríos setting_use_pending_items: Mou lentu severity: Gravedá sign_in_token_attempt: Códigu de seguranza diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index a2cf8e4222543a..2690f071417beb 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -130,6 +130,7 @@ bg: name: Можете да смените само употребата на големи/малки букви, например, за да е по-четимо user: chosen_languages: Само публикации на отметнатите езици ще се показват в публичните часови оси + role: Ролята управлява какви позволения има потребителят. user_role: color: Цветът, използван за ролите в потребителския интерфейс, като RGB в шестнадесетичен формат highlighted: Това прави ролята обществено видима diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 7b651470bfe1b6..c628bebaad79fd 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -3,7 +3,6 @@ ca: simple_form: hints: account: - attribution_domains_as_text: Protegeix de falses atribucions. discoverable: El teu perfil i els teus tuts públics poden aparèixer o ser recomanats en diverses àreas de Mastodon i el teu perfil pot ser suggerit a altres usuaris. display_name: El teu nom complet o el teu nom divertit. fields: La teva pàgina d'inici, pronoms, edat, el que vulguis. @@ -144,7 +143,6 @@ ca: url: On els esdeveniments seran enviats labels: account: - attribution_domains_as_text: Permet només webs específics discoverable: Permet el perfil i el tuts en els algorismes de descobriment fields: name: Etiqueta diff --git a/config/locales/simple_form.cy.yml b/config/locales/simple_form.cy.yml index 56d1f873dcf110..dedd50504ba2db 100644 --- a/config/locales/simple_form.cy.yml +++ b/config/locales/simple_form.cy.yml @@ -3,7 +3,7 @@ cy: simple_form: hints: account: - attribution_domains_as_text: Yn amddiffyn rhag priodoliadau ffug. + attribution_domains_as_text: Un i bob llinell. Yn amddiffyn rhag cydnabyddiaethau ffug. discoverable: Mae'n bosibl y bydd eich postiadau cyhoeddus a'ch proffil yn cael sylw neu'n cael eu hargymell mewn gwahanol feysydd o Mastodon ac efallai y bydd eich proffil yn cael ei awgrymu i ddefnyddwyr eraill. display_name: Eich enw llawn neu'ch enw hwyl. fields: Eich tudalen cartref, rhagenwau, oed, neu unrhyw beth. @@ -144,7 +144,7 @@ cy: url: I ble bydd digwyddiadau'n cael eu hanfon labels: account: - attribution_domains_as_text: Dim ond yn caniatáu gwefannau penodol + attribution_domains_as_text: Gwefannau sy'n cael caniatâd i'ch cydnabod chi discoverable: Proffil nodwedd a phostiadau mewn algorithmau darganfod fields: name: Label diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index e7b8fe337a9701..25cf670ea917ac 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -3,7 +3,7 @@ da: simple_form: hints: account: - attribution_domains_as_text: Beskytter mod falske tilskrivninger. + attribution_domains_as_text: Ét pr. linje. Beskytter mod falske tilskrivninger. discoverable: Dine offentlige indlæg og profil kan blive fremhævet eller anbefalet i forskellige områder af Mastodon, og profilen kan blive foreslået til andre brugere. display_name: Dit fulde navn eller dit sjove navn. fields: Din hjemmeside, dine pronominer, din alder, eller hvad du har lyst til. @@ -144,7 +144,7 @@ da: url: Hvor begivenheder sendes til labels: account: - attribution_domains_as_text: Tillad kun bestemte websteder + attribution_domains_as_text: Websteder, man må krediteres af discoverable: Fremhæv profil og indlæg i opdagelsesalgoritmer fields: name: Etiket diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index f7e55f1a7bfb4b..08d5331151d903 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -3,7 +3,7 @@ de: simple_form: hints: account: - attribution_domains_as_text: Dadurch können falsche Zuschreibungen unterbunden werden. + attribution_domains_as_text: Eine Domain pro Zeile. Dadurch können falsche Zuschreibungen unterbunden werden. discoverable: Deine öffentlichen Beiträge und dein Profil können in verschiedenen Bereichen auf Mastodon angezeigt oder empfohlen werden und dein Profil kann anderen vorgeschlagen werden. display_name: Dein richtiger Name oder dein Fantasiename. fields: Deine Website, Pronomen, dein Alter – alles, was du möchtest. @@ -144,7 +144,7 @@ de: url: Wohin Ereignisse gesendet werden labels: account: - attribution_domains_as_text: Nur ausgewählte Websites zulassen + attribution_domains_as_text: Websites, die dich anerkennen dürfen discoverable: Profil und Beiträge in Suchalgorithmen berücksichtigen fields: name: Beschriftung diff --git a/config/locales/simple_form.el.yml b/config/locales/simple_form.el.yml index 88c1c0e184312d..9dcac5c16064e3 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -2,6 +2,14 @@ el: simple_form: hints: + account: + discoverable: Οι δημόσιες δημοσιεύσεις και το προφίλ σου μπορεί να εμφανίζονται ή να συνιστώνται σε διάφορους τομείς του Mastodon και το προφίλ σου μπορεί να προτείνεται σε άλλους χρήστες. + display_name: Το πλήρες ή το αστείο σου όνομα. + fields: Η αρχική σου σελίδα, αντωνυμίες, ηλικία, ό,τι θες. + indexable: Οι δημόσιες δημοσιεύσεις σου μπορεί να εμφανιστούν στα αποτελέσματα αναζήτησης στο Mastodon. Άτομα που έχουν αλληλεπιδράσει με τις δημοσιεύσεις σου μπορεί να είναι σε θέση να τις αναζητήσουν όπως και να 'χει. + note: 'Μπορείς να @επισημάνεις άλλα άτομα ή #ετικέτες.' + show_collections: Οι χρήστες θα είναι σε θέση να περιηγηθούν στα άτομα που ακολουθείς και στους ακόλουθούς σου. Άτομα που ακολουθείς θα βλέπουν ότι τους ακολουθείς όπως και να 'χει. + unlocked: Οι χρήστες θα είναι σε θέση να σε ακολουθήσουν χωρίς να ζητούν έγκριση. Κατάργησε την επιλογή αν θες να αξιολογείς τα αιτήματα ακολούθησης και να επιλέξεις αν θα αποδεχθείς ή απορρίψεις νέους ακόλουθους. account_alias: acct: Όρισε το username@domain του λογαριασμού από τον οποίο θέλεις να μετακινηθείς account_migration: @@ -31,12 +39,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 +77,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 +118,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 +139,17 @@ el: position: Ανώτεροι ρόλοι αποφασίζει την επίλυση συγκρούσεων σε ορισμένες περιπτώσεις. Ορισμένες ενέργειες μπορούν να εκτελεστούν μόνο σε ρόλους με χαμηλότερη προτεραιότητα webhook: events: Επιλέξτε συμβάντα για αποστολή + template: Σύνθεσε το δικό σου JSON payload χρησιμοποιώντας μεταβλητή παρεμβολή. Άφησε κενό για προεπιλογή JSON. url: Πού θα σταλούν τα γεγονότα labels: account: + discoverable: Παροχή προφίλ και αναρτήσεων σε αλγορίθμους ανακάλυψης fields: name: Περιγραφή value: Περιεχόμενο + indexable: Συμπερίληψη δημόσιων αναρτήσεων στα αποτελέσματα αναζήτησης + show_collections: Εμφάνιση ακολούθων και ακολουθουμένων στο προφίλ + unlocked: Αυτόματη αποδοχή νέων ακολούθων account_alias: acct: Διακριτικό του παλιού λογαριασμού account_migration: @@ -186,6 +211,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 +243,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 +297,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 +326,11 @@ el: position: Προτεραιότητα webhook: events: Ενεργοποιημένα συμβάντα + template: Πρότυπο payload url: Endpoint URL 'no': Όχι not_recommended: Δεν προτείνεται + overridden: Αντικαταστάθηκε recommended: Προτείνεται required: mark: "*" diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index b802fd532f5180..e20249e6bc22fb 100644 --- a/config/locales/simple_form.en-GB.yml +++ b/config/locales/simple_form.en-GB.yml @@ -3,7 +3,6 @@ en-GB: simple_form: hints: account: - attribution_domains_as_text: Protects from false attributions. discoverable: Your public posts and profile may be featured or recommended in various areas of Mastodon and your profile may be suggested to other users. display_name: Your full name or your fun name. fields: Your homepage, pronouns, age, anything you want. @@ -144,7 +143,6 @@ en-GB: url: Where events will be sent to labels: account: - attribution_domains_as_text: Only allow specific websites discoverable: Feature profile and posts in discovery algorithms fields: name: Label diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index d0ca617a319ee6..a9091bbf993202 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -3,7 +3,7 @@ en: simple_form: hints: account: - attribution_domains_as_text: Protects from false attributions. + attribution_domains_as_text: One per line. Protects from false attributions. discoverable: Your public posts and profile may be featured or recommended in various areas of Mastodon and your profile may be suggested to other users. display_name: Your full name or your fun name. fields: Your homepage, pronouns, age, anything you want. @@ -145,7 +145,7 @@ en: url: Where events will be sent to labels: account: - attribution_domains_as_text: Only allow specific websites + attribution_domains_as_text: Websites allowed to credit you discoverable: Feature profile and posts in discovery algorithms fields: name: Label diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index 053816ef881c06..cfb5578f5dba4e 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -75,9 +75,11 @@ eo: warn: Kaŝi la enhavon filtritan malantaŭ averto mencianta la nomon de la filtro form_admin_settings: activity_api_enabled: Nombroj de loke publikigitaj afiŝoj, aktivaj uzantoj kaj novaj registradoj en semajnaj siteloj + backups_retention_period: Uzantoj havas la kapablon generi arkivojn de siaj afiŝoj por elŝuti poste. Kiam estas agordita al pozitiva valoro, ĉi tiuj arkivoj estos aŭtomate forigitaj de via stokado post la specifita nombro da tagoj. 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 @@ -238,7 +242,9 @@ eo: backups_retention_period: Uzantoarkivretendauro bootstrap_timeline_accounts: Ĉiam rekomendi ĉi tiujn kontojn al novaj uzantoj closed_registrations_message: Kutima mesaĝo kiam registroj ne estas disponeblaj + content_cache_retention_period: Retenperiodo de fora enhavo 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-AR.yml b/config/locales/simple_form.es-AR.yml index d06d09761ad512..98254c5e994d45 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -3,7 +3,7 @@ es-AR: simple_form: hints: account: - attribution_domains_as_text: Protege de atribuciones falsas. + attribution_domains_as_text: Una por línea. Protege de falsas atribuciones. discoverable: Tu perfil y publicaciones pueden ser destacadas o recomendadas en varias áreas de Mastodon, y tu perfil puede ser sugerido a otros usuarios. display_name: Tu nombre completo o tu pseudónimo. fields: Tu sitio web, pronombres, edad, o lo que quieras. @@ -144,7 +144,7 @@ es-AR: url: Adónde serán enviados los eventos labels: account: - attribution_domains_as_text: Solo permitir sitios web específicos + attribution_domains_as_text: Sitios web autorizados a acreditarte discoverable: Destacar perfil y mensajes en algoritmos de descubrimiento fields: name: Nombre de campo diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index f2108828d5643b..9d7809ef3ab3ea 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -3,7 +3,7 @@ es-MX: simple_form: hints: account: - attribution_domains_as_text: Protege frente atribuciones fraudulentas. + attribution_domains_as_text: One per line. Protects from false attributions. discoverable: Tu perfil y las publicaciones públicas pueden ser destacadas o recomendadas en varias áreas de Mastodon y tu perfil puede ser sugerido a otros usuarios. display_name: Tu nombre completo o tu nick. fields: Tu página de inicio, pronombres, edad, todo lo que quieras. @@ -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 @@ -144,7 +144,7 @@ es-MX: url: Donde los eventos serán enviados labels: account: - attribution_domains_as_text: Solo permitir sitios web específicos + attribution_domains_as_text: Sitios web autorizados para acreditarte discoverable: Destacar el perfil y las publicaciones en el algoritmo de descubrimiento fields: name: Etiqueta @@ -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.es.yml b/config/locales/simple_form.es.yml index b22701aae7b0b8..8bc2c5f65c5e14 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -3,7 +3,7 @@ es: simple_form: hints: account: - attribution_domains_as_text: Protege frente atribuciones fraudulentas. + attribution_domains_as_text: Una por línea. Protege de falsas atribuciones. discoverable: Tu perfil y publicaciones públicas pueden ser destacadas o recomendadas en varias áreas de Mastodon y tu perfil puede ser sugerido a otros usuarios. display_name: Tu nombre completo o tu apodo. fields: Tu carta de presentación, pronombres, edad, lo que quieras. @@ -144,7 +144,7 @@ es: url: Donde los eventos serán enviados labels: account: - attribution_domains_as_text: Solo permitir sitios web específicos + attribution_domains_as_text: Sitios web autorizados a acreditarte discoverable: Destacar perfil y publicaciones en algoritmos de descubrimiento fields: name: Etiqueta diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml index 8d045cfcfe34df..4a9245682d4f05 100644 --- a/config/locales/simple_form.et.yml +++ b/config/locales/simple_form.et.yml @@ -3,7 +3,6 @@ et: simple_form: hints: account: - attribution_domains_as_text: Kaitseb valede omistuste eest. discoverable: Su profiili ja avalikke postitusi võidakse Mastodoni erinevates piirkondades esile tõsta või soovitada ning su profiili soovitada teistele kasutajatele. display_name: Su täisnimi või naljanimi. fields: Su koduleht, sugu, vanus. Mistahes, mida soovid. @@ -144,7 +143,6 @@ et: url: Kuhu sündmused saadetakse labels: account: - attribution_domains_as_text: Luba vaid kindlad veebilehed discoverable: Tõsta postitused ja profiil avastamise algoritmides esile fields: name: Nimetus diff --git a/config/locales/simple_form.fa.yml b/config/locales/simple_form.fa.yml index bbb0523b174738..6121467768445f 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -39,12 +39,14 @@ fa: text: فقط یک بار می‌توانید برای اخطار درخواست تجدیدنظر کنید defaults: autofollow: کسانی که از راه دعوت‌نامه عضو می‌شوند به طور خودکار پیگیر شما خواهند شد + avatar: یکی از قالب‌های WEBP، PNG، GIF یا JPG. بیشترین اندازه %{size}. تصویر به اندازهٔ %{dimensions} پیکسل تبدیل خواهد شد bot: این حساب بیشتر به طور خودکار فعالیت می‌کند و نظارت پیوسته‌ای روی آن وجود ندارد context: یک یا چند زمینه که پالایه باید در آن‌ها اعمال شود current_password: به دلایل امنیتی لطفاً گذرواژه این حساب را وارد کنید current_username: برای تأیید، لطفاً نام کاربری حساب فعلی را وارد کنید digest: تنها وقتی فرستاده می‌شود که مدتی طولانی فعالیتی نداشته باشید و در این مدت برای شما پیغام خصوصی‌ای نوشته شده باشد email: به شما ایمیل تأییدی فرستاده خواهد شد + header: یکی از قالب‌های WEBP، PNG، GIF یا JPG. بیشترین اندازه %{size}. تصویر به اندازهٔ %{dimensions} پیکسل تبدیل خواهد شد inbox_url: نشانی صفحهٔ اصلی رله‌ای را که می‌خواهید به کار ببرید کپی کنید irreversible: فرسته‌های پالوده به طور برگشت‌ناپذیری ناپدید می‌شوند، حتا اگر بعدها پالایه برداشته شود locale: زبان واسط کاربری، رایانامه‌ها و آگاهی‌های ارسالی diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 5c85367dbb7906..8c914295fee3d4 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -3,7 +3,7 @@ fi: simple_form: hints: account: - attribution_domains_as_text: Suojaa vääriltä tunnustuksilta. + attribution_domains_as_text: Yksi riviä kohti. Suojaa vääriltä tunnustuksilta. discoverable: Julkisia julkaisujasi ja profiiliasi voidaan pitää esillä tai suositella Mastodonin eri alueilla ja profiiliasi voidaan ehdottaa toisille käyttäjille. display_name: Koko nimesi tai lempinimesi. fields: Verkkosivustosi, pronominisi, ikäsi ja mitä ikinä haluatkaan ilmoittaa. @@ -144,7 +144,7 @@ fi: url: Mihin tapahtumat lähetetään labels: account: - attribution_domains_as_text: Salli vain tietyt verkkosivustot + attribution_domains_as_text: Verkkosivustot, jotka voivat antaa sinulle tunnustusta discoverable: Pidä profiiliasi ja julkaisujasi esillä löytämisalgoritmeissa fields: name: Nimike diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index afcd3b39accfe2..e45183df99c1a8 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -3,7 +3,7 @@ fo: simple_form: hints: account: - attribution_domains_as_text: Verjir fyri følskum ískoytum. + attribution_domains_as_text: Eitt á hvørja reglu. Tað verjir fyri skeivum tilsipingum. discoverable: Tínir almennu postar og tín vangi kunnu vera drigin fram og viðmæld ymsa staðni í Mastodon og vangin hjá tær kann vera viðmæltur øðrum brúkarum. display_name: Títt fulla navn og títt stuttliga navn. fields: Heimasíðan hjá tær, fornøvn, aldur ella hvat tú vil. @@ -144,7 +144,7 @@ fo: url: Hvar hendingar verða sendar til labels: account: - attribution_domains_as_text: Loyv einans ávísum heimasíðum + attribution_domains_as_text: Heimasíður, sum hava loyvi at sipa til tín discoverable: Framheva vanga og postar í uppdagingar-algoritmum fields: name: Spjaldur diff --git a/config/locales/simple_form.fr-CA.yml b/config/locales/simple_form.fr-CA.yml index 90a268f411bd0c..d2ce30ec8e3df8 100644 --- a/config/locales/simple_form.fr-CA.yml +++ b/config/locales/simple_form.fr-CA.yml @@ -3,7 +3,6 @@ fr-CA: simple_form: hints: account: - attribution_domains_as_text: Protège contre les fausses attributions. discoverable: Vos messages publics et votre profil peuvent être mis en avant ou recommandés dans diverses parties de Mastodon et votre profil peut être suggéré à d’autres utilisateurs. display_name: Votre nom complet ou votre nom cool. fields: Votre page d'accueil, pronoms, âge, tout ce que vous voulez. @@ -144,7 +143,6 @@ fr-CA: url: Là où les événements seront envoyés labels: account: - attribution_domains_as_text: Autoriser uniquement des sites Web spécifiques discoverable: Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages fields: name: Étiquette diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml index 370f5c1e46e058..626032600aaacc 100644 --- a/config/locales/simple_form.fr.yml +++ b/config/locales/simple_form.fr.yml @@ -3,7 +3,6 @@ fr: simple_form: hints: account: - attribution_domains_as_text: Protège contre les fausses attributions. discoverable: Vos messages publics et votre profil peuvent être mis en avant ou recommandés dans diverses parties de Mastodon et votre profil peut être suggéré à d’autres utilisateurs. display_name: Votre nom complet ou votre nom rigolo. fields: Votre page personnelle, vos pronoms, votre âge, ce que vous voulez. @@ -144,7 +143,6 @@ fr: url: Là où les événements seront envoyés labels: account: - attribution_domains_as_text: Autoriser uniquement des sites Web spécifiques discoverable: Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages fields: name: Étiquette diff --git a/config/locales/simple_form.fy.yml b/config/locales/simple_form.fy.yml index e7deca9460c98f..8a753dcc898d51 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -130,6 +130,7 @@ fy: name: Jo kinne elk wurd mei in haadletter begjinne, om sa bygelyks de tekst mear lêsber te meitsjen user: chosen_languages: Allinnich berjochten yn de selektearre talen wurde op de iepenbiere tiidline toand + role: De rol bepaalt hokker rjochten in brûker hat. user_role: color: Kleur dy’t brûkt wurdt foar de rol yn de UI, as RGB yn heksadesimaal formaat highlighted: Dit makket de rol iepenbier sichtber diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml index 772f996ca6c92c..7c125b165a0cd4 100644 --- a/config/locales/simple_form.ga.yml +++ b/config/locales/simple_form.ga.yml @@ -3,7 +3,6 @@ ga: simple_form: hints: account: - attribution_domains_as_text: Cosnaíonn sé ó sannadh bréagach. discoverable: Seans go mbeidh do phostálacha poiblí agus do phróifíl le feiceáil nó molta i réimsí éagsúla de Mastodon agus is féidir do phróifíl a mholadh d’úsáideoirí eile. display_name: D'ainm iomlán nó d'ainm spraoi. fields: Do leathanach baile, forainmneacha, aois, rud ar bith is mian leat. @@ -144,7 +143,6 @@ ga: url: An áit a seolfar imeachtaí chuig labels: account: - attribution_domains_as_text: Ná ceadaigh ach láithreáin ghréasáin ar leith discoverable: Próifíl gné agus postálacha in halgartaim fionnachtana fields: name: Lipéad diff --git a/config/locales/simple_form.gd.yml b/config/locales/simple_form.gd.yml index de585c7a218ac5..9b6c156de79c94 100644 --- a/config/locales/simple_form.gd.yml +++ b/config/locales/simple_form.gd.yml @@ -3,7 +3,6 @@ gd: simple_form: hints: account: - attribution_domains_as_text: Dìonadh seo o bhuaidh-aithrisean cearra. discoverable: Dh’fhaoidte gun dèid na postaichean poblach ’s a’ phròifil agad a bhrosnachadh no a mholadh ann an caochladh roinnean de Mhastodon agus gun dèid a’ phròifil agad a mholadh do chàch. display_name: D’ ainm slàn no spòrsail. fields: An duilleag-dhachaigh agad, roimhearan, aois, rud sam bith a thogras tu. @@ -144,7 +143,6 @@ gd: url: Far an dèid na tachartasan a chur labels: account: - attribution_domains_as_text: Na ceadaich ach làraichean-lìnn sònraichte discoverable: Brosnaich a’ phròifil is postaichean agad sna h-algairimean rùrachaidh fields: name: Leubail diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index cddeae5cee5dd7..b29a071e800519 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -3,7 +3,7 @@ gl: simple_form: hints: account: - attribution_domains_as_text: Protéxete de falsas atribucións. + attribution_domains_as_text: Un por liña. Protéxete das atribucións falsas. discoverable: As túas publicacións públicas e perfil poden mostrarse ou recomendarse en varias zonas de Mastodon e o teu perfil ser suxerido a outras usuarias. display_name: O teu nome completo ou un nome divertido. fields: Páxina web, pronome, idade, o que ti queiras. @@ -144,7 +144,7 @@ gl: url: A onde se enviarán os eventos labels: account: - attribution_domains_as_text: Permitir só os sitios web indicados + attribution_domains_as_text: Sitios web que poden acreditarte discoverable: Perfil destacado e publicacións nos algoritmos de descubrimento fields: name: Etiqueta diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml index 1feebb0d69ae11..d8d6af5e99ab60 100644 --- a/config/locales/simple_form.he.yml +++ b/config/locales/simple_form.he.yml @@ -3,7 +3,7 @@ he: simple_form: hints: account: - attribution_domains_as_text: הגנה מייחוסים שקריים. + attribution_domains_as_text: אחד בכל שורה. יגן מפני יחוס מטעה. discoverable: הפוסטים והפרופיל שלך עשויים להיות מוצגים או מומלצים באזורים שונים באתר וייתכן שהפרופיל שלך יוצע למשתמשים אחרים. display_name: שמך המלא או שם הכיף שלך. fields: עמוד הבית שלך, לשון הפנייה, גיל, וכל מידע אחר לפי העדפתך האישית. @@ -144,7 +144,7 @@ he: url: היעד שאליו יישלחו אירועים labels: account: - attribution_domains_as_text: רק אתרים מסויימים יאושרו + attribution_domains_as_text: אתרים המורשים לייחס אליך מאמרים discoverable: הצג משתמש ופוסטים בעמוד התגליות fields: name: תווית diff --git a/config/locales/simple_form.hu.yml b/config/locales/simple_form.hu.yml index 383bdd076054b7..545fd4a8e91fd0 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -3,7 +3,6 @@ hu: simple_form: hints: account: - attribution_domains_as_text: Megvéd a hamis forrásmegjelölésektől. discoverable: A nyilvános bejegyzéseid és a profilod kiemelhető vagy ajánlható a Mastodon különböző területein, a profilod más felhasználóknak is javasolható. display_name: Teljes neved vagy vicces neved. fields: Weboldalad, megszólításaid, korod, bármi, amit szeretnél. @@ -144,7 +143,6 @@ hu: url: Ahová az eseményket küldjük labels: account: - attribution_domains_as_text: Csak meghatározott weboldalak engedélyezése discoverable: Profil és bejegyzések szerepeltetése a felfedezési algoritmusokban fields: name: Címke diff --git a/config/locales/simple_form.ia.yml b/config/locales/simple_form.ia.yml index dc5aad57ae3957..85fa74f1edd960 100644 --- a/config/locales/simple_form.ia.yml +++ b/config/locales/simple_form.ia.yml @@ -142,7 +142,6 @@ ia: url: Ubi le eventos essera inviate labels: account: - attribution_domains_as_text: Solmente permitter sitos web specific discoverable: Evidentiar le profilo e messages in le algorithmos de discoperta fields: name: Etiquetta diff --git a/config/locales/simple_form.io.yml b/config/locales/simple_form.io.yml index fe8243b0e9fb57..1df50081951292 100644 --- a/config/locales/simple_form.io.yml +++ b/config/locales/simple_form.io.yml @@ -39,12 +39,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 +77,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 +118,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 +130,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,6 +139,7 @@ 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: @@ -201,6 +211,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 +243,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 +305,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 +314,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 +326,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.is.yml b/config/locales/simple_form.is.yml index 6f3a4fe8a561ed..40ae267a064186 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -3,7 +3,7 @@ is: simple_form: hints: account: - attribution_domains_as_text: Ver fyrir fölskum tilvísunum í höfunda. + attribution_domains_as_text: Eitt á hverja línu. Ver fyrir röngum tilvísunum. discoverable: Opinberar færslur og notandasnið þitt geta birst eða verið mælt með á hinum ýmsu svæðum í Mastodon auk þess sem hægt er að mæla með þér við aðra notendur. display_name: Fullt nafn þitt eða eitthvað til gamans. fields: Heimasíðan þín, fornöfn, aldur eða eitthvað sem þú vilt koma á framfæri. @@ -144,7 +144,7 @@ is: url: Hvert atburðir verða sendir labels: account: - attribution_domains_as_text: Einungis leyfa tiltekin vefsvæði + attribution_domains_as_text: Vefsvæði sem mega vitna í þig discoverable: Hafa notandasnið og færslur með í reikniritum leitar fields: name: Skýring diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index 7ed4c0d004c6b6..c36fce36f74930 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -3,7 +3,7 @@ it: simple_form: hints: account: - attribution_domains_as_text: Protegge da false attribuzioni. + attribution_domains_as_text: Uno per riga. Protegge da false attribuzioni. discoverable: I tuoi post pubblici e il tuo profilo potrebbero essere presenti o consigliati in varie aree di Mastodon e il tuo profilo potrebbe essere suggerito ad altri utenti. display_name: Il tuo nome completo o il tuo soprannome. fields: La tua homepage, i pronomi, l'età, tutto quello che vuoi. @@ -144,7 +144,7 @@ it: url: Dove gli eventi saranno inviati labels: account: - attribution_domains_as_text: Consenti solo siti web specifici + attribution_domains_as_text: Siti web autorizzati ad accreditarti discoverable: Include il profilo e i post negli algoritmi di scoperta fields: name: Etichetta diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 2c1bd6a08404ad..6ce16b64480153 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -130,6 +130,7 @@ ja: name: 視認性向上などのためにアルファベット大文字小文字の変更のみ行うことができます user: chosen_languages: 選択すると、選択した言語の投稿のみが公開タイムラインに表示されるようになります + role: そのロールは、ユーザーが持つ権限を制御します。 user_role: color: UI 全体でロールの表示に使用される色(16進数RGB形式) highlighted: これによりロールが公開されます。 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.ko.yml b/config/locales/simple_form.ko.yml index a649b4ec5a90df..fee07fa5e0ff66 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -3,7 +3,6 @@ ko: simple_form: hints: account: - attribution_domains_as_text: 가짜 기여로부터 보호합니다. discoverable: 내 공개 게시물과 프로필이 마스토돈의 다양한 추천 기능에 나타날 수 있고 프로필이 다른 사용자에게 제안될 수 있습니다 display_name: 진짜 이름 또는 재미난 이름. fields: 홈페이지, 호칭, 나이, 뭐든지 적고 싶은 것들. @@ -144,7 +143,6 @@ ko: url: 이벤트가 어디로 전송될 지 labels: account: - attribution_domains_as_text: 특정 웹사이트만 허용하기 discoverable: 발견하기 알고리즘에 프로필과 게시물을 추천하기 fields: name: 라벨 diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index 2a381534ba5c2a..de37005312d456 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 @@ -306,6 +307,7 @@ lad: listable: Permite ke esta etiketa apareska en bushkedas i sujestyones name: Etiketa trendable: Permite ke esta etiketa apareska en trendes + usable: Permite ke publikasyones uzen esta etiketa lokalmente user: role: Rolo time_zone: Zona de tiempo diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index 5d3a02993bb319..de3dd2f31c64e0 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -3,7 +3,7 @@ lt: simple_form: hints: account: - attribution_domains_as_text: Apsaugo nuo klaidingų atributų. + attribution_domains_as_text: Po vieną eilutėje. Apsaugo nuo klaidingų atributų. discoverable: Tavo vieši įrašai ir profilis gali būti rodomi arba rekomenduojami įvairiose Mastodon vietose, o profilis gali būti siūlomas kitiems naudotojams. display_name: Tavo pilnas vardas arba smagus vardas. fields: Tavo pagrindinis puslapis, įvardžiai, amžius, bet kas, ko tik nori. @@ -107,7 +107,7 @@ lt: role: Vaidmuo valdo, kokius leidimus naudotojas turi. labels: account: - attribution_domains_as_text: Leisti tik konkrečias svetaines + attribution_domains_as_text: Svetainės, kuriuose leidžiama jus nurodyti discoverable: Rekomenduoti profilį ir įrašus į atradimo algoritmus indexable: Įtraukti viešus įrašus į paieškos rezultatus show_collections: Rodyti sekimus ir sekėjus profilyje diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml index ed27e08bc33466..4303ba9b41458a 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -3,7 +3,6 @@ lv: simple_form: hints: account: - attribution_domains_as_text: Aizsargā no nepatiesa attiecinājuma. discoverable: Tavas publiskās ziņas un profils var tikt piedāvāti vai ieteikti dažādās Mastodon vietās, un tavs profils var tikt ieteikts citiem lietotājiem. display_name: Tavs pilnais vārds vai tavs joku vārds. fields: Tava mājas lapa, vietniekvārdi, vecums, viss, ko vēlies. @@ -82,9 +81,11 @@ 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ē. + media_cache_retention_period: Informācijas nesēju datnes no ierakstiem, kurus ir veikuši attālie lietotāji, tiek kešoti šajā serverī. Kad ir iestatīta apstiprinoša vērtība, informācijas nesēji tiks izdzēsti pēc norādītā dienu skaita. Ja informācijas nesēju dati tiks pieprasīti pēc tam, kad tie tika izdzēsti, tie tiks atkārtoti lejupielādēti, ja avota saturs joprojām būs pieejams. Saišu priekšskatījuma karšu vaicājumu biežuma ierobežojumu dēļ ir ieteicams iestatīt šo vērtību vismaz 14 dienas vai saišu priekšskatījuma kartes netiks atjauninātas pēc pieprasījuma pirms tā laika. peers_api_enabled: Domēna vārdu saraksts, ar kuriem šis serveris ir saskāries fediversā. Šeit nav iekļauti dati par to, vai tu veic federāciju ar noteiktu serveri, tikai tavs serveris par to zina. To izmanto dienesti, kas apkopo statistiku par federāciju vispārīgā nozīmē. profile_directory: Profilu direktorijā ir uzskaitīti visi lietotāji, kuri ir izvēlējušies būt atklājami. require_invite_text: 'Ja pierakstīšanai nepieciešama manuāla apstiprināšana, izdari tā, lai teksta: “Kāpēc vēlaties pievienoties?” ievade ir obligāta, nevis opcionāla' @@ -142,7 +143,6 @@ lv: url: Kur notikumi tiks nosūtīti labels: account: - attribution_domains_as_text: Ļaut tikai noteiktas tīmekļvietnes discoverable: Funkcijas profils un ziņas atklāšanas algoritmos fields: name: Marķējums diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 7f8aaa01d6fd05..afd3624785a5aa 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -3,7 +3,7 @@ nl: simple_form: hints: account: - attribution_domains_as_text: Beschermt tegen onjuiste attributies. + attribution_domains_as_text: Eén per regel. Beschermt tegen valse attribueringen. discoverable: Jouw openbare berichten kunnen worden uitgelicht op verschillende plekken binnen Mastodon en jouw account kan worden aanbevolen aan andere gebruikers. display_name: Jouw volledige naam of een leuke bijnaam. fields: Jouw website, persoonlijke voornaamwoorden, leeftijd, alles wat je maar kwijt wilt. @@ -144,7 +144,7 @@ nl: url: Waar gebeurtenissen naartoe worden verzonden labels: account: - attribution_domains_as_text: Alleen bepaalde websites toestaan + attribution_domains_as_text: Websites doe jou credit mogen geven discoverable: Jouw account en berichten laten uitlichten door Mastodon fields: name: Label @@ -295,7 +295,7 @@ nl: favourite: Wanneer iemand jouw bericht als favoriet markeert follow: Wanneer iemand jou is gaan volgen follow_request: Wanneer iemand jou wil volgen - mention: Wanneer iemand jou heeft vermeld + mention: Je bent door iemand vermeld pending_account: Wanneer een nieuw account moet worden beoordeeld reblog: Wanneer iemand jouw bericht heeft geboost report: Nieuwe rapportage is ingediend diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index ddd5ed8995d541..f963d3bc72d196 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -3,7 +3,6 @@ nn: simple_form: hints: account: - attribution_domains_as_text: Vernar mot falske krediteringar. discoverable: Dei offentlege innlegga dine og profilen din kan dukka opp i tilrådingar på ulike stader på Mastodon, og profilen din kan bli føreslegen for andre folk. display_name: Ditt fulle namn eller ditt tøysenamn. fields: Heimesida di, pronomen, alder, eller kva du måtte ynskje. @@ -137,14 +136,13 @@ nn: highlighted: Dette gjer rolla synleg offentleg name: Offentleg namn på rolla, dersom rolla skal visast som eit emblem permissions_as_keys: Brukarar med denne rolla vil ha tilgang til... - position: Høgare rolle avgjer konfliktløysing i visse situasjonar. Visse handlingar kan kun utførast på rollar med lågare prioritet + position: Høgare rolle avgjer konfliktløysing i visse situasjonar. Visse handlingar kan berre utførast på roller med lågare prioritet webhook: events: Vel hendingar å senda template: Skriv di eiga JSON nyttelast ved å bruka variabel interpolering. La stå tom for standard JSON. url: Kvar hendingar skal sendast labels: account: - attribution_domains_as_text: Tillat berre visse nettstader discoverable: Ta med profilen og innlegga i oppdagingsalgoritmar fields: name: Merkelapp diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index bb404e56c93320..c5ff55c15de10f 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -3,7 +3,7 @@ pl: simple_form: hints: account: - attribution_domains_as_text: Chroni przed fałszywym przypisaniem wpisów. + attribution_domains_as_text: Jedna na linię. Chroni przed fałszywym przypisaniem wpisów. discoverable: Twój profil i publiczne wpisy mogą być promowane lub polecane na Mastodonie i twój profil może być sugerowany innym użytkownikom. display_name: Twoje imię lub pseudonim. fields: Co ci się tylko podoba – twoja strona domowa, zaimki, wiek… @@ -144,7 +144,7 @@ pl: url: Dokąd będą wysłane zdarzenia labels: account: - attribution_domains_as_text: Zezwól tylko na konkretne strony + attribution_domains_as_text: Strony które mogą ci przypisywać autorstwo. discoverable: Udostępniaj profil i wpisy funkcjom odkrywania fields: name: Nazwa diff --git a/config/locales/simple_form.pt-BR.yml b/config/locales/simple_form.pt-BR.yml index 96bc219e8eb24a..16d7cfe4458bf9 100644 --- a/config/locales/simple_form.pt-BR.yml +++ b/config/locales/simple_form.pt-BR.yml @@ -3,7 +3,7 @@ pt-BR: simple_form: hints: account: - attribution_domains_as_text: Protege de atribuições falsas. + attribution_domains_as_text: Um por linha. Protege de falsas atribuições. discoverable: Suas publicações e perfil públicos podem ser destaques ou recomendados em várias áreas de Mastodon, e seu perfil pode ser sugerido a outros usuários. display_name: Seu nome completo ou apelido. fields: Sua página inicial, pronomes, idade ou qualquer coisa que quiser. @@ -144,7 +144,7 @@ pt-BR: url: Aonde os eventos serão enviados labels: account: - attribution_domains_as_text: Permitir apenas sites específicos + attribution_domains_as_text: Sites permitidos para credenciar você discoverable: Destacar perfil e publicações nos algoritmos de descoberta fields: name: Rótulo diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index 3ff746451b3279..1bdffc6f1d5634 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -3,7 +3,6 @@ ru: simple_form: hints: account: - attribution_domains_as_text: Защищает от ложных атрибуций. discoverable: Ваши публичные сообщения и профиль могут быть показаны или рекомендованы в различных разделах Mastodon, и ваш профиль может быть предложен другим пользователям. display_name: Ваше полное имя или псевдоним. fields: Ваша домашняя страница, местоимения, возраст - все, что угодно. @@ -144,7 +143,6 @@ ru: url: Куда события будут отправляться labels: account: - attribution_domains_as_text: Разрешить только определенные сайты discoverable: Профиль и сообщения в алгоритмах обнаружения fields: name: Пункт 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.sq.yml b/config/locales/simple_form.sq.yml index 169f4a02dee4c5..3d865572824706 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -3,7 +3,6 @@ sq: simple_form: hints: account: - attribution_domains_as_text: Mbron nga atribuime të rreme. discoverable: Postimet dhe profili juaj publik mund të shfaqen, ose rekomandohen në zona të ndryshme të Mastodon-it dhe profili juaj mund të sugjerohet përdoruesve të tjerë. display_name: Emri juaj i plotë, ose emri juaj lojcak. fields: Faqja juaj hyrëse, përemra, moshë, ç’të keni qejf. @@ -144,7 +143,6 @@ sq: url: Ku do të dërgohen aktet labels: account: - attribution_domains_as_text: Lejo vetëm sajte specifikë discoverable: Profilin dhe postimet bëji objekt të algoritmeve të zbulimit fields: name: Etiketë diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index 1ecd672a97a14c..8bd782c1405d32 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -3,7 +3,6 @@ th: simple_form: hints: account: - attribution_domains_as_text: ปกป้องจากการระบุแหล่งที่มาที่ผิด discoverable: อาจแสดงหรือแนะนำโพสต์และโปรไฟล์สาธารณะของคุณในพื้นที่ต่าง ๆ ของ Mastodon และอาจเสนอแนะโปรไฟล์ของคุณให้กับผู้ใช้อื่น ๆ display_name: ชื่อเต็มของคุณหรือชื่อแบบสนุกสนานของคุณ fields: หน้าแรก, สรรพนาม, อายุของคุณ สิ่งใดก็ตามที่คุณต้องการ @@ -144,7 +143,6 @@ th: url: ที่ซึ่งจะส่งเหตุการณ์ไปยัง labels: account: - attribution_domains_as_text: อนุญาตเฉพาะเว็บไซต์ที่เฉพาะเจาะจงเท่านั้น discoverable: แสดงโปรไฟล์และโพสต์ในอัลกอริทึมการค้นพบ fields: name: ป้ายชื่อ diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index d90b97bf9b2e61..5aed566626d6d1 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -3,7 +3,7 @@ tr: simple_form: hints: account: - attribution_domains_as_text: Sahte atıflardan korur. + attribution_domains_as_text: Her satırda bir tanesi. Sahte atıflardan korur. discoverable: Herkese açık gönderileriniz ve profiliniz Mastodon'un çeşitli kısımlarında öne çıkarılabilir veya önerilebilir ve profiliniz başka kullanıcılara önerilebilir. display_name: Tam adınız veya kullanıcı adınız. fields: Ana sayfanız, zamirleriniz, yaşınız, istediğiniz herhangi bir şey. @@ -144,7 +144,7 @@ tr: url: Olayların gönderileceği yer labels: account: - attribution_domains_as_text: Yalnızca belirli websitelerine izin ver + attribution_domains_as_text: Size atıf verebilecek websiteleri discoverable: Profil ve gönderileri keşif algoritmalarında kullan fields: name: Etiket diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index b584a6cada12af..e2a1562b53499e 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -3,7 +3,6 @@ uk: simple_form: hints: account: - attribution_domains_as_text: Захищає від фальшивих атрибутів. discoverable: Ваші дописи та профіль можуть бути рекомендовані в різних частинах Mastodon і ваш профіль може бути запропонований іншим користувачам. display_name: Ваше повне ім'я або ваш псевдонім. fields: Ваша домашня сторінка, займенники, вік, все, що вам заманеться. @@ -144,7 +143,6 @@ uk: url: Куди надсилатимуться події labels: account: - attribution_domains_as_text: Дозволити лише на певних вебсайтах discoverable: Функції профілю та дописів у алгоритмах виявлення fields: name: Мітка diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index eab025c6655466..2b1d84f595ec58 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -3,13 +3,13 @@ vi: simple_form: 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. + attribution_domains_as_text: Mỗi cái một dòng. Bảo vệ khỏi những sự gán ghép sai. + 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,8 +42,8 @@ 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 - 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 + context: Chọn những nơi mà bộ lọc sẽ áp dụng + current_password: Để 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) email: Bạn sẽ được gửi một email xác minh @@ -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. @@ -144,7 +144,7 @@ vi: url: Nơi những sự kiện được gửi đến labels: account: - attribution_domains_as_text: Chỉ cho phép các website đặc biệt + attribution_domains_as_text: Các trang web được ghi nhận cho bạn discoverable: Cho phép khám phá hồ sơ fields: name: Nhãn @@ -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 @@ -290,7 +290,7 @@ vi: sign_up_requires_approval: Giới hạn đăng ký severity: Mức độ notification_emails: - appeal: Ai đó kháng cáo kiểm duyệt + appeal: Ai đó khiếu nại kiểm duyệt digest: Gửi email định kỳ favourite: Ai đó thích tút của bạn follow: Ai đó theo dõi bạ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/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 419cb99abb5974..6586c372efd238 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -3,7 +3,7 @@ zh-CN: simple_form: hints: account: - attribution_domains_as_text: 保护作品免受虚假署名。 + attribution_domains_as_text: 每行一个域名。这样就可以保护作品免受虚假署名。 discoverable: 您的公开嘟文和个人资料可能会在 Mastodon 的多个位置展示,您的个人资料可能会被推荐给其他用户。 display_name: 你的全名或昵称。 fields: 你的主页、人称代词、年龄,以及任何你想要添加的内容。 @@ -144,7 +144,7 @@ zh-CN: url: 事件将被发往的目的地 labels: account: - attribution_domains_as_text: 仅允许特定网站 + attribution_domains_as_text: 授权展示你的署名的网站 discoverable: 在发现算法中展示你的个人资料和嘟文 fields: name: 标签 diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index a5bc6836348ef1..289a24f122c130 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -3,7 +3,7 @@ zh-TW: simple_form: hints: account: - attribution_domains_as_text: 偽造署名保護。 + attribution_domains_as_text: 每行一個。以保護偽造署名。 discoverable: 公開嘟文及個人檔案可能於各 Mastodon 功能中被推薦,並且您的個人檔案可能被推薦至其他使用者。 display_name: 完整名稱或暱稱。 fields: 烘培雞、自我認同代稱、年齡,及任何您想分享的。 @@ -144,7 +144,7 @@ zh-TW: url: 事件會被傳送至何處 labels: account: - attribution_domains_as_text: 僅允許特定網站 + attribution_domains_as_text: 允許對您予與信譽之網站 discoverable: 於探索演算法中推薦個人檔案及嘟文 fields: name: 標籤 diff --git a/config/locales/sk.yml b/config/locales/sk.yml index d7eacb68509796..399ecc061af0db 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -8,10 +8,10 @@ sk: title: Ohľadom accounts: followers: - few: Sledovateľov + few: Sledujúcich many: Sledovateľov one: Sledujúci - other: Sledovatelia + other: Sledujúci following: Nasledujem instance_actor_flash: Toto konto je virtuálny aktér, ktorý predstavuje samotný server, a nie konkrétneho používateľa. Používa sa na účely federácie a nemal by byť pozastavený. last_active: naposledy aktívny @@ -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: @@ -1165,8 +1167,8 @@ sk: dormant: Spiace 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í + followers: Sledovatelia + 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..e9c06bcaa65674 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -1398,20 +1398,6 @@ sl: merge_long: Ohrani obstoječe zapise in dodaj nove overwrite: Prepiši overwrite_long: Zamenjaj trenutne zapise z novimi - overwrite_preambles: - blocking_html: Svoj seznam blokiranih računov boste nadomestili z največ %{total_items} računi iz %{filename}. - bookmarks_html: Svoje zaznamke boste nadomestili z največ %{total_items} objavami iz %{filename}. - domain_blocking_html: Svoj seznam blokiranih domen boste nadomestili z največ %{total_items} domenami iz %{filename}. - following_html: "Začeli boste slediti največ %{total_items} računom iz %{filename} in prenehali slediti vsem ostalim." - lists_html: Svoje sezname boste nadomestili z vsebino datoteke %{filename}. Največ %{total_items} računov bo dodanih na nove sezname. - muting_html: Svoj seznam utišanih računov boste nadomestili z največ %{total_items} računi iz %{filename}. - preambles: - blocking_html: "Blokirali boste največ %{total_items} računov iz %{filename}." - bookmarks_html: "Med zaznamke boste dodali boste največ %{total_items} objav iz %{filename}." - domain_blocking_html: "Blokirali boste največ %{total_items} domen iz %{filename}." - following_html: "Začeli boste slediti največ %{total_items} računom iz %{filename}." - lists_html: Dodali boste največ %{total_items} računov iz %{filename} na svoje sezname. Po potrebi bodo ustvarjeni novi seznami. - muting_html: "Utišali boste največ %{total_items} računov iz %{filename}." preface: Podatke, ki ste jih izvozili iz drugega strežnika, lahko uvozite. Na primer seznam oseb, ki jih spremljate ali blokirate. recent_imports: Nedavni uvozi states: @@ -1729,7 +1715,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..c113308eea9b70 100644 --- a/config/locales/sq.yml +++ b/config/locales/sq.yml @@ -21,6 +21,7 @@ sq: one: Mesazh other: Mesazhe posts_tab_heading: Mesazhe + self_follow_error: Ndjekja e llogarisë personale nuk lejohet admin: account_actions: action: Kryeje veprimin @@ -296,6 +297,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 +872,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. @@ -1154,7 +1159,6 @@ sq: use_security_key: Përdor kyç sigurie author_attribution: example_title: Tekst shembull - hint_html: Kontrolloni se si vlerësoheni, kur ndahen lidhje me të tjerë në Mastodon. more_from_html: Më tepër nga %{name} s_blog: Blogu i %{name} title: Atribuim autorësh @@ -1355,19 +1359,43 @@ sq: overwrite: Mbishkruaje overwrite_long: Zëvendësoji zërat ekzistues me të rinjtë overwrite_preambles: - blocking_html: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimeve me %{total_items} llogari nga %{filename}. - bookmarks_html: Ju ndan një hap nga zëvendësimi i faqerojtësve tuaj me %{total_items} postime nga %{filename}. - domain_blocking_html: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimit të përkatësive me %{total_items} përkatësi nga %{filename}. - following_html: Ju ndan një hap nga ndjekja e %{total_items} llogarive nga %{filename} dhe reshtja së ndjekuri këdo tjetër. - lists_html: Ju ndan një hap nga zëvendësimi i listave tuaja me lëndë nga %{filename}. Te listat e reja do të shtohen deri në %{total_items} llogari. - muting_html: Ju ndan një hpa nga zëvendësimi i listës suaj të llogarive të heshtuara me %{total_items} llogari nga %{filename}. + blocking_html: + one: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimeve, me %{count} llogari nga %{filename}. + other: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimeve, me %{count} llogari nga %{filename}. + bookmarks_html: + one: Ju ndan një hap nga zëvendësimi i faqerojtësve tuaj, me %{count} postim nga %{filename}. + other: Ju ndan një hap nga zëvendësimi i faqerojtësve tuaj, me %{count} postime nga %{filename}. + domain_blocking_html: + one: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimeve të përkatësive, me %{count} përkatësi nga %{filename}. + other: Ju ndan një hap nga zëvendësimi i listës tuaj të bllokimeve të përkatësive, me %{count} përkatësi nga %{filename}. + following_html: + one: Ju ndan një hap nga ndjekja e %{count} llogarie nga %{filename} dhe reshtja e ndjekjes së gjithkujt tjetër. + other: Ju ndan një hap nga ndjekja e deri %{count} llogarish nga %{filename} dhe reshtja e ndjekjes së gjithkujt tjetër. + lists_html: + one: Ju ndan një hap nga zëvendësimi i listave tuaja me lëndën e %{filename}. Te listat e reja do të shtohet deri %{count} llogari. + other: Ju ndan një hap nga zëvendësimi i listave tuaja me lëndën e %{filename}. Te listat e reja do të shtohet deri %{count} llogari. + muting_html: + one: Ju ndan një hap nga zëvendësimi i listës tuaj të llogarisë së heshtuar me %{count} llogari nga from %{filename}. + other: Ju ndan një hap nga zëvendësimi i listës tuaj të llogarive të heshtuara me %{count} llogari nga from %{filename}. preambles: - blocking_html: Ju ndan një hap nga bllokimi i %{total_items} llogarive nga %{filename}. - bookmarks_html: Ju ndan një hap nga shtimi te faqerojtësit tuaj i %{total_items} postimeve nga %{filename}. - domain_blocking_html: Ju ndan një hap nga bllokimi i %{total_items} përkatësive nga %{filename}. - following_html: Ju ndan një hap nga ndjekja e %{total_items} llogarive nga %{filename}. - lists_html: Jui nda një hap nga shtimi te listat tuaja i deri %{total_items} llogarive nga %{filename}. Nëse s’ka listë ku të shtohen, do të krijohen lista të reja. - muting_html: Ju ndan një hap nga heshtimi i %{total_items} llogarive nga %{filename}. + blocking_html: + one: Ju ndan një hap nga bllokimi i deri %{count} llogarie nga %{filename}. + other: Ju ndan një hap nga bllokimi i deri %{count} llogarive nga %{filename}. + bookmarks_html: + one: Ju ndan një hap nga shtimi te faqerojtësit tuaj i deri %{count} postimi nga %{filename}. + other: Ju ndan një hap nga shtimi te faqerojtësit tuaj i deri %{count} postimeve nga %{filename}. + domain_blocking_html: + one: Ju ndan një hap nga bllokimi i deri %{count} përkatësie nga %{filename}. + other: Ju ndan një hap nga bllokimi i deri %{count} përkatësive nga %{filename}. + following_html: + one: Ju ndan një hap nga ndjekja e deri %{count} llogarie nga %{filename}. + other: Ju ndan një hap nga ndjekja e deri %{count} llogarive nga %{filename}. + lists_html: + one: Ju ndan një hap nga shtimi i deri %{count} llogarie nga %{filename} te listat tuaja. Nëse s’ka listë ku të shtohen, do të krijohen lista të reja. + other: Ju ndan një hap nga shtimi i deri %{count} llogarive nga %{filename} te listat tuaja. Nëse s’ka listë ku të shtohen, do të krijohen lista të reja. + muting_html: + one: Ju ndan një hap nga heshtimi i deri %{count} llogarie nga %{filename}. + other: Ju ndan një hap nga heshtimi i deri %{count} llogarive nga %{filename}. preface: Mund të importoni të dhëna që keni eksportuar nga një shërbyes tjetër, bie fjala, një listë të personave që ndiqni ose bllokoni. recent_imports: Importime së fundi states: @@ -1684,7 +1712,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..f56cdb9cb5e26f 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -1302,20 +1302,6 @@ sr-Latn: merge_long: Zadržite postojeće zapise i dodajte nove overwrite: Zameni overwrite_long: Zameni trenutne zapise novima - overwrite_preambles: - blocking_html: Upravo ćete zameniti svoju listu blokiranih sa do %{total_items} naloga iz %{filename}. - bookmarks_html: Upravo ćete zameniti svoje obeleživače sa do %{total_items} objava iz %{filename}. - domain_blocking_html: Upravo ćete zameniti svoju listu blokiranih domena sa do %{total_items} domena iz %{filename}. - following_html: Upravo ćete pratiti do %{total_items} naloga iz %{filename} and i prestati sa praćenjem bilo koga drugog. - lists_html: Spremate se da zamenite svoje liste sadržajem od %{filename}. Do %{total_items} naloga će biti dodato na nove liste. - muting_html: Upravo ćete zameniti svoju listu ignorisanih naloga sa do %{total_items} naloga iz %{filename}. - preambles: - blocking_html: Upravo ćete blokirati do %{total_items} naloga iz %{filename}. - bookmarks_html: Upravo ćete dodati do %{total_items} objava iz %{filename} u vaše obeleživače. - domain_blocking_html: Upravo ćete blokirati do %{total_items} domena iz %{filename}. - following_html: Upravo ćete pratiti do %{total_items} naloga iz %{filename}. - lists_html: Spremate se da dodate do %{total_items} naloga od %{filename} na svoje liste. Nove liste će biti kreirane ako ne postoji lista za dodavanje. - muting_html: Upravo ćete ignorisati do %{total_items} naloga iz %{filename}. preface: Možete uvesti podatke koje ste izvezli sa druge instance, kao što su liste ljudi koje ste pratili ili blokirali. recent_imports: Nedavni uvozi states: @@ -1619,7 +1605,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..45feb0b5fca073 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -1332,20 +1332,6 @@ sr: merge_long: Задржите постојеће записе и додајте нове overwrite: Замени overwrite_long: Замени тренутне записе новима - overwrite_preambles: - blocking_html: Управо ћете заменити своју листу блокираних са до %{total_items} налога из %{filename}. - bookmarks_html: Управо ћете заменити своје обележиваче са до %{total_items} објава из %{filename}. - domain_blocking_html: Управо ћете заменити своју листу блокираних домена са до %{total_items} домена из %{filename}. - following_html: Управо ћете пратити до %{total_items} налога из %{filename} and и престати са праћењем било кога другог. - lists_html: Спремате се да замените своје листе садржајем од %{filename}. До %{total_items} налога ће бити додато на нове листе. - muting_html: Управо ћете заменити своју листу игнорисаних налога са до %{total_items} налога из %{filename}. - preambles: - blocking_html: Управо ћете блокирати до %{total_items} налога из %{filename}. - bookmarks_html: Управо ћете додати до %{total_items} објава из %{filename} у ваше обележиваче. - domain_blocking_html: Управо ћете блокирати до %{total_items} домена из %{filename}. - following_html: Управо ћете пратити до %{total_items} налога из %{filename}. - lists_html: Спремате се да додате до %{total_items} налога од %{filename} на своје листе. Нове листе ће бити креиране ако не постоји листа за додавање. - muting_html: Управо ћете игнорисати до %{total_items} налога из %{filename}. preface: Можете увести податке које сте извезли са друге инстанце, као што су листе људи које сте пратили или блокирали. recent_imports: Недавни увози states: @@ -1649,7 +1635,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..b79820310c76ac 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -21,10 +21,12 @@ sv: one: Inlägg other: Inlägg posts_tab_heading: Inlägg + self_follow_error: Det är inte tillåtet att följa ditt eget konto admin: account_actions: action: Utför åtgärd already_silenced: Detta konto är redan begränsat. + already_suspended: Detta konto är redan avstängt. title: Utför aktivitet för moderering på %{acct} account_moderation_notes: create: Lämna kommentar @@ -85,7 +87,7 @@ sv: remote: Avlägsen title: Plats login_status: Inloggningsstatus - media_attachments: Media bifogade filer + media_attachments: Mediebilagor memorialize: Förvandla till ett memoriam memorialized: Memorialiserad memorialized_msg: Omvandlingen av %{username} till ett minneskonto lyckades @@ -261,8 +263,10 @@ sv: destroy_user_role_html: "%{name} raderade rollen %{target}" disable_2fa_user_html: "%{name} inaktiverade tvåfaktorsautentiseringskrav för användaren %{target}" disable_custom_emoji_html: "%{name} inaktiverade emoji %{target}" + disable_sign_in_token_auth_user_html: "%{name} inaktiverade e-posttokenautentisering för %{target}" disable_user_html: "%{name} stängde av inloggning för användaren %{target}" enable_custom_emoji_html: "%{name} aktiverade emoji %{target}" + enable_sign_in_token_auth_user_html: "%{name} aktiverade e-posttokenautentisering för %{target}" enable_user_html: "%{name} aktiverade inloggning för användaren %{target}" memorialize_account_html: "%{name} gjorde %{target}'s konto till en minnessida" promote_user_html: "%{name} befordrade användaren %{target}" @@ -270,6 +274,7 @@ sv: reject_user_html: "%{name} avvisade registrering från %{target}" remove_avatar_user_html: "%{name} tog bort %{target}'s avatar" reopen_report_html: "%{name} öppnade rapporten igen %{target}" + resend_user_html: "%{name} skickade bekräftelsemail för %{target} på nytt" reset_password_user_html: "%{name} återställ användarens lösenord %{target}" resolve_report_html: "%{name} löste rapporten %{target}" sensitive_account_html: "%{name} markerade %{target}'s media som känsligt" @@ -430,6 +435,7 @@ sv: attempts_over_week: one: "%{count} försök under den senaste veckan" other: "%{count} registreringsförsök under den senaste veckan" + created_msg: Blockerade e-postdomänen delete: Radera dns: types: @@ -438,8 +444,12 @@ sv: new: create: Skapa domän resolve: Slå upp domän + title: Blockera ny e-postdomän + no_email_domain_block_selected: Inga blockeringar av e-postdomäner ändrades eftersom inga valdes not_permitted: Ej tillåtet + resolved_dns_records_hint_html: Domännamnet ger uppslag till följande MX-domäner, vilka är ytterst ansvariga för att e-post tas emot. Att blockera en MX-domän blockerar även registreringar från alla e-postadresser som använder samma MX-domän, även om det synliga domännamnet är annorlunda. Var noga med att inte blockera stora e-postleverantörer. resolved_through_html: Uppslagen genom %{domain} + title: Blockerade e-postdomäner export_domain_allows: new: title: Importera domäntillåtelser @@ -593,7 +603,9 @@ sv: resolve_description_html: Ingen åtgärd vidtas mot det rapporterade kontot, ingen prick registreras och rapporten stängs. silence_description_html: Kontot kommer endast synas för de som redan följer den eller manuellt söker på den, vilket dramatiskt minskar dess räckvidd. Kan alltid ångras. Stänger alla anmälningar mot detta konto. suspend_description_html: Kontot och allt dess innehåll kommer att vara oåtkomligt och så småningom tas bort, det kommer inte gå att interagera med kontot. Kan ångras inom 30 dagar. Stänger alla anmälningar mot detta konto. + actions_description_html: Välj vilken åtgärd som skall vidtas för att lösa denna rapport. Om du vidtar en bestraffningsåtgärd mot det rapporterade kontot kommer en e-postnotis att skickas till dem, förutom om du valt kategorin Skräppost. actions_description_remote_html: Bestäm vilka åtgärder som ska vidtas för att lösa denna rapport. Detta kommer bara att påverka hur din server kommunicerar med detta fjärrkonto och hanterar dess innehåll. + actions_no_posts: Denna rapport har inga associerade inlägg att ta bort add_to_report: Lägg till mer i rapporten already_suspended_badges: local: Redan avstängd på denna server @@ -657,6 +669,7 @@ sv: delete_data_html: Ta bort @%{acct}s profil och innehåll om 30 dagar ifall deras avstängning inte tagits bort under tiden preview_preamble_html: "@%{acct} kommer få en varning med följande innehåll:" record_strike_html: Registrera en varning mot @%{acct} för att hjälpa dig eskalera vid framtida överträdelser från detta konto + send_email_html: Skicka @%{acct} ett varningsmejl warning_placeholder: Valfri ytterligare resonemang för modereringsåtgärd. target_origin: Ursprung för anmält konto title: Anmälningar @@ -696,6 +709,7 @@ sv: manage_appeals: Hantera överklaganden manage_appeals_description: Tillåter användare att granska överklaganden av modereringsåtgärder manage_blocks: Hantera blockeringar + manage_blocks_description: Tillåter användare att blockera e-postleverantörer och IP-adresser manage_custom_emojis: Hantera egna emojier manage_custom_emojis_description: Tillåter användare att hantera egna emojier på servern manage_federation: Hantera federering @@ -713,6 +727,7 @@ sv: manage_taxonomies: Hantera taxonomier manage_taxonomies_description: Tillåter användare att granska trendande innehåll och uppdatera inställningar för hashtaggar manage_user_access: Hantera användaråtkomst + manage_user_access_description: Tillåter användare att inaktivera andra användares tvåfaktorsautentisering, ändra deras e-postadress samt återställa deras lösenord manage_users: Hantera användare manage_users_description: Tillåter användare att granska användares data och utföra modereringsåtgärder på dessa manage_webhooks: Hantera webhooks @@ -787,6 +802,7 @@ sv: destroyed_msg: Webbplatsuppladdningen har raderats! software_updates: critical_update: Kritiskt — vänligen uppdatera omgående + description: Det rekommenderas att hålla din Mastodon-installation uppdaterad för att ta nytta av de senaste fixarna och funktionerna. Dessutom är det ibland viktigt att uppdatera Mastodon i tid för att undvika säkerhetsproblem. Av dessa skäl kontrollerar Mastodon efter uppdateringar var 30:e minut och meddelar dig i enlighet med dina e-postaviseringsinställningar. documentation_link: Läs mer release_notes: Ändringslogg title: Tillgängliga uppdateringar @@ -860,6 +876,9 @@ 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: + action: Se tillgängliga uppdateringar + 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. @@ -874,22 +893,36 @@ sv: message_html: "Din objektlagring är felkonfigurerad. Sekretessen för dina användare är i riskzonen." tags: moderation: + not_usable: Inte användbar + pending_review: Väntar på granskning + review_requested: Granskning begärd reviewed: Granskat title: Status trendable: + unreviewed: Ogranskad + usable: Användbar name: Namn + newest: Nyaste + oldest: Äldsta reset: Återställ review: Granskningsstatus search: Sök + title: Hashtaggar updated_msg: Hashtagg-inställningarna har uppdaterats title: Administration trends: allow: Tillåt approved: Godkänd + confirm_allow: Är du säker på att du vill tillåta valda taggar? + confirm_disallow: Är du säker på att du vill förbjuda valda taggar? disallow: Neka links: allow: Tillåt länk allow_provider: Tillåt utgivare + confirm_allow: Är du säker på att du vill tillåta valda länkar? + confirm_allow_provider: Är du säker på att du vill tillåta valda leverantörer? + confirm_disallow: Är du säker på att du vill förbjuda valda länkar? + confirm_disallow_provider: Är du säker på att du vill förbjuda valda leverantörer? description_html: Detta är länkar som för närvarande delas mycket av konton som din server ser inlägg från. Det kan hjälpa dina användare att ta reda på vad som händer i världen. Inga länkar visas offentligt tills du godkänner utgivaren. Du kan också tillåta eller avvisa enskilda länkar. disallow: Blockera länk disallow_provider: Blockera utgivare @@ -913,6 +946,10 @@ sv: statuses: allow: Tillåt inlägg allow_account: Godkänn författare + confirm_allow: Är du säker på att du vill tillåta valda statusar? + confirm_allow_account: Är du säker på att du vill tillåta valda konton? + confirm_disallow: Är du säker på att du vill förbjuda valda statusar? + confirm_disallow_account: Är du säker på att du vill förbjuda valda konton? description_html: Detta är inlägg som din server vet om som för närvarande delas och favoriseras mycket just nu. Det kan hjälpa dina nya och återvändande användare att hitta fler människor att följa. Inga inlägg visas offentligt förrän du godkänner författaren, och författaren tillåter att deras konto föreslås till andra. Du kan också tillåta eller avvisa enskilda inlägg. disallow: Tillåt inte inlägg disallow_account: Tillåt inte författare @@ -1032,6 +1069,7 @@ sv: application_mailer: notification_preferences: Ändra e-postpreferenser salutation: "%{name}," + settings: 'Ändra e-postinställningar: %{link}' unsubscribe: Avprenumerera view: 'Granska:' view_profile: Visa profil @@ -1051,6 +1089,7 @@ sv: hint_html: En sista sak till! Vi måste bekräfta att du är en människa (för att hålla borta skräpinlägg!). Lös CAPTCHA nedan och klicka på "Fortsätt". title: Säkerhetskontroll confirmations: + awaiting_review: Din e-postadress är bekräftad! %{domain} personalen granskar nu din registrering. Du kommer att få ett e-postmeddelande om de godkänner ditt konto! awaiting_review_title: Din registrering är under granskning clicking_this_link: klicka på denna länk login_link: logga in @@ -1058,6 +1097,7 @@ sv: redirect_to_app_html: Du borde ha omdirigerats till appen %{app_name}. Om det inte hände, försök att %{clicking_this_link} eller återgå manuellt till appen. registration_complete: Din registrering på %{domain} är nu slutförd! welcome_title: Välkommen %{name}! + wrong_email_hint: Om e-postadressen inte är rätt, kan du ändra den i kontoinställningarna. delete_account: Radera konto delete_account_html: Om du vill radera ditt konto kan du fortsätta här. Du kommer att bli ombedd att bekräfta. description: @@ -1078,6 +1118,7 @@ sv: or_log_in_with: Eller logga in med privacy_policy_agreement_html: Jag har läst och godkänner integritetspolicyn progress: + confirm: Bekräfta e-postadress details: Dina uppgifter review: Vår recension rules: Acceptera regler @@ -1099,8 +1140,10 @@ sv: security: Säkerhet set_new_password: Skriv in nytt lösenord setup: + email_below_hint_html: Kolla din skräppost-mapp eller begär en ny. Du kan korrigera din e-postadress om den är fel. email_settings_hint_html: Klicka på länken som vi har skickat till dig för att bekräfta %{email}. Vi väntar här. link_not_received: Fick du ingen länk? + new_confirmation_instructions_sent: Du kommer att få ett nytt e-postmeddelande med bekräftelselänken om några minuter! title: Kolla din inkorg sign_in: preamble_html: Logga in med dina användaruppgifter på %{domain}. Om ditt konto finns på en annan server kommer du inte att kunna logga in här. @@ -1111,6 +1154,7 @@ sv: title: Låt oss få igång dig på %{domain}. status: account_status: Kontostatus + confirming: Väntar på att e-postbekräftelsen ska slutföras. functional: Ditt konto fungerar som det ska. pending: Din ansökan inväntar granskning. Detta kan ta tid. Du kommer att få ett e-postmeddelande om din ansökan har godkänts. redirecting_to: Ditt konto är inaktivt eftersom det för närvarande dirigeras om till %{acct}. @@ -1120,6 +1164,9 @@ sv: use_security_key: Använd säkerhetsnyckel author_attribution: example_title: Exempeltext + more_from_html: Mer från %{name} + s_blog: "%{name}s blogg" + title: Författarattribution challenge: confirm: Fortsätt hint_html: "Tips: Vi frågar dig inte efter ditt lösenord igen under nästkommande timme." @@ -1317,19 +1364,9 @@ sv: overwrite: Skriv över overwrite_long: Ersätt de nuvarande uppgifterna med de nya overwrite_preambles: - blocking_html: Du är på väg att ersätta din blockeringslista med upp till %{total_items} konton från %{filename}. - bookmarks_html: Du är på väg att ersätta din blockeringslista med upp till %{total_items} inlägg från %{filename}. - domain_blocking_html: Du är på väg att ersätta din blockeringslista med upp till %{total_items} domäner från %{filename}. - following_html: Du är på väg till följ upp till %{total_items} konton från %{filename} och sluta följa någon annan. - lists_html: Du är på väg att ersätta dina listor med innehållet i %{filename}. Upp till %{total_items} konton kommer att läggas till i nya listor. - muting_html: Du är på väg att ersätta din lista med tystade konton med upp till %{total_items} konton från %{filename}. - preambles: - blocking_html: Du är på väg att blockera med upp till %{total_items} konton från %{filename}. - bookmarks_html: Du håller på att lägga upp till %{total_items} inlägg från %{filename} till dina bokmärken. - domain_blocking_html: Du är på väg att blockera upp till %{total_items} domäner från %{filename}. - following_html: Du är på väg att följa upp till %{total_items} konton från %{filename}. - lists_html: Du håller på att lägga upp till %{total_items} konton från %{filename} till dina listor. Nya listor kommer att skapas om det inte finns någon lista att lägga till. - muting_html: Du är på väg att tysta upp till %{total_items} konton från %{filename}. + bookmarks_html: + one: Du är på väg att ersätta din blockeringslista med upp till %{count} inlägg från %{filename}. + other: Du är på väg att ersätta din blockeringslista med upp till %{count} inlägg från %{filename}. preface: Du kan importera data som du exporterat från en annan instans, till exempel en lista över personer du följer eller blockerar. recent_imports: Nyligen importerade states: @@ -1414,6 +1451,7 @@ sv: media_attachments: validations: images_and_video: Det går inte att bifoga en video till ett inlägg som redan innehåller bilder + not_found: Media %{ids} hittades inte eller är redan anslutet till ett annat inlägg not_ready: Kan inte bifoga filer som inte har behandlats färdigt. Försök igen om ett ögonblick! too_many: Det går inte att bifoga mer än 4 filer migrations: @@ -1645,7 +1683,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 @@ -1895,6 +1933,7 @@ sv: instructions_html: Kopiera och klistra in koden nedan in i HTML-koden på din webbplats. Lägg sedan till adressen till din webbplats i ett av de extra fälten på din profil från fliken "Redigera profil" och spara ändringar. verification: Bekräftelse verified_links: Dina verifierade länkar + website_verification: Webbplats verifiering webauthn_credentials: add: Lägg till ny säkerhetsnyckel create: diff --git a/config/locales/th.yml b/config/locales/th.yml index d56385f2611add..2c21687a460bd0 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -19,6 +19,7 @@ th: posts: other: โพสต์ posts_tab_heading: โพสต์ + self_follow_error: ไม่อนุญาตการติดตามบัญชีของคุณเอง admin: account_actions: action: ทำการกระทำ @@ -861,12 +862,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: "เว็บเซิร์ฟเวอร์ของคุณกำหนดค่าไม่ถูกต้อง ความเป็นส่วนตัวของผู้ใช้ของคุณตกอยู่ในความเสี่ยง" @@ -1144,7 +1148,6 @@ th: use_security_key: ใช้กุญแจความปลอดภัย author_attribution: example_title: ข้อความตัวอย่าง - hint_html: ควบคุมวิธีที่ให้เครดิตแก่คุณเมื่อมีการแบ่งปันลิงก์ใน Mastodon more_from_html: เพิ่มเติมจาก %{name} s_blog: บล็อกของ %{name} title: การระบุแหล่งที่มาผู้สร้าง @@ -1337,20 +1340,6 @@ th: merge_long: เก็บระเบียนที่มีอยู่และเพิ่มระเบียนใหม่ overwrite: เขียนทับ overwrite_long: แทนที่ระเบียนปัจจุบันด้วยระเบียนใหม่ - overwrite_preambles: - blocking_html: คุณกำลังจะ แทนที่รายการการปิดกั้นของคุณ ด้วยมากถึง %{total_items} บัญชี จาก %{filename} - bookmarks_html: คุณกำลังจะ แทนที่ที่คั่นหน้าของคุณ ด้วยมากถึง %{total_items} โพสต์ จาก %{filename} - domain_blocking_html: คุณกำลังจะ แทนที่รายการการปิดกั้นโดเมนของคุณ ด้วยมากถึง %{total_items} โดเมน จาก %{filename} - following_html: คุณกำลังจะ ติดตาม มากถึง %{total_items} บัญชี จาก %{filename} และ หยุดการติดตามคนอื่นใด - lists_html: คุณกำลังจะ แทนที่รายการของคุณ ด้วยเนื้อหาของ %{filename} จะเพิ่มมากถึง %{total_items} บัญชี ไปยังรายการใหม่ - muting_html: คุณกำลังจะ แทนที่รายการบัญชีที่ซ่อนอยู่ของคุณ ด้วยมากถึง %{total_items} บัญชี จาก %{filename} - preambles: - blocking_html: คุณกำลังจะ ปิดกั้น มากถึง %{total_items} บัญชี จาก %{filename} - bookmarks_html: คุณกำลังจะเพิ่มมากถึง %{total_items} โพสต์ จาก %{filename} ไปยัง ที่คั่นหน้า ของคุณ - domain_blocking_html: คุณกำลังจะ ปิดกั้น มากถึง %{total_items} โดเมน จาก %{filename} - following_html: คุณกำลังจะ ติดตาม มากถึง %{total_items} บัญชี จาก %{filename} - lists_html: คุณกำลังจะเพิ่มมากถึง %{total_items} บัญชี จาก %{filename} ไปยัง รายการ ของคุณ จะสร้างรายการใหม่หากไม่มีรายการที่จะเพิ่มไปยัง - muting_html: คุณกำลังจะ ซ่อน มากถึง %{total_items} บัญชี จาก %{filename} preface: คุณสามารถนำเข้าข้อมูลที่คุณได้ส่งออกจากเซิร์ฟเวอร์อื่น เช่น รายการผู้คนที่คุณกำลังติดตามหรือกำลังปิดกั้น recent_imports: การนำเข้าล่าสุด states: @@ -1666,7 +1655,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..942ee2fbf29b40 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1,7 +1,7 @@ --- tr: about: - about_mastodon_html: Mastodon ücretsiz ve açık kaynaklı bir sosyal ağdır. Merkezileştirilmemiş yapısı sayesinde diğer ticari sosyal platformların aksine iletişimininizin tek bir firmada tutulmasının/yönetilmesinin önüne geçer. Güvendiğiniz bir sunucuyu seçerek oradaki kişilerle etkileşimde bulunabilirsiniz. Herkes kendi Mastodon sunucusunu kurabilir ve sorunsuz bir şekilde Mastodon sosyal ağına dahil edebilir. + about_mastodon_html: Mastodon ücretsiz ve açık kaynaklı bir sosyal ağdır. Merkezi olmayan yapısı sayesinde diğer ticari sosyal platformların aksine iletişimininizin tek bir firmada tutulmasının/yönetilmesinin önüne geçer. Güvendiğiniz bir sunucuyu seçerek oradaki kişilerle etkileşimde bulunabilirsiniz. Herkes kendi Mastodon sunucusunu kurabilir ve sorunsuz bir şekilde Mastodon sosyal ağına dahil edebilir! contact_missing: Ayarlanmadı contact_unavailable: Bulunamadı hosted_on: Mastodon %{domain} üzerinde barındırılıyor @@ -21,6 +21,7 @@ tr: one: Gönderi other: Gönderiler posts_tab_heading: Gönderiler + self_follow_error: Kendi hesabınızı takip etmenize izin yok admin: account_actions: action: Eylemi gerçekleştir @@ -875,6 +876,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. @@ -1162,9 +1166,11 @@ tr: use_security_key: Güvenlik anahtarını kullan author_attribution: example_title: Örnek metin - hint_html: Mastodon'da bağlantılar paylaşıldığında nasıl tanınmak istediğinizi denetleyin. + hint_html: Mastodon dışında haber veya günlük yazıları mı yazıyorsunuz? Bu yazılar Mastodon'da paylaşıldığında size nasıl atıf yapılacağını denetleyin. + instructions: 'Bu kodun yazınızın HTML''sinde olduğundan emin olun:' more_from_html: "%{name} kişisinden daha fazlası" s_blog: "%{name} kişisinin Günlüğü" + then_instructions: Daha sonra, yayının alan adını aşağıda sahaya girin. title: Yazar atıfı challenge: confirm: Devam et @@ -1363,19 +1369,43 @@ tr: overwrite: Üzerine yaz overwrite_long: Mevcut kayıtları yenileriyle değiştir overwrite_preambles: - blocking_html: "Engel listenizi, %{filename} dosyasından, %{total_items} hesapla değiştirmek üzeresiniz." - bookmarks_html: "Yerimlerinizi, %{filename} dosyasından, %{total_items} gönderiyle değiştirmek üzeresiniz." - domain_blocking_html: "Alan adı engel listenizi, %{filename} dosyasından, %{total_items} alan adıyla değiştirmek üzeresiniz." - following_html: "%{filename} dosyasından %{total_items} hesabı takip etmeye başlamak ve diğer herkesi takipten çıkmak üzeresiniz." - lists_html: Listelerinizi %{filename} içeriğiyle değiştirmek üzeresiniz. Yeni listelere en fazla %{total_items} hesap eklenecek. - muting_html: "Sessize alınmış hesaplar listenizi, %{filename} dosyasından, %{total_items} hesapla değiştirmek üzeresiniz." + blocking_html: + one: "Engelleme listenizi, %{filename} dosyasından %{count} hesap ile değiştirmek üzeresiniz." + other: "Engelleme listenizi, %{filename} dosyasından %{count} hesap ile değiştirmek üzeresiniz." + bookmarks_html: + one: "Yerimlerinizi, %{filename} dosyasından %{count} gönderi ile değiştirmek üzeresiniz." + other: "Yerimlerinizi, %{filename} dosyasından %{count} gönderi ile değiştirmek üzeresiniz." + domain_blocking_html: + one: "Alan adı engelleme listenizi, %{filename} dosyasından %{count} alan adı ile değiştirmek üzeresiniz." + other: "Alan adı engelleme listenizi, %{filename} dosyasından %{count} alan adı ile değiştirmek üzeresiniz." + following_html: + one: "%{filename} dosyasından %{count} hesabı takip etmek ve diğer herkesin takibini bırakmak üzeresiniz." + other: "%{filename} dosyasından %{count} hesabı takip etmek ve diğer herkesin takibini bırakmak üzeresiniz." + lists_html: + one: "Listelerinizi, %{filename} dosya içeriğiyle değiştirmek üzeresiniz. %{count} hesap yeni listelere eklenecektir." + other: "Listelerinizi, %{filename} dosya içeriğiyle değiştirmek üzeresiniz. %{count} hesap yeni listelere eklenecektir." + muting_html: + one: "Sessize alınmış hesap listenizi, %{filename} dosyasından %{count} hesap ile değiştirmek üzeresiniz." + other: "Sessize alınmış hesap listenizi, %{filename} dosyasından %{count} hesap ile değiştirmek üzeresiniz." preambles: - blocking_html: "%{filename} dosyasından %{total_items} hesabı engellemek üzeresiniz." - bookmarks_html: "%{filename} dosyasından %{total_items} gönderiyi yerimlerinize eklemek üzeresiniz." - domain_blocking_html: "%{filename} dosyasından %{total_items} alan adını engellemek üzeresiniz." - following_html: "%{filename} dosyasından %{total_items} hesabı takip etmek üzeresiniz." - lists_html: "Listelerinize %{filename} dosyasından en fazla %{total_items} hesap eklemek üzeresiniz. Eklenecek bir liste olmaması durumunda yeni listeler oluşturulacaktır." - muting_html: "%{filename} dosyasından %{total_items} hesabı sessize almak üzeresiniz." + blocking_html: + one: "%{filename} dosyasından %{count} hesap engellemek üzeresiniz." + other: "%{filename} dosyasından %{count} hesap engellemek üzeresiniz." + bookmarks_html: + one: "Yerimlerinize, %{filename} dosyasından %{count} gönderi eklemek üzeresiniz." + other: "Yerimlerinize, %{filename} dosyasından %{count} gönderi eklemek üzeresiniz." + domain_blocking_html: + one: "%{filename} dosyasından %{count} alan adı engellemek üzeresiniz." + other: "%{filename} dosyasından %{count} alan adı engellemek üzeresiniz." + following_html: + one: "%{filename} dosyasından %{count} hesap takip etmek üzeresiniz." + other: "%{filename} dosyasından %{count} hesap takip etmek üzeresiniz." + lists_html: + one: "Listelerinize, %{filename} %{count} hesap eklemek üzeresiniz. Eklenecek liste yoksa yeni listeler oluşturulacaktır." + other: "Listelerinize, %{filename} %{count} hesap eklemek üzeresiniz. Eklenecek liste yoksa yeni listeler oluşturulacaktır." + muting_html: + one: "%{filename} dosyasından %{count} hesabı sessize almak üzeresiniz." + other: "%{filename} dosyasından %{count} hesabı sessize almak üzeresiniz." preface: Diğer sunucudan alarak oluşturduğunuz dosyalar sayesinde, bu sunucudaki hesabınıza takipçilerinizi aktarabilir veya istemediğiniz kişileri otomatik olarak engelleyebilirsiniz. recent_imports: Son içe aktarmalar states: @@ -1692,7 +1722,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..ab50ac4deea134 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -25,6 +25,7 @@ uk: one: Допис other: Дописів posts_tab_heading: Дописів + self_follow_error: Ви не можете стежити за власним обліковим записом admin: account_actions: action: Виконати дію @@ -903,6 +904,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. Оновіться якнайшвидше. @@ -1198,9 +1202,9 @@ uk: use_security_key: Використовувати ключ безпеки author_attribution: example_title: Зразок тексту - hint_html: Контроль авторства поширених посилань на Mastodon. more_from_html: Більше від %{name} s_blog: Блог %{name} + then_instructions: Потім додайте доменне ім'я публікації у поле нижче. title: Атрибути авторства challenge: confirm: Далі @@ -1412,20 +1416,6 @@ uk: merge_long: Зберегти наявні записи та додати нові overwrite: Перезаписувати overwrite_long: Замінити наявні записи новими - overwrite_preambles: - blocking_html: Ви збираєтеся замінити ваш список блокування з %{total_items} обліковими записами з %{filename}. - bookmarks_html: Ви збираєтеся замінити ваші закладки з %{total_items} дописами з %{filename}. - domain_blocking_html: Ви збираєтеся замінити ваш список блокування доменів з %{total_items} доменами з %{filename}. - following_html: Ви збираєтеся слідкувати за %{total_items} обліковими записами з %{filename} і перестати слідкувати за всіма іншими. - lists_html: Ви збираєтеся замінити ваші списки вмістом з %{filename}. До нових списків буде додано до %{total_items} облікових записів. - muting_html: Ви збираєтеся замінити ваш список ігнорованих облікових записів з %{total_items} обліковими записами з %{filename}. - preambles: - blocking_html: Ви збираєтеся заблокувати %{total_items} облікових записів з %{filename}. - bookmarks_html: Ви збираєтеся додати %{total_items} дописів з %{filename} до ваших закладок. - domain_blocking_html: Ви збираєтеся заблокувати %{total_items} доменів з %{filename}. - following_html: Ви збираєтеся слідкувати за %{total_items} обліковими записами з %{filename}. - lists_html: Ви збираєтеся додати до %{total_items} облікових записів з %{filename} до ваших списків. Нові списки будуть створені, якщо немає списку для додавання. - muting_html: Ви збираєтеся ігнорувати %{total_items} облікових записів з %{filename}. preface: Ви можете імпортувати дані, які ви експортували з іншого сервера, наприклад, список людей, яких ви відстежуєте або блокуєте. recent_imports: Останні імпорти states: @@ -1744,7 +1734,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..00431ba4250662 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -19,6 +19,7 @@ vi: posts: other: Tút posts_tab_heading: Tút + self_follow_error: Bạn không thể tự theo dõi chính bạn admin: account_actions: action: Thực hiện hành động @@ -32,7 +33,7 @@ vi: accounts: add_email_domain_block: Chặn tên miền email approve: Phê duyệt - approved_msg: Đã phê duyệt đăng ký %{username} + approved_msg: Đã chấp nhận đăng ký %{username} are_you_sure: Bạn có chắc không? avatar: Ảnh đại diện by_domain: Máy chủ @@ -44,7 +45,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 +56,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 +92,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 +109,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 @@ -131,7 +132,7 @@ vi: resubscribe: Đăng ký lại role: Vai trò search: Tìm kiếm - search_same_email_domain: Những người khác với cùng tên miền email + search_same_email_domain: Những người có cùng tên miền email search_same_ip: Tra cứu IP security: Bảo mật security_measures: @@ -153,8 +154,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ế @@ -164,12 +165,12 @@ vi: unsuspended_msg: Đã kích hoạt lại %{username} thành công username: Tài khoản view_domain: Xem mô tả tài khoản này - warn: Nhắc + warn: Cảnh cáo web: Web whitelisted: Danh sách trắng action_logs: action_types: - approve_appeal: Chấp nhận kháng cáo + approve_appeal: Chấp nhận khiếu nại approve_user: Chấp nhận đăng ký assigned_to_self_report: Tự xử lý báo cáo change_email_user: Đổi email người dùng @@ -177,25 +178,25 @@ vi: 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 biến thể 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_email_domain_block: Chặn tên miền email + create_ip_block: Chặn IP + create_unavailable_domain: Bỏ 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 biến thể destroy_custom_emoji: Xóa emoji - destroy_domain_allow: Bỏ thanh trừng máy chủ + destroy_domain_allow: Bỏ máy chủ cho phép 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: Cho phép 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 @@ -203,21 +204,21 @@ vi: disable_user: Vô hiệu hóa đăng nhập enable_custom_emoji: Cho phép 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 - memorialize_account: Đánh dấu tưởng niệm - promote_user: Chỉ định vai trò - reject_appeal: Từ chối kháng cáo + enable_user: Cho phép đăng nhập + memorialize_account: Gán tưởng niệm + promote_user: Nâng vai trò + reject_appeal: Từ chối khiếu nại reject_user: Từ chối đăng ký remove_avatar_user: Xóa ảnh đại diện reopen_report: Mở lại báo cáo 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 - unassigned_report: Báo cáo chưa xử lý - unblock_email_account: Mở khóa địa chỉ email + 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ỏ xử lý báo cáo + 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,65 +230,65 @@ 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} đã chấp nhận khiếu nại từ %{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}" + 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}" - change_role_user_html: "%{name} đã thay đổi vai trò %{target}" + change_role_user_html: "%{name} đã thay đổi vai trò của %{target}" 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_announcement_html: "%{name} đã tạo thông báo %{target}" + create_canonical_email_block_html: "%{name} đã chặn địa chỉ email biến thể %{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}" + create_domain_allow_html: "%{name} đã bật liên hợp với %{target}" + create_domain_block_html: "%{name} đã chặn máy chủ %{target}" create_email_domain_block_html: "%{name} đã chặn tên miền email %{target}" 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_unavailable_domain_html: "%{name} đã bỏ liên hợp 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}" - 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}" + 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 địa chỉ email biến thể %{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}" + destroy_domain_block_html: "%{name} đã bỏ chặn máy chủ %{target}" destroy_email_domain_block_html: "%{name} đã bỏ chặn email %{target}" - destroy_instance_html: "%{name} thanh trừng máy chủ %{target}" - destroy_ip_block_html: "%{name} bỏ chặn IP %{target}" + destroy_instance_html: "%{name} đã thanh trừng máy chủ %{target}" + destroy_ip_block_html: "%{name} đã bỏ chặn IP %{target}" destroy_status_html: "%{name} đã xóa tút của %{target}" - destroy_unavailable_domain_html: "%{name} tiếp tục phân phối với máy chủ %{target}" + destroy_unavailable_domain_html: "%{name} tiếp tục liên hợp với máy chủ %{target}" destroy_user_role_html: "%{name} đã xóa vai trò %{target}" disable_2fa_user_html: "%{name} đã vô hiệu hóa xác minh hai bước của %{target}" 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}" + disable_user_html: "%{name} đã vô hiệu hóa đăng nhập %{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}" + 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}" - reject_appeal_html: "%{name} đã từ chối kháng cáo của %{target}" + promote_user_html: "%{name} đã nâng vai trò của %{target}" + reject_appeal_html: "%{name} đã từ chối khiếu nại từ %{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}" - reopen_report_html: "%{name} mở lại báo cáo %{target}" + reopen_report_html: "%{name} đã mở lại báo cáo %{target}" resend_user_html: "%{name} đã gửi lại email xác minh cho %{target}" reset_password_user_html: "%{name} đã đặt lại mật khẩu của %{target}" resolve_report_html: "%{name} đã xử lý báo cáo %{target}" - sensitive_account_html: "%{name} đánh dấu nội dung của %{target} là nhạy cảm" + sensitive_account_html: "%{name} đã gán nội dung của %{target} là nhạy cảm" 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}" - unsensitive_account_html: "%{name} đánh dấu nội dung của %{target} là bình thường" + unassigned_report_html: "%{name} đã thôi xử lý báo cáo %{target}" + unblock_email_account_html: "%{name} đã bỏ chặn địa chỉ email của %{target}" + unsensitive_account_html: "%{name} đã gán 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}" - update_announcement_html: "%{name} cập nhật thông báo %{target}" + update_announcement_html: "%{name} đã cập nhật thông báo %{target}" update_custom_emoji_html: "%{name} đã cập nhật emoji %{target}" - update_domain_block_html: "%{name} cập nhật chặn máy chủ %{target}" - 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_domain_block_html: "%{name} đã cập nhật chặn máy chủ %{target}" + 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} đã 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 +329,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ê @@ -353,7 +354,7 @@ vi: new_users: người mới opened_reports: báo cáo pending_appeals_html: - other: "%{count} kháng cáo đang chờ" + other: "%{count} khiếu nại đang chờ" pending_reports_html: other: "%{count} báo cáo đang chờ" pending_tags_html: @@ -371,7 +372,7 @@ vi: disputes: appeals: empty: Không tìm thấy. - title: Kháng cáo + title: Khiếu nại domain_allows: add_new: Cho phép liên hợp với máy chủ created_msg: Máy chủ đã được kích hoạt liên hợp thành công @@ -691,8 +692,8 @@ vi: invite_users_description: Cho phép mời những người mới vào máy chủ 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: Quản lý khiếu nại + manage_appeals_description: Cho phép thành viên khiếu nại đố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 +705,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 +799,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,8 +818,8 @@ vi: open: Mở tút original_status: Tút gốc reblogs: Lượt đăng lại - status_changed: Tút đã thay đổi - title: Toàn bộ tút + status_changed: Tút đã sửa + title: Tất cả tút trending: Xu hướng visibility: Hiển thị with_media: Có media @@ -861,6 +862,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 +900,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 +919,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 +940,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 +960,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 +1008,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ể chấp nhận khiếu nại để bỏ kiểm duyệt, hoặc không. 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 +1026,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 +1041,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á @@ -1144,10 +1148,12 @@ vi: use_security_key: Dùng khóa bảo mật author_attribution: example_title: Văn bản mẫu - 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} + hint_html: Bạn là nhà báo hoặc blogger bên ngoài Mastodon? Kiểm soát cách bạn được ghi nhận khi chúng được chia sẻ trên Mastodon. + instructions: 'Đặt mã này trong HTML bài viết:' + more_from_html: Viết bởi %{name} s_blog: "%{name}'s Blog" - title: Ghi nhận tác giả + then_instructions: Sau đó, thêm URL của báo/blog trong trường bên dưới. + 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,12 +1207,12 @@ 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: Chấp nhận khiếu nại 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}. recipient: Người nhận - reject_appeal: Từ chối kháng cáo + reject_appeal: Từ chối khiếu nại status: 'Tút #%{id}' status_removed: Tút này đã được xóa khỏi hệ thống title: "%{action} từ %{date}" @@ -1262,7 +1268,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 +1286,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,21 +1342,33 @@ 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}. - domain_blocking_html: Bạn sắp thay thế danh sách máy chủ chặn với %{total_items} máy chủ từ %{filename}. - following_html: Bạn sắp theo dõi với %{total_items} người từ %{filename}ngừng theo dõi bất kỳ ai. - lists_html: Bạn sắp thay thế các danh sách bằng nội dung từ %{filename}. Hơn %{total_items} tài khoản sẽ được thêm vào những danh sách mới. - muting_html: Bạn sắp thay thế danh sách ẩn với %{total_items} người từ %{filename}. + blocking_html: + other: Bạn sắp thay thế danh sách chặn với %{count} người từ %{filename}. + bookmarks_html: + other: Bạn sắp thay thế danh sách tút đã lưu với %{count} tút từ %{filename}. + domain_blocking_html: + other: Bạn sắp thay thế danh sách máy chủ chặn với %{count} máy chủ từ %{filename}. + following_html: + other: Bạn sắp theo dõi tới %{count} người từ %{filename}ngừng theo dõi mọi người khác. + lists_html: + other: Bạn sắp thay thế danh sách với nội dung của %{filename}. Có %{count} người sẽ được thêm vào những danh sách mới. + muting_html: + other: Bạn sắp they thế danh sách người bạn chặn với %{count} người từ %{filename}. preambles: - blocking_html: Bạn sắp chặn tới %{total_items} người từ %{filename}. - bookmarks_html: Bạn sắp thêm vào %{total_items} tút từ %{filename} vào lượt lưu. - domain_blocking_html: Bạn sắp chặn tới %{total_items} máy chủ từ %{filename}. - following_html: Bạn sắp theo dõi tới %{total_items} người từ %{filename}. - lists_html: Bạn sắp thêm %{total_items} tài khoản từ %{filename} vào danh sách của bạn. Những danh sách mới sẽ được tạo nếu bạn chưa có danh sách nào. - muting_html: Bạn sắp ẩn lên tới %{total_items} người từ %{filename}. + blocking_html: + other: Bạn sắp chặn tới %{count} người từ %{filename}. + bookmarks_html: + other: Bạn sắp thêm tới %{count} tút từ %{filename} vào danh sách tút đã lưu. + domain_blocking_html: + other: Bạn sắp chặn tới %{count} máy chủ từ %{filename}. + following_html: + other: Bạn sắp theo dõi tới %{count} người từ %{filename}. + lists_html: + other: Bạn sắp thêm tới %{count} người từ %{filename} vào danh sách của bạn. Những danh sách mới sẽ được tạo nếu không có danh sách để thêm. + muting_html: + other: Bạn sắp ẩn tới %{count} người từ %{filename}. preface: Bạn có thể nhập dữ liệu mà bạn đã xuất từ một máy chủ khác, chẳng hạn danh sách những người đang theo dõi hoặc chặn. recent_imports: Đã nhập gần đây states: @@ -1370,10 +1388,10 @@ vi: muting: Đang nhập người đã ẩn type: Kiểu nhập type_groups: - constructive: Lượt theo dõi và những thứ đã lưu - destructive: Lượt chặn và ẩn + constructive: Theo dõi và lưu + destructive: Chặn và ẩn types: - blocking: Danh sách chặn + blocking: Danh sách người đã chặn bookmarks: Tút đã lưu domain_blocking: Danh sách máy chủ đã chặn following: Danh sách người theo dõi @@ -1414,7 +1432,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 +1573,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 +1684,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 +1693,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 +1706,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: @@ -1731,7 +1749,7 @@ vi: ignore_favs: Bỏ qua số lượt thích ignore_reblogs: Bỏ qua lượt đăng lại interaction_exceptions: Ngoại lệ dựa trên tương tác - interaction_exceptions_explanation: Lưu ý rằng không có gì đảm bảo rằng các tút sẽ bị xóa nếu chúng tụt dưới ngưỡng mức yêu thích hoặc đăng lại, dù đã từng đạt. + interaction_exceptions_explanation: Lưu ý là không có gì đảm bảo rằng các tút sẽ bị xóa nếu chúng bị giảm lượt thích hoặc đăng lại, dù đã từng đạt. keep_direct: Giữ lại tin nhắn keep_direct_hint: Không xóa tin nhắn của bạn keep_media: Giữ lại những tút có đính kèm media @@ -1762,14 +1780,14 @@ vi: sensitive_content: NSFW strikes: errors: - too_late: Đã quá trễ để kháng cáo + too_late: Đã quá trễ để khiếu nại tags: does_not_match_previous_name: không khớp với tên trước themes: 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 +1850,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. + silence: Bạn vẫn có thể sử dụng tài khoản của mình và người khác vẫn có thể theo dõi bạn, nhưng chỉ những người đã theo dõi bạn mới thấy tút của bạn. Bạn cũng bị loại khỏi các tính năng khám phá khác. + suspend: Tài khoản của bạn, hồ sơ và các dữ liệu khác sẽ không thể truy cập được nữa. 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 trong vòng 30 ngày, nhưng chúng tôi sẽ giữ lại một số dữ liệu cơ bản để phòng khi bạn được bỏ 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 +1923,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 +1936,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..209683e21cf32b 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -19,6 +19,7 @@ zh-CN: posts: other: 嘟文 posts_tab_heading: 嘟文 + self_follow_error: 不可以关注自己 admin: account_actions: action: 执行操作 @@ -595,7 +596,7 @@ zh-CN: actions_no_posts: 该举报没有相关嘟文可供删除 add_to_report: 增加更多举报内容 already_suspended_badges: - local: 已经在此服务器上暂停 + local: 已在此服务器上被封禁 remote: 已在其所属服务器被封禁 are_you_sure: 你确定吗? assign_to_self: 接管 @@ -861,6 +862,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紧急更新可用,请尽快更新。 @@ -1144,9 +1148,11 @@ zh-CN: use_security_key: 使用安全密钥 author_attribution: example_title: 示例文本 - hint_html: 控制在 Mastodon 上分享的链接如何显示你的署名。 + hint_html: 你是否在 Mastodon 之外撰写新闻或博客文章?控制它们被分享到 Mastodon 时的署名方式。 + instructions: 请确保将这段代码放在您文章的 HTML 中: more_from_html: 来自 %{name} 的更多内容 s_blog: "%{name} 的博客" + then_instructions: 然后,在下面的文本框中添加你用于发布文章的域名。 title: 作者归属 challenge: confirm: 继续 @@ -1338,19 +1344,31 @@ zh-CN: overwrite: 覆盖 overwrite_long: 将当前记录替换为新记录 overwrite_preambles: - blocking_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个账户替换你的屏蔽列表。 - bookmarks_html: 你即将使用来自 %{filename} %{total_items} 篇嘟文替换你的书签。 - domain_blocking_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个域名替换你的域名屏蔽列表。 - following_html: 你即将从 %{filename} 关注 %{total_items} 个账户,并停止关注其他任何人。 - lists_html: 你即将用 %{filename} 的内容替换你的列表。新列表中将添加 %{total_items} 个账户。 - muting_html: 你即将使用来自 %{filename} 的最多 %{total_items} 个账户替换你已隐藏的账户列表。 + blocking_html: + other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的屏蔽列表。 + bookmarks_html: + other: 你即将使用来自 %{filename} 的最多 %{count} 条嘟文替换你的书签。 + domain_blocking_html: + other: 你即将使用来自 %{filename} 的最多 %{count} 个域名替换你的域名屏蔽列表。 + following_html: + other: 你即将关注来自 %{filename} 的最多 %{count} 个账户,并停止关注其他所有人。 + lists_html: + other: 你即将使用来自 %{filename} 的内容替换你的列表。最多将会有 %{count} 个账户 被添加到新列表。 + muting_html: + other: 你即将使用来自 %{filename} 的最多 %{count} 个帐户替换你的已隐藏账户列表。 preambles: - blocking_html: 你即将从 %{filename} 封锁多达 %{total_items} 个账户。 - bookmarks_html: 你即将把来自 %{filename} %{total_items} 篇嘟文添加到你的书签中。 - domain_blocking_html: 你即将从 %{filename} 屏蔽 %{total_items} 个域名。 - following_html: 你即将从 %{filename} 关注最多 %{total_items} 个账户。 - lists_html: 你即将从 %{filename} 中添加最多 %{total_items} 个账户到你的列表中。如果没有可用列表,将创建新的列表。 - muting_html: 你即将从 %{filename} 隐藏 %{total_items} 个账户。 + blocking_html: + other: 你即将屏蔽来自 %{filename} 的最多 %{count} 个账号。 + bookmarks_html: + other: 你即将把来自 %{filename} %{count} 篇嘟文添加到你的书签中。 + domain_blocking_html: + other: 你即将屏蔽来自 %{filename} 的最多 %{count} 个域名。 + following_html: + other: 你即将关注来自 %{filename} 的最多 %{count} 个账号。 + lists_html: + other: 你即将从 %{filename} 中添加最多 %{count} 个账户到你的列表中。如果没有可用列表,将创建新的列表。 + muting_html: + other: 你即将隐藏来自 %{filename} 的最多 %{count} 个账号。 preface: 你可以在此导入你在其他实例导出的数据,比如你所关注或屏蔽的用户列表。 recent_imports: 最近导入 states: @@ -1683,8 +1701,8 @@ zh-CN: severed_relationships: download: 下载 (%{count}) event_type: - account_suspension: 账户被封禁 (%{target_name}) - domain_block: 服务器被封禁 (%{target_name}) + account_suspension: 封禁账户 (%{target_name}) + domain_block: 封禁服务器 (%{target_name}) user_domain_block: 你屏蔽了 %{target_name} lost_followers: 失去的关注者 lost_follows: 失去的关注 @@ -1860,7 +1878,7 @@ zh-CN: apps_android_action: 从 Google Play 下载 apps_ios_action: 从 App Store 下载 apps_step: 下载我们的官方应用。 - apps_title: Mastodon应用 + apps_title: Mastodon 应用 checklist_subtitle: 让我们带你开启这片社交新天地: checklist_title: 欢迎清单 edit_profile_action: 个性化 @@ -1868,16 +1886,16 @@ zh-CN: edit_profile_title: 个性化你的个人资料 explanation: 下面是几个小贴士,希望它们能帮到你 feature_action: 了解更多 - feature_audience: Mastodon为你提供了无需中间商即可管理受众的独特可能。Mastodon可被部署在你自己的基础设施上,允许你关注其它任何Mastodon在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受你之外的任何人控制。 + feature_audience: Mastodon 为你提供了无需中间商即可管理受众的独特可能。Mastodon 可被部署在你自己的基础设施上,允许你关注其它任何 Mastodon 在线服务器的用户,或被任何其他在线 Mastodon 服务器的用户关注,并且不受你之外的任何人控制。 feature_audience_title: 放手去建立起你的受众 feature_control: 你最清楚你想在你自己的主页中看到什么动态。没有算法或广告浪费你的时间。你可以用一个账号关注任何 Mastodon 服务器上的任何人,并按时间顺序获得他们发布的嘟文,让你的互联网的角落更合自己的心意。 feature_control_title: 掌控自己的时间线 - feature_creativity: Mastodon支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助你在网上尽情表达自己。无论你是要发布你的艺术作品、音乐还是播客,Mastodon 都能为你服务。 + feature_creativity: Mastodon 支持音频、视频和图片、无障碍描述、投票、内容警告, 动画头像、自定义表情包、缩略图裁剪控制等功能,帮助你在网上尽情表达自己。无论你是要发布你的艺术作品、音乐还是播客,Mastodon 都能为你服务。 feature_creativity_title: 无与伦比的创造力 - feature_moderation: Mastodon将决策权交还给你。每个服务器都会创建自己的规则和条例,并在站点内施行,而不是像企业社交媒体那样居高临下,这使得它可以最灵活地响应不同人群的需求。加入一个你认同其规则的服务器,或托管你自己的服务器。 + feature_moderation: Mastodon 将决策权交还给你。每个服务器都会创建自己的规则和条例,并在站点内施行,而不是像企业社交媒体那样居高临下,这使得它可以最灵活地响应不同人群的需求。加入一个你认同其规则的服务器,或托管你自己的服务器。 feature_moderation_title: 管理,本应如此 follow_action: 关注 - follow_step: 关注有趣的人,这就是Mastodon的意义所在。 + follow_step: 关注有趣的人,这就是 Mastodon 的意义所在。 follow_title: 个性化你的首页动态 follows_subtitle: 关注知名账户 follows_title: 推荐关注 @@ -1891,8 +1909,8 @@ zh-CN: post_step: 向世界打个招呼吧。 post_title: 发布你的第一条嘟文 share_action: 分享 - share_step: 让你的朋友知道如何在Mastodon找到你。 - share_title: 分享你的Mastodon个人资料 + share_step: 让你的朋友知道如何在 Mastodon 找到你。 + share_title: 分享你的 Mastodon 个人资料 sign_in_action: 登录 subject: 欢迎来到 Mastodon title: "%{name},欢迎你的加入!" diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 598c65d0494ec7..e33ebeadb4c096 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -1249,20 +1249,6 @@ zh-HK: merge_long: 留下舊有記錄並添加新的資訊 overwrite: 覆蓋 overwrite_long: 用新記錄覆蓋當前記錄 - overwrite_preambles: - blocking_html: 你將以%{filename}的最多%{total_items}個帳號,來取代你現有的封鎖列表。 - bookmarks_html: 你將以%{filename}的最多%{total_items}個帳號,來取代你現有的書籤。 - domain_blocking_html: 你將以%{filename}的最多%{total_items} 個帳號,來取代你現有的網域封鎖列表。 - following_html: 你將從%{filename}追蹤最多%{total_items} 個帳號,並取消追蹤其他人。 - lists_html: 你將根據%{filename}的內容取代的你列表。最多新增 %{total_items} 個帳號 到新列表。 - muting_html: 你將根據%{filename}中最多 %{total_items} 個帳號取代你的靜音帳號列表。 - preambles: - blocking_html: 你將根據%{filename}封鎖最多 %{total_items} 個帳號。 - bookmarks_html: 你將加入 %{filename} 中最多 %{total_items} 篇帖文到你的書籤中。 - domain_blocking_html: 你將封鎖來自%{filename}的最多 %{total_items} 個網域。 - following_html: 你將追蹤 來自 %{filename} 最多 %{total_items} 個帳號。 - lists_html: 你將加入來自%{filename}最多 %{total_items} 個帳號到你的列表中。如果現時沒有列表,將會建立新列表。 - muting_html: 你將靜音來自%{filename}的最多 %{total_items} 個帳號。 preface: 你可以在此匯入你在其他服務站所匯出的資料檔,包括︰你所關注的用戶,被你封鎖的用戶。 recent_imports: 最近的匯入 states: @@ -1564,7 +1550,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..d8fef10816d145 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -19,6 +19,7 @@ zh-TW: posts: other: 嘟文 posts_tab_heading: 嘟文 + self_follow_error: 無法跟隨您自己的帳號 admin: account_actions: action: 執行動作 @@ -863,6 +864,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 更新,請立即升級。 @@ -1146,9 +1150,11 @@ zh-TW: use_security_key: 使用安全金鑰 author_attribution: example_title: 範例文字 - hint_html: 控制如何於 Mastodon 上分享連結時註明您的貢獻。 + hint_html: 您是否正於 Mastodon 之外撰寫新聞或部落格文章?控制當它們於 Mastodon 上分享時您如何獲得信譽。 + instructions: 確認您文章 HTML 內容中包含此份程式碼: more_from_html: 來自 %{name} 之更多內容 s_blog: "%{name} 的部落格" + then_instructions: 接著,將發表處網域加入以下欄位中。 title: 作者署名 challenge: confirm: 繼續 @@ -1340,19 +1346,31 @@ zh-TW: overwrite: 覆蓋 overwrite_long: 以新的紀錄覆蓋目前紀錄 overwrite_preambles: - blocking_html: 您將要自 %{filename} 中之 %{total_items} 個帳號取代您的封鎖帳號列表。 - bookmarks_html: 您將要自 %{filename} 中之 %{total_items} 個嘟文取代您的書籤。 - domain_blocking_html: 您將要自 %{filename} 中之 %{total_items} 個網域取代您的封鎖網域列表。 - following_html: 您將要 跟隨%{filename} 中之 %{total_items} 個帳號 並且 取消跟隨其他所有人。 - lists_html: 您將以 %{filename} 之內容取代您的列表。這將會新增 %{total_items} 個帳號至新列表。 - muting_html: 您將要自 %{filename} 中之 %{total_items} 個帳號取代您的靜音帳號列表。 + blocking_html: + other: 您將要自 %{filename} 中之 %{count} 個帳號取代您的封鎖帳號列表。 + bookmarks_html: + other: 您將要自 %{filename} 中之 %{count} 個嘟文取代您的書籤。 + domain_blocking_html: + other: 您將要自 %{filename} 中之 %{count} 個網域取代您的封鎖網域列表。 + following_html: + other: 您將要 跟隨%{filename} 中之 %{count} 個帳號 並且 取消跟隨其他所有人。 + lists_html: + other: 您將以 %{filename} 之內容取代您的列表。這將會新增 %{count} 個帳號至新列表。 + muting_html: + other: 您將要自 %{filename} 中之 %{count} 個帳號取代您的靜音帳號列表。 preambles: - blocking_html: 您將要 封鎖%{filename} 中之 %{total_items} 個帳號。 - bookmarks_html: 您將要自 %{filename} 中之 %{total_items} 個嘟文加入至您的書籤。 - domain_blocking_html: 您將要 封鎖%{filename} 中之 %{total_items} 個網域。 - following_html: 您將要 跟隨%{filename} 中之 %{total_items} 個帳號。 - lists_html: 您將自 %{filename} 新增 %{total_items} 個帳號至您的列表。若不存在列表用以新增帳號,則會建立新列表。 - muting_html: 您將要 靜音%{filename} 中之 %{total_items} 個帳號。 + blocking_html: + other: 您將要 封鎖%{filename} 中之 %{count} 個帳號。 + bookmarks_html: + other: 您將要自 %{filename} 中之 %{count} 個嘟文加入至您的書籤。 + domain_blocking_html: + other: 您將要 封鎖%{filename} 中之 %{count} 個網域。 + following_html: + other: 您將要 跟隨%{filename} 中之 %{count} 個帳號。 + lists_html: + other: 您將自 %{filename} 新增 %{count} 個帳號至您的列表。若不存在列表用以新增帳號,則會建立新列表。 + muting_html: + other: 您將要 靜音%{filename} 中之 %{count} 個帳號。 preface: 您能於此匯入您於其他伺服器所匯出的資料檔,包括跟隨中的使用者、封鎖的使用者名單等。 recent_imports: 最近匯入的 states: diff --git a/config/navigation.rb b/config/navigation.rb index f5269d18ce39f3..2480e1741b64ba 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -30,18 +30,18 @@ n.item :filters, safe_join([material_symbol('filter_alt'), t('filters.index.title')]), filters_path, highlights_on: %r{/filters}, if: -> { current_user.functional? && !self_destruct } n.item :statuses_cleanup, safe_join([material_symbol('history'), t('settings.statuses_cleanup')]), statuses_cleanup_path, if: -> { current_user.functional_or_moved? && !self_destruct } - n.item :security, safe_join([material_symbol('lock'), t('settings.account')]), edit_user_registration_path do |s| - s.item :password, safe_join([material_symbol('lock'), t('settings.account_settings')]), edit_user_registration_path, highlights_on: %r{/auth/edit|/settings/delete|/settings/migration|/settings/aliases|/settings/login_activities|^/disputes} + n.item :security, safe_join([material_symbol('account_circle'), t('settings.account')]), edit_user_registration_path do |s| + s.item :password, safe_join([material_symbol('lock'), t('settings.account_settings')]), edit_user_registration_path, highlights_on: %r{^/auth|/settings/delete|/settings/migration|/settings/aliases|/settings/login_activities|^/disputes} s.item :two_factor_authentication, safe_join([material_symbol('safety_check'), t('settings.two_factor_authentication')]), settings_two_factor_authentication_methods_path, highlights_on: %r{/settings/two_factor_authentication|/settings/otp_authentication|/settings/security_keys} s.item :authorized_apps, safe_join([material_symbol('list_alt'), t('settings.authorized_apps')]), oauth_authorized_applications_path, if: -> { !self_destruct } end n.item :data, safe_join([material_symbol('cloud_sync'), t('settings.import_and_export')]), settings_export_path do |s| - s.item :import, safe_join([material_symbol('cloud_upload'), t('settings.import')]), settings_imports_path, if: -> { current_user.functional? && !self_destruct } + s.item :import, safe_join([material_symbol('cloud_upload'), t('settings.import')]), settings_imports_path, highlights_on: %r{/settings/imports}, if: -> { current_user.functional? && !self_destruct } s.item :export, safe_join([material_symbol('cloud_download'), t('settings.export')]), settings_export_path end - n.item :invites, safe_join([material_symbol('person_add'), t('invites.title')]), invites_path, if: -> { current_user.can?(:invite_users) && current_user.functional? && !self_destruct } + n.item :user_invites, safe_join([material_symbol('person_add'), t('invites.title')]), invites_path, if: -> { current_user.can?(:invite_users) && current_user.functional? && !self_destruct } n.item :development, safe_join([material_symbol('code'), t('settings.development')]), settings_applications_path, highlights_on: %r{/settings/applications}, if: -> { current_user.functional? && !self_destruct } n.item :trends, safe_join([material_symbol('trending_up'), t('admin.trends.title')]), admin_trends_statuses_path, if: -> { current_user.can?(:manage_taxonomies) && !self_destruct } do |s| @@ -57,7 +57,9 @@ s.item :accounts, safe_join([material_symbol('groups'), t('admin.accounts.title')]), admin_accounts_path(origin: 'local'), highlights_on: %r{/admin/accounts|admin/account_moderation_notes|/admin/pending_accounts|/admin/users}, if: -> { current_user.can?(:manage_users) } s.item :tags, safe_join([material_symbol('tag'), t('admin.tags.title')]), admin_tags_path, highlights_on: %r{/admin/tags}, if: -> { current_user.can?(:manage_taxonomies) } s.item :invites, safe_join([material_symbol('person_add'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) } - s.item :instances, safe_join([material_symbol('cloud'), t('admin.instances.title')]), admin_instances_path(limited: limited_federation_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) } + s.item :instances, safe_join([material_symbol('cloud'), t('admin.instances.title')]), admin_instances_path(limited: limited_federation_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows|/admin/export_domain_blocks}, if: lambda { + current_user.can?(:manage_federation) + } s.item :email_domain_blocks, safe_join([material_symbol('mail'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_path, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.can?(:manage_blocks) } s.item :ip_blocks, safe_join([material_symbol('hide_source'), t('admin.ip_blocks.title')]), admin_ip_blocks_path, highlights_on: %r{/admin/ip_blocks}, if: -> { current_user.can?(:manage_blocks) } s.item :action_logs, safe_join([material_symbol('list'), t('admin.action_logs.title')]), admin_action_logs_path, if: -> { current_user.can?(:view_audit_log) } diff --git a/config/routes.rb b/config/routes.rb index 86248dda412fc3..b04ffe096cc0ce 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -68,7 +68,7 @@ def redirect_with_vary(path) scope path: '.well-known' do scope module: :well_known do get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } - get 'host-meta', to: 'host_meta#show', as: :host_meta, defaults: { format: 'xml' } + get 'host-meta', to: 'host_meta#show', as: :host_meta get 'nodeinfo', to: 'node_info#index', as: :nodeinfo, defaults: { format: 'json' } get 'webfinger', to: 'webfinger#show', as: :webfinger end @@ -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/admin.rb b/config/routes/admin.rb index 78194f578980f8..334e806227cf1a 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -145,8 +145,10 @@ end resources :users, only: [] do - resource :two_factor_authentication, only: [:destroy], controller: 'users/two_factor_authentications' - resource :role, only: [:show, :update], controller: 'users/roles' + scope module: :users do + resource :two_factor_authentication, only: [:destroy] + resource :role, only: [:show, :update] + end end resources :custom_emojis, only: [:index, :new, :create] do 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/db/migrate/.rubocop.yml b/db/migrate/.rubocop.yml index 4e23800dd14965..6f8b6cc60da42e 100644 --- a/db/migrate/.rubocop.yml +++ b/db/migrate/.rubocop.yml @@ -2,3 +2,8 @@ inherit_from: ../../.rubocop.yml Naming/VariableNumber: CheckSymbols: false + +# Enabled here as workaround for https://docs.rubocop.org/rubocop/configuration.html#path-relativity +Rails/CreateTableWithTimestamps: + Include: + - '*.rb' diff --git a/db/migrate/20170508230434_create_conversation_mutes.rb b/db/migrate/20170508230434_create_conversation_mutes.rb index 01122c45166a92..4beba9dfa32009 100644 --- a/db/migrate/20170508230434_create_conversation_mutes.rb +++ b/db/migrate/20170508230434_create_conversation_mutes.rb @@ -2,7 +2,7 @@ class CreateConversationMutes < ActiveRecord::Migration[5.0] def change - create_table :conversation_mutes do |t| + create_table :conversation_mutes do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.integer :account_id, null: false t.bigint :conversation_id, null: false end diff --git a/db/migrate/20170823162448_create_status_pins.rb b/db/migrate/20170823162448_create_status_pins.rb index c8d3fab3a5128e..2cf3a85ca9de6b 100644 --- a/db/migrate/20170823162448_create_status_pins.rb +++ b/db/migrate/20170823162448_create_status_pins.rb @@ -2,7 +2,7 @@ class CreateStatusPins < ActiveRecord::Migration[5.1] def change - create_table :status_pins do |t| + create_table :status_pins do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.belongs_to :account, foreign_key: { on_delete: :cascade }, null: false t.belongs_to :status, foreign_key: { on_delete: :cascade }, null: false end diff --git a/db/migrate/20171116161857_create_list_accounts.rb b/db/migrate/20171116161857_create_list_accounts.rb index ff9ab3faad89bc..b0371e4c884771 100644 --- a/db/migrate/20171116161857_create_list_accounts.rb +++ b/db/migrate/20171116161857_create_list_accounts.rb @@ -2,7 +2,7 @@ class CreateListAccounts < ActiveRecord::Migration[5.2] def change - create_table :list_accounts do |t| + create_table :list_accounts do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.belongs_to :list, foreign_key: { on_delete: :cascade }, null: false t.belongs_to :account, foreign_key: { on_delete: :cascade }, null: false t.belongs_to :follow, foreign_key: { on_delete: :cascade }, null: false diff --git a/db/migrate/20180410220657_create_bookmarks.rb b/db/migrate/20180410220657_glitch_create_bookmarks.rb similarity index 70% rename from db/migrate/20180410220657_create_bookmarks.rb rename to db/migrate/20180410220657_glitch_create_bookmarks.rb index aba21f5eaae23f..5a2e0d35e5a691 100644 --- a/db/migrate/20180410220657_create_bookmarks.rb +++ b/db/migrate/20180410220657_glitch_create_bookmarks.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true -# This migration is a duplicate of 20180831171112 and may get ignored, see -# config/initializers/0_duplicate_migrations.rb +# This migration is a duplicate of 20180831171112 + +class GlitchCreateBookmarks < ActiveRecord::Migration[5.1] + def up + return if table_exists?(:bookmarks) -class CreateBookmarks < ActiveRecord::Migration[5.1] - def change create_table :bookmarks do |t| t.references :account, null: false t.references :status, null: false @@ -19,4 +20,6 @@ def change add_index :bookmarks, [:account_id, :status_id], unique: true end + + def down; end end diff --git a/db/migrate/20180831171112_create_bookmarks.rb b/db/migrate/20180831171112_create_bookmarks.rb index 4fa4c323d64858..88fb75a5977fa0 100644 --- a/db/migrate/20180831171112_create_bookmarks.rb +++ b/db/migrate/20180831171112_create_bookmarks.rb @@ -1,10 +1,11 @@ # frozen_string_literal: true -# This migration is a duplicate of 20180410220657 and may get ignored, see -# config/initializers/0_duplicate_migrations.rb +# This migration is a duplicate of 20180410220657 class CreateBookmarks < ActiveRecord::Migration[5.2] - def change + def up + return if table_exists?(:bookmarks) + create_table :bookmarks do |t| t.references :account, null: false t.references :status, null: false @@ -19,4 +20,8 @@ def change add_index :bookmarks, [:account_id, :status_id], unique: true end + + def down + drop_table :bookmarks + end end diff --git a/db/migrate/20180929222014_create_account_conversations.rb b/db/migrate/20180929222014_create_account_conversations.rb index 9386b86e7c9181..4e85e68d4771f5 100644 --- a/db/migrate/20180929222014_create_account_conversations.rb +++ b/db/migrate/20180929222014_create_account_conversations.rb @@ -2,7 +2,7 @@ class CreateAccountConversations < ActiveRecord::Migration[5.2] def change - create_table :account_conversations do |t| + create_table :account_conversations do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.belongs_to :account, foreign_key: { on_delete: :cascade } t.belongs_to :conversation, foreign_key: { on_delete: :cascade } t.bigint :participant_account_ids, array: true, null: false, default: [] diff --git a/db/migrate/20181007025445_create_pghero_space_stats.rb b/db/migrate/20181007025445_create_pghero_space_stats.rb index ddaf4aef31c6f0..696b53d8d77518 100644 --- a/db/migrate/20181007025445_create_pghero_space_stats.rb +++ b/db/migrate/20181007025445_create_pghero_space_stats.rb @@ -2,7 +2,7 @@ class CreatePgheroSpaceStats < ActiveRecord::Migration[5.2] def change - create_table :pghero_space_stats do |t| + create_table :pghero_space_stats do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.text :database t.text :schema t.text :relation diff --git a/db/migrate/20190103124649_create_scheduled_statuses.rb b/db/migrate/20190103124649_create_scheduled_statuses.rb index a66546187eed57..02b4916be86281 100644 --- a/db/migrate/20190103124649_create_scheduled_statuses.rb +++ b/db/migrate/20190103124649_create_scheduled_statuses.rb @@ -2,7 +2,7 @@ class CreateScheduledStatuses < ActiveRecord::Migration[5.2] def change - create_table :scheduled_statuses do |t| + create_table :scheduled_statuses do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.belongs_to :account, foreign_key: { on_delete: :cascade } t.datetime :scheduled_at, index: true t.jsonb :params diff --git a/db/migrate/20220824233535_create_status_trends.rb b/db/migrate/20220824233535_create_status_trends.rb index 52dcbf8f38e9e5..e68e5b7c11aa5d 100644 --- a/db/migrate/20220824233535_create_status_trends.rb +++ b/db/migrate/20220824233535_create_status_trends.rb @@ -2,7 +2,7 @@ class CreateStatusTrends < ActiveRecord::Migration[6.1] def change - create_table :status_trends do |t| + create_table :status_trends do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.references :status, null: false, foreign_key: { on_delete: :cascade }, index: { unique: true } t.references :account, null: false, foreign_key: { on_delete: :cascade } t.float :score, null: false, default: 0 diff --git a/db/migrate/20221006061337_create_preview_card_trends.rb b/db/migrate/20221006061337_create_preview_card_trends.rb index 934a06e24d1728..266f6440239751 100644 --- a/db/migrate/20221006061337_create_preview_card_trends.rb +++ b/db/migrate/20221006061337_create_preview_card_trends.rb @@ -2,7 +2,7 @@ class CreatePreviewCardTrends < ActiveRecord::Migration[6.1] def change - create_table :preview_card_trends do |t| + create_table :preview_card_trends do |t| # rubocop:disable Rails/CreateTableWithTimestamps t.references :preview_card, null: false, foreign_key: { on_delete: :cascade }, index: { unique: true } t.float :score, null: false, default: 0 t.integer :rank, null: false, default: 0 diff --git a/db/migrate/20241007071624_fix_notification_permission_foreign_keys.rb b/db/migrate/20241007071624_fix_notification_permission_foreign_keys.rb new file mode 100644 index 00000000000000..11b82de8a62bb7 --- /dev/null +++ b/db/migrate/20241007071624_fix_notification_permission_foreign_keys.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +class FixNotificationPermissionForeignKeys < ActiveRecord::Migration[7.1] + def up + safety_assured do + execute <<~SQL.squish + ALTER TABLE notification_permissions + DROP CONSTRAINT fk_rails_7c0bed08df, + ADD CONSTRAINT fk_rails_7c0bed08df + FOREIGN KEY (account_id) + REFERENCES accounts(id) + ON DELETE CASCADE, + + DROP CONSTRAINT fk_rails_e3e0aaad70, + ADD CONSTRAINT fk_rails_e3e0aaad70 + FOREIGN KEY (from_account_id) + REFERENCES accounts(id) + ON DELETE CASCADE + SQL + end + end + + def down + safety_assured do + execute <<~SQL.squish + ALTER TABLE notification_permissions + DROP CONSTRAINT fk_rails_7c0bed08df, + ADD CONSTRAINT fk_rails_7c0bed08df + FOREIGN KEY (account_id) + REFERENCES accounts(id), + + DROP CONSTRAINT fk_rails_e3e0aaad70, + ADD CONSTRAINT fk_rails_e3e0aaad70 + FOREIGN KEY (from_account_id) + REFERENCES accounts(id) + SQL + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 80a363dd381069..6335f7f31ac210 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_09_16_190140) do +ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1296,8 +1296,8 @@ add_foreign_key "mentions", "statuses", on_delete: :cascade add_foreign_key "mutes", "accounts", column: "target_account_id", name: "fk_eecff219ea", on_delete: :cascade add_foreign_key "mutes", "accounts", name: "fk_b8d8daf315", on_delete: :cascade - add_foreign_key "notification_permissions", "accounts" - add_foreign_key "notification_permissions", "accounts", column: "from_account_id" + add_foreign_key "notification_permissions", "accounts", column: "from_account_id", on_delete: :cascade + add_foreign_key "notification_permissions", "accounts", on_delete: :cascade add_foreign_key "notification_policies", "accounts", on_delete: :cascade add_foreign_key "notification_requests", "accounts", column: "from_account_id", on_delete: :cascade add_foreign_key "notification_requests", "accounts", on_delete: :cascade diff --git a/docker-compose.yml b/docker-compose.yml index c4e8cb73748122..37cb16497fbfb9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: web: # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # build: . - image: ghcr.io/mastodon/mastodon:v4.3.0-beta.2 + image: ghcr.io/mastodon/mastodon:v4.3.0 restart: always env_file: .env.production command: bundle exec puma -C config/puma.rb @@ -83,7 +83,7 @@ services: # build: # dockerfile: ./streaming/Dockerfile # context: . - image: ghcr.io/mastodon/mastodon-streaming:v4.3.0-beta.2 + image: ghcr.io/mastodon/mastodon-streaming:v4.3.0 restart: always env_file: .env.production command: node ./streaming/index.js @@ -101,7 +101,7 @@ services: sidekiq: build: . - image: ghcr.io/mastodon/mastodon:v4.3.0-beta.2 + image: ghcr.io/mastodon/mastodon:v4.3.0 restart: always env_file: .env.production command: bundle exec sidekiq diff --git a/lib/exceptions.rb b/lib/exceptions.rb index c2ff162a6e0881..1910d37a13ceee 100644 --- a/lib/exceptions.rb +++ b/lib/exceptions.rb @@ -36,4 +36,11 @@ def initialize(host) super() end end + + HTTP_CONNECTION_ERRORS = [ + HTTP::ConnectionError, + HTTP::Error, + HTTP::TimeoutError, + OpenSSL::SSL::SSLError, + ].freeze end diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb index 08a28e5f5c0c8b..e76735298f20f5 100644 --- a/lib/mastodon/cli/accounts.rb +++ b/lib/mastodon/cli/accounts.rb @@ -305,7 +305,7 @@ def cull(*domains) begin code = Request.new(:head, account.uri).perform(&:code) - rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Mastodon::PrivateNetworkAddressError + rescue *Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::PrivateNetworkAddressError skip_domains << account.domain end diff --git a/lib/mastodon/cli/ip_blocks.rb b/lib/mastodon/cli/ip_blocks.rb index 3c5fdb275c5105..ef24f2e047e30c 100644 --- a/lib/mastodon/cli/ip_blocks.rb +++ b/lib/mastodon/cli/ip_blocks.rb @@ -5,7 +5,7 @@ module Mastodon::CLI class IpBlocks < Base - option :severity, required: true, enum: %w(no_access sign_up_requires_approval sign_up_block), desc: 'Severity of the block' + option :severity, required: true, enum: IpBlock.severities.keys, desc: 'Severity of the block' option :comment, aliases: [:c], desc: 'Optional comment' option :duration, aliases: [:d], type: :numeric, desc: 'Duration of the block in seconds' option :force, type: :boolean, aliases: [:f], desc: 'Overwrite existing blocks' diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb index 70c11ee1a15b94..996b7fd92ca3b6 100644 --- a/lib/mastodon/cli/media.rb +++ b/lib/mastodon/cli/media.rb @@ -177,7 +177,7 @@ def remove_orphans attachment_name = path_segments[1].singularize file_name = path_segments.last - next unless PRELOAD_MODEL_WHITELIST.include?(model_name) + next unless PRELOADED_MODELS.include?(model_name) record = model_name.constantize.find_by(id: record_id) attachment = record&.public_send(attachment_name) @@ -278,14 +278,10 @@ def refresh desc 'usage', 'Calculate disk space consumed by Mastodon' def usage - say("Attachments:\t#{number_to_human_size(media_attachment_storage_size)} (#{number_to_human_size(local_media_attachment_storage_size)} local)") - say("Custom emoji:\t#{number_to_human_size(CustomEmoji.sum(:image_file_size))} (#{number_to_human_size(CustomEmoji.local.sum(:image_file_size))} local)") - say("Preview cards:\t#{number_to_human_size(PreviewCard.sum(:image_file_size))}") - say("Avatars:\t#{number_to_human_size(Account.sum(:avatar_file_size))} (#{number_to_human_size(Account.local.sum(:avatar_file_size))} local)") - say("Headers:\t#{number_to_human_size(Account.sum(:header_file_size))} (#{number_to_human_size(Account.local.sum(:header_file_size))} local)") - say("Backups:\t#{number_to_human_size(Backup.sum(:dump_file_size))}") - say("Imports:\t#{number_to_human_size(Import.sum(:data_file_size))}") - say("Settings:\t#{number_to_human_size(SiteUpload.sum(:file_file_size))}") + print_table [ + %w(Object Total Local), + *object_storage_summary, + ] end desc 'lookup URL', 'Lookup where media is displayed by passing a media URL' @@ -300,7 +296,7 @@ def lookup(url) model_name = path_segments.first.classify record_id = path_segments[2...-2].join.to_i - fail_with_message "Cannot find corresponding model: #{model_name}" unless PRELOAD_MODEL_WHITELIST.include?(model_name) + fail_with_message "Cannot find corresponding model: #{model_name}" unless PRELOADED_MODELS.include?(model_name) record = model_name.constantize.find_by(id: record_id) record = record.status if record.respond_to?(:status) @@ -318,23 +314,26 @@ def lookup(url) private - def media_attachment_storage_size - MediaAttachment.sum(file_and_thumbnail_size_sql) + def object_storage_summary + [ + [:attachments, MediaAttachment.sum(combined_media_sum), MediaAttachment.where(account: Account.local).sum(combined_media_sum)], + [:custom_emoji, CustomEmoji.sum(:image_file_size), CustomEmoji.local.sum(:image_file_size)], + [:avatars, Account.sum(:avatar_file_size), Account.local.sum(:avatar_file_size)], + [:headers, Account.sum(:header_file_size), Account.local.sum(:header_file_size)], + [:preview_cards, PreviewCard.sum(:image_file_size), nil], + [:backups, Backup.sum(:dump_file_size), nil], + [:imports, Import.sum(:data_file_size), nil], + [:settings, SiteUpload.sum(:file_file_size), nil], + ].map { |label, total, local| [label.to_s.titleize, number_to_human_size(total), local.present? ? number_to_human_size(local) : nil] } end - def local_media_attachment_storage_size - MediaAttachment.where(account: Account.local).sum(file_and_thumbnail_size_sql) + def combined_media_sum + Arel.sql(<<~SQL.squish) + COALESCE(file_file_size, 0) + COALESCE(thumbnail_file_size, 0) + SQL end - def file_and_thumbnail_size_sql - Arel.sql( - <<~SQL.squish - COALESCE(file_file_size, 0) + COALESCE(thumbnail_file_size, 0) - SQL - ) - end - - PRELOAD_MODEL_WHITELIST = %w( + PRELOADED_MODELS = %w( Account Backup CustomEmoji @@ -356,7 +355,7 @@ def preload_records_from_mixed_objects(objects) model_name = segments.first.classify record_id = segments[2...-2].join.to_i - next unless PRELOAD_MODEL_WHITELIST.include?(model_name) + next unless PRELOADED_MODELS.include?(model_name) preload_map[model_name] << record_id end diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index a5471704ad1a83..5bc32b1eaf605d 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -9,7 +9,7 @@ def major end def minor - 3 + 4 end def patch @@ -17,7 +17,7 @@ def patch end def default_prerelease - 'beta.2' + 'alpha.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/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index ed244d4a3ef44f..2b7cb10321a77e 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -21,7 +21,7 @@ module Config gemini ).freeze - CLASS_WHITELIST_TRANSFORMER = lambda do |env| + ALLOWED_CLASS_TRANSFORMER = lambda do |env| node = env[:node] class_list = node['class']&.split(/[\t\n\f\r ]/) @@ -99,7 +99,7 @@ module Config }, transformers: [ - CLASS_WHITELIST_TRANSFORMER, + ALLOWED_CLASS_TRANSFORMER, IMG_TAG_TRANSFORMER, TRANSLATE_TRANSFORMER, UNSUPPORTED_HREF_TRANSFORMER, @@ -163,7 +163,7 @@ module Config add_attributes: {}, transformers: [ - CLASS_WHITELIST_TRANSFORMER, + ALLOWED_CLASS_TRANSFORMER, IMG_TAG_TRANSFORMER, TRANSLATE_TRANSFORMER, UNSUPPORTED_HREF_TRANSFORMER, diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index d8bc927bc495ba..73de0c120faa09 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -7,8 +7,19 @@ namespace :db do namespace :encryption do desc 'Generate a set of keys for configuring Active Record encryption in a given environment' task :init do # rubocop:disable Rails/RakeEnvironment + if %w( + ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY + ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT + ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY + ).any? { |key| ENV.key?(key) } + pastel = Pastel.new + puts pastel.red(<<~MSG) + WARNING: It looks like encryption secrets have already been set. Please ensure you are not changing secrets for a Mastodon installation that already uses them, as this will cause data loss and other issues that are difficult to recover from. + MSG + end + puts <<~MSG - Add these secret environment variables to your Mastodon environment (e.g. .env.production):#{' '} + Add the following secret environment variables to your Mastodon environment (e.g. .env.production), ensure they are shared across all your nodes and do not change them after they are set:#{' '} ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=#{SecureRandom.alphanumeric(32)} ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=#{SecureRandom.alphanumeric(32)} diff --git a/lib/tasks/icons.rake b/lib/tasks/icons.rake index 96e0a143150584..9a05cf349914d2 100644 --- a/lib/tasks/icons.rake +++ b/lib/tasks/icons.rake @@ -38,6 +38,20 @@ def find_used_icons end end + Rails.root.join('config', 'navigation.rb').open('r') do |file| + pattern = /material_symbol\('(?[^']*)'\)/ + file.each_line do |line| + match = pattern.match(line) + next if match.blank? + + # navigation.rb only uses 400x24 icons, per material_symbol() in + # app/helpers/application_helper.rb + icons_by_weight_and_size[400] ||= {} + icons_by_weight_and_size[400][24] ||= Set.new + icons_by_weight_and_size[400][24] << match['icon'] + end + end + icons_by_weight_and_size end diff --git a/package.json b/package.json index 1a3c86f728d4de..81d4d8a01789f9 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,10 +42,13 @@ "@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", - "@rails/ujs": "7.1.400", + "@rails/ujs": "7.1.401", "@reduxjs/toolkit": "^2.0.1", "@svgr/webpack": "^5.5.0", "arrow-key-navigation": "^1.2.0", 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/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb deleted file mode 100644 index b6471e80b2766b..00000000000000 --- a/spec/controllers/admin/invites_controller_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Admin::InvitesController do - render_views - - let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - - before do - sign_in user, scope: :user - end - - describe 'GET #index' do - subject { get :index, params: { available: true } } - - let!(:invite) { Fabricate(:invite) } - - it 'renders index page' do - expect(subject).to render_template :index - expect(response.body) - .to include(invite.code) - end - end - - describe 'POST #create' do - subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } } - - it 'succeeds to create a invite' do - expect { subject }.to change(Invite, :count).by(1) - expect(subject).to redirect_to admin_invites_path - expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10) - end - end - - describe 'DELETE #destroy' do - subject { delete :destroy, params: { id: invite.id } } - - let!(:invite) { Fabricate(:invite, expires_at: nil) } - - it 'expires invite' do - expect(subject).to redirect_to admin_invites_path - expect(invite.reload).to be_expired - end - end - - describe 'POST #deactivate_all' do - before { Fabricate(:invite, expires_at: nil) } - - it 'expires all invites, then redirects to admin_invites_path' do - expect { post :deactivate_all } - .to change { Invite.exists?(expires_at: nil) } - .from(true) - .to(false) - - expect(response).to redirect_to admin_invites_path - end - end -end diff --git a/spec/controllers/admin/tags_controller_spec.rb b/spec/controllers/admin/tags_controller_spec.rb deleted file mode 100644 index 1df2bc400309a0..00000000000000 --- a/spec/controllers/admin/tags_controller_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Admin::TagsController do - render_views - - before do - sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')) - end - - describe 'GET #index' do - before do - Fabricate(:tag) - - tag_filter = instance_double(Admin::TagFilter, results: Tag.all) - allow(Admin::TagFilter).to receive(:new).and_return(tag_filter) - end - - let(:params) { { order: 'newest' } } - - it 'returns http success' do - get :index - - expect(response).to have_http_status(200) - expect(response).to render_template(:index) - - expect(Admin::TagFilter) - .to have_received(:new) - .with(hash_including(params)) - end - - describe 'with filters' do - let(:params) { { order: 'newest', name: 'test' } } - - it 'returns http success' do - get :index, params: { name: 'test' } - - expect(response).to have_http_status(200) - expect(response).to render_template(:index) - - expect(Admin::TagFilter) - .to have_received(:new) - .with(hash_including(params)) - end - end - end - - describe 'GET #show' do - let!(:tag) { Fabricate(:tag) } - - before do - get :show, params: { id: tag.id } - end - - it 'returns status 200' do - expect(response).to have_http_status(200) - end - end - - describe 'PUT #update' do - let!(:tag) { Fabricate(:tag, listable: false) } - - context 'with valid params' do - it 'updates the tag' do - put :update, params: { id: tag.id, tag: { listable: '1' } } - - expect(response).to redirect_to(admin_tag_path(tag.id)) - expect(tag.reload).to be_listable - end - end - - context 'with invalid params' do - it 'does not update the tag' do - put :update, params: { id: tag.id, tag: { name: 'cant-change-name' } } - - expect(response).to have_http_status(200) - expect(response).to render_template(:show) - end - end - end -end diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index 713ea3ff16c5bf..4a6956cb095e1c 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -208,7 +208,7 @@ context 'when using two-factor authentication' do context 'with OTP enabled as second factor' do let!(:user) do - Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) + Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret) end let!(:recovery_codes) do @@ -230,7 +230,7 @@ context 'when using email and password after an unfinished log-in attempt to a 2FA-protected account' do let!(:other_user) do - Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) + Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret) end before do @@ -342,7 +342,7 @@ context 'with WebAuthn and OTP enabled as second factor' do let!(:user) do - Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) + Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret) end let!(:webauthn_credential) do 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/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb index 34eaacdf498f96..224310b7ef3043 100644 --- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb @@ -18,7 +18,7 @@ def qr_code_markup RQRCode::QRCode.new( 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io' - ).as_svg(padding: 0, module_size: 4) + ).as_svg(padding: 0, module_size: 4, use_path: true) end end diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb index d9702251f41d0a..121e4aa6c6f9e6 100644 --- a/spec/controllers/statuses_controller_spec.rb +++ b/spec/controllers/statuses_controller_spec.rb @@ -736,76 +736,4 @@ end end end - - describe 'GET #embed' do - let(:account) { Fabricate(:account) } - let(:status) { Fabricate(:status, account: account) } - - context 'when account is suspended' do - let(:account) { Fabricate(:account, suspended: true) } - - before do - get :embed, params: { account_username: account.username, id: status.id } - end - - it 'returns http gone' do - expect(response).to have_http_status(410) - end - end - - context 'when status is a reblog' do - let(:original_account) { Fabricate(:account, domain: 'example.com') } - let(:original_status) { Fabricate(:status, account: original_account, url: 'https://example.com/123') } - let(:status) { Fabricate(:status, account: account, reblog: original_status) } - - before do - get :embed, params: { account_username: status.account.username, id: status.id } - end - - it 'returns http not found' do - expect(response).to have_http_status(404) - end - end - - context 'when status is public' do - before do - get :embed, params: { account_username: status.account.username, id: status.id } - end - - it 'renders status successfully', :aggregate_failures do - expect(response) - .to have_http_status(200) - .and render_template(:embed) - expect(response.headers).to include( - 'Vary' => 'Accept, Accept-Language, Cookie', - 'Cache-Control' => include('public'), - 'Link' => include('activity+json') - ) - end - end - - context 'when status is private' do - let(:status) { Fabricate(:status, account: account, visibility: :private) } - - before do - get :embed, params: { account_username: status.account.username, id: status.id } - end - - it 'returns http not found' do - expect(response).to have_http_status(404) - end - end - - context 'when status is direct' do - let(:status) { Fabricate(:status, account: account, visibility: :direct) } - - before do - get :embed, params: { account_username: status.account.username, id: status.id } - end - - it 'returns http not found' do - expect(response).to have_http_status(404) - end - end - end end diff --git a/spec/fabricators/account_domain_block_fabricator.rb b/spec/fabricators/account_domain_block_fabricator.rb index 83df509da2cc85..a211b7c6667031 100644 --- a/spec/fabricators/account_domain_block_fabricator.rb +++ b/spec/fabricators/account_domain_block_fabricator.rb @@ -2,5 +2,5 @@ Fabricator(:account_domain_block) do account { Fabricate.build(:account) } - domain 'example.com' + domain { sequence { |n| "host-#{n}.example" } } end diff --git a/spec/fabricators/ip_block_fabricator.rb b/spec/fabricators/ip_block_fabricator.rb new file mode 100644 index 00000000000000..30c48b90c6f4b4 --- /dev/null +++ b/spec/fabricators/ip_block_fabricator.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +Fabricator(:ip_block) do + severity { :sign_up_requires_approval } + ip { sequence(:ip) { |n| "10.0.0.#{n}" } } +end diff --git a/spec/helpers/formatting_helper_spec.rb b/spec/helpers/formatting_helper_spec.rb index 136a609b1c9cf4..5ff534e4eb3873 100644 --- a/spec/helpers/formatting_helper_spec.rb +++ b/spec/helpers/formatting_helper_spec.rb @@ -6,19 +6,57 @@ include Devise::Test::ControllerHelpers describe '#rss_status_content_format' do - let(:status) { Fabricate(:status, text: 'Hello world<>', spoiler_text: 'This is a spoiler<>', poll: Fabricate(:poll, options: %w(Yes<> No))) } - let(:html) { helper.rss_status_content_format(status) } + subject { helper.rss_status_content_format(status) } - it 'renders the spoiler text' do - expect(html).to include('

This is a spoiler<>


') + context 'with a simple status' do + let(:status) { Fabricate.build :status, text: 'Hello world' } + + it 'renders the formatted elements' do + expect(parsed_result.css('p').first.text) + .to eq('Hello world') + end end - it 'renders the status text' do - expect(html).to include('

Hello world<>

') + context 'with a spoiler and an emoji and a poll' do + let(:status) { Fabricate(:status, text: 'Hello :world: <>', spoiler_text: 'This is a spoiler<>', poll: Fabricate(:poll, options: %w(Yes<> No))) } + + before { Fabricate :custom_emoji, shortcode: 'world' } + + it 'renders the formatted elements' do + expect(spoiler_node.css('strong').text) + .to eq('Content warning:') + expect(spoiler_node.text) + .to include('This is a spoiler<>') + expect(content_node.text) + .to eq('Hello <>') + expect(content_node.css('img').first.to_h.symbolize_keys) + .to include( + rel: 'emoji', + title: ':world:' + ) + expect(poll_node.css('radio').first.text) + .to eq('Yes<>') + expect(poll_node.css('radio').first.to_h.symbolize_keys) + .to include( + disabled: 'disabled' + ) + end + + def spoiler_node + parsed_result.css('p').first + end + + def content_node + parsed_result.css('p')[1] + end + + def poll_node + parsed_result.css('p').last + end end - it 'renders the poll' do - expect(html).to include('Yes<>
') + def parsed_result + Nokogiri::HTML.fragment(subject) end end end diff --git a/spec/lib/account_reach_finder_spec.rb b/spec/lib/account_reach_finder_spec.rb index e5d85656a200c4..0c1d92b2da59af 100644 --- a/spec/lib/account_reach_finder_spec.rb +++ b/spec/lib/account_reach_finder_spec.rb @@ -38,16 +38,23 @@ end describe '#inboxes' do - it 'includes the preferred inbox URL of followers' do - expect(described_class.new(account).inboxes).to include(*[ap_follower_example_com, ap_follower_example_org, ap_follower_with_shared].map(&:preferred_inbox_url)) + subject { described_class.new(account).inboxes } + + it 'includes the preferred inbox URL of followers and recently mentioned accounts but not unrelated users' do + expect(subject) + .to include(*follower_inbox_urls) + .and include(*mentioned_account_inbox_urls) + .and not_include(unrelated_account.preferred_inbox_url) end - it 'includes the preferred inbox URL of recently-mentioned accounts' do - expect(described_class.new(account).inboxes).to include(*[ap_mentioned_with_shared, ap_mentioned_example_com, ap_mentioned_example_org].map(&:preferred_inbox_url)) + def follower_inbox_urls + [ap_follower_example_com, ap_follower_example_org, ap_follower_with_shared] + .map(&:preferred_inbox_url) end - it 'does not include the inbox of unrelated users' do - expect(described_class.new(account).inboxes).to_not include(unrelated_account.preferred_inbox_url) + def mentioned_account_inbox_urls + [ap_mentioned_with_shared, ap_mentioned_example_com, ap_mentioned_example_org] + .map(&:preferred_inbox_url) end end end diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 6f68984018c1d2..385628852b714d 100644 --- a/spec/lib/activitypub/activity/block_spec.rb +++ b/spec/lib/activitypub/activity/block_spec.rb @@ -3,6 +3,8 @@ require 'rails_helper' RSpec.describe ActivityPub::Activity::Block do + subject { described_class.new(json, sender) } + let(:sender) { Fabricate(:account) } let(:recipient) { Fabricate(:account) } @@ -16,93 +18,65 @@ }.with_indifferent_access end - context 'when the recipient does not follow the sender' do - describe '#perform' do - subject { described_class.new(json, sender) } - - before do + describe '#perform' do + context 'when the recipient does not follow the sender' do + it 'creates a block from sender to recipient' do subject.perform - end - it 'creates a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be true + expect(sender) + .to be_blocking(recipient) end end - end - - context 'when the recipient is already blocked' do - before do - sender.block!(recipient, uri: 'old') - end - describe '#perform' do - subject { described_class.new(json, sender) } + context 'when the recipient is already blocked' do + before { sender.block!(recipient, uri: 'old') } - before do + it 'creates a block from sender to recipient and sets uri to last received block activity' do subject.perform - end - - it 'creates a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be true - end - it 'sets the uri to that of last received block activity' do - expect(sender.block_relationships.find_by(target_account: recipient).uri).to eq 'foo' + expect(sender) + .to be_blocking(recipient) + expect(sender.block_relationships.find_by(target_account: recipient).uri) + .to eq 'foo' end end - end - context 'when the recipient follows the sender' do - before do - recipient.follow!(sender) - end + context 'when the recipient follows the sender' do + before { recipient.follow!(sender) } - describe '#perform' do - subject { described_class.new(json, sender) } - - before do + it 'creates a block from sender to recipient and ensures recipient not following sender' do subject.perform - end - - it 'creates a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be true - end - it 'ensures recipient is not following sender' do - expect(recipient.following?(sender)).to be false + expect(sender) + .to be_blocking(recipient) + expect(recipient) + .to_not be_following(sender) end end - end - context 'when a matching undo has been received first' do - let(:undo_json) do - { - '@context': 'https://www.w3.org/ns/activitystreams', - id: 'bar', - type: 'Undo', - actor: ActivityPub::TagManager.instance.uri_for(sender), - object: json, - }.with_indifferent_access - end - - before do - recipient.follow!(sender) - ActivityPub::Activity::Undo.new(undo_json, sender).perform - end - - describe '#perform' do - subject { described_class.new(json, sender) } + context 'when a matching undo has been received first' do + let(:undo_json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'bar', + type: 'Undo', + actor: ActivityPub::TagManager.instance.uri_for(sender), + object: json, + }.with_indifferent_access + end before do - subject.perform + recipient.follow!(sender) + ActivityPub::Activity::Undo.new(undo_json, sender).perform end - it 'does not create a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be false - end + it 'does not create a block from sender to recipient and ensures recipient not following sender' do + subject.perform - it 'ensures recipient is not following sender' do - expect(recipient.following?(sender)).to be false + expect(sender) + .to_not be_blocking(recipient) + expect(recipient) + .to_not be_following(sender) end end end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 83ea6566e41402..ab69a4693db6c5 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -63,6 +63,24 @@ } end + let(:invalid_mention_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), 'post2'].join('/'), + type: 'Note', + to: [ + 'https://www.w3.org/ns/activitystreams#Public', + ActivityPub::TagManager.instance.uri_for(follower), + ], + content: '@bob lorem ipsum', + published: 1.hour.ago.utc.iso8601, + updated: 1.hour.ago.utc.iso8601, + tag: { + type: 'Mention', + href: 'http://notexisting.dontexistingtld/actor', + }, + } + end + def activity_for_object(json) { '@context': 'https://www.w3.org/ns/activitystreams', @@ -117,6 +135,25 @@ def activity_for_object(json) # Creates two notifications expect(Notification.count).to eq 2 end + + it 'ignores unprocessable mention', :aggregate_failures do + stub_request(:get, invalid_mention_json[:tag][:href]).to_raise(HTTP::ConnectionError) + # When receiving the post that contains an invalid mention… + described_class.new(activity_for_object(invalid_mention_json), sender, delivery: true).perform + + # NOTE: Refering explicitly to the workers is a bit awkward + DistributionWorker.drain + FeedInsertWorker.drain + + # …it creates a status + status = Status.find_by(uri: invalid_mention_json[:id]) + + # Check the process did not crash + expect(status.nil?).to be false + + # It has queued a mention resolve job + expect(MentionResolveWorker).to have_enqueued_sidekiq_job(status.id, invalid_mention_json[:tag][:href], anything) + end end describe '#perform' 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/plain_text_formatter_spec.rb b/spec/lib/plain_text_formatter_spec.rb index b22f473d0ce320..4683e150935f46 100644 --- a/spec/lib/plain_text_formatter_spec.rb +++ b/spec/lib/plain_text_formatter_spec.rb @@ -7,7 +7,7 @@ subject { described_class.new(status.text, status.local?).to_s } context 'when status is local' do - let(:status) { Fabricate(:status, text: '

a text by a nerd who uses an HTML tag in text

', uri: nil) } + let(:status) { Fabricate.build(:status, text: '

a text by a nerd who uses an HTML tag in text

', uri: nil) } it 'returns the raw text' do expect(subject).to eq '

a text by a nerd who uses an HTML tag in text

' @@ -15,10 +15,10 @@ end context 'when status is remote' do - let(:remote_account) { Fabricate(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/') } + let(:remote_account) { Fabricate.build(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/') } context 'when text contains inline HTML tags' do - let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem ipsum') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem ipsum') } it 'strips the tags' do expect(subject).to eq 'Lorem ipsum' @@ -26,7 +26,7 @@ end context 'when text contains

tags' do - let(:status) { Fabricate(:status, account: remote_account, text: '

Lorem

ipsum

') } + let(:status) { Fabricate.build(:status, account: remote_account, text: '

Lorem

ipsum

') } it 'inserts a newline' do expect(subject).to eq "Lorem\nipsum" @@ -34,7 +34,7 @@ end context 'when text contains a single
tag' do - let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem
ipsum') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem
ipsum') } it 'inserts a newline' do expect(subject).to eq "Lorem\nipsum" @@ -42,7 +42,7 @@ end context 'when text contains consecutive
tag' do - let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem


ipsum') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem


ipsum') } it 'inserts a single newline' do expect(subject).to eq "Lorem\nipsum" @@ -50,7 +50,7 @@ end context 'when text contains HTML entity' do - let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem & ipsum ❤') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem & ipsum ❤') } it 'unescapes the entity' do expect(subject).to eq 'Lorem & ipsum ❤' @@ -58,7 +58,7 @@ end context 'when text contains ipsum') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem ipsum') } it 'strips the tag and its contents' do expect(subject).to eq 'Lorem ipsum' @@ -66,7 +66,7 @@ end context 'when text contains an HTML comment tags' do - let(:status) { Fabricate(:status, account: remote_account, text: 'Lorem ipsum') } + let(:status) { Fabricate.build(:status, account: remote_account, text: 'Lorem ipsum') } it 'strips the comment' do expect(subject).to eq 'Lorem ipsum' @@ -74,7 +74,7 @@ end context 'when text contains HTML ruby tags' do - let(:status) { Fabricate(:status, account: remote_account, text: '

Lorem 明日 (Ashita) ipsum

') } + let(:status) { Fabricate.build(:status, account: remote_account, text: '

Lorem 明日 (Ashita) ipsum

') } it 'strips the comment' do expect(subject).to eq 'Lorem 明日 (Ashita) ipsum' 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/lib/vacuum/access_tokens_vacuum_spec.rb b/spec/lib/vacuum/access_tokens_vacuum_spec.rb index 54760c41bd4531..8768f6b2dc170c 100644 --- a/spec/lib/vacuum/access_tokens_vacuum_spec.rb +++ b/spec/lib/vacuum/access_tokens_vacuum_spec.rb @@ -14,32 +14,24 @@ let!(:expired_access_grant) { Fabricate(:access_grant, expires_in: 59.minutes.to_i, created_at: 1.hour.ago) } let!(:active_access_grant) { Fabricate(:access_grant) } - before do + it 'deletes revoked/expired access tokens and revoked/expired grants, but preserves active tokens/grants' do subject.perform - end - - it 'deletes revoked access tokens' do - expect { revoked_access_token.reload }.to raise_error ActiveRecord::RecordNotFound - end - - it 'deletes expired access tokens' do - expect { expired_access_token.reload }.to raise_error ActiveRecord::RecordNotFound - end - it 'deletes revoked access grants' do - expect { revoked_access_grant.reload }.to raise_error ActiveRecord::RecordNotFound - end + expect { revoked_access_token.reload } + .to raise_error ActiveRecord::RecordNotFound + expect { expired_access_token.reload } + .to raise_error ActiveRecord::RecordNotFound - it 'deletes expired access grants' do - expect { expired_access_grant.reload }.to raise_error ActiveRecord::RecordNotFound - end + expect { revoked_access_grant.reload } + .to raise_error ActiveRecord::RecordNotFound + expect { expired_access_grant.reload } + .to raise_error ActiveRecord::RecordNotFound - it 'does not delete active access tokens' do - expect { active_access_token.reload }.to_not raise_error - end + expect { active_access_token.reload } + .to_not raise_error - it 'does not delete active access grants' do - expect { active_access_grant.reload }.to_not raise_error + expect { active_access_grant.reload } + .to_not raise_error end end end diff --git a/spec/lib/vacuum/backups_vacuum_spec.rb b/spec/lib/vacuum/backups_vacuum_spec.rb index 867dbe4020c1f0..4a025352cbf7b7 100644 --- a/spec/lib/vacuum/backups_vacuum_spec.rb +++ b/spec/lib/vacuum/backups_vacuum_spec.rb @@ -11,16 +11,13 @@ let!(:expired_backup) { Fabricate(:backup, created_at: (retention_period + 1.day).ago) } let!(:current_backup) { Fabricate(:backup) } - before do + it 'deletes backups past the retention period but preserves those within the period' do subject.perform - end - - it 'deletes backups past the retention period' do - expect { expired_backup.reload }.to raise_error ActiveRecord::RecordNotFound - end - it 'does not delete backups within the retention period' do - expect { current_backup.reload }.to_not raise_error + expect { expired_backup.reload } + .to raise_error ActiveRecord::RecordNotFound + expect { current_backup.reload } + .to_not raise_error end end end diff --git a/spec/lib/vacuum/feeds_vacuum_spec.rb b/spec/lib/vacuum/feeds_vacuum_spec.rb index ede1e3c36097e6..38459a558fbab1 100644 --- a/spec/lib/vacuum/feeds_vacuum_spec.rb +++ b/spec/lib/vacuum/feeds_vacuum_spec.rb @@ -14,11 +14,11 @@ redis.zadd(feed_key_for(active_user), 1, 1) redis.zadd(feed_key_for(inactive_user, 'reblogs'), 2, 2) redis.sadd(feed_key_for(inactive_user, 'reblogs:2'), 3) - - subject.perform end it 'clears feeds of inactive users and lists' do + subject.perform + expect(redis.zcard(feed_key_for(inactive_user))).to eq 0 expect(redis.zcard(feed_key_for(active_user))).to eq 1 expect(redis.exists?(feed_key_for(inactive_user, 'reblogs'))).to be false diff --git a/spec/lib/vacuum/media_attachments_vacuum_spec.rb b/spec/lib/vacuum/media_attachments_vacuum_spec.rb index 1039c36cea6ff2..f7749038cb432e 100644 --- a/spec/lib/vacuum/media_attachments_vacuum_spec.rb +++ b/spec/lib/vacuum/media_attachments_vacuum_spec.rb @@ -17,9 +17,9 @@ let!(:old_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 10.days.ago) } let!(:new_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 1.hour.ago) } - before { subject.perform } - it 'handles attachments based on metadata details' do + subject.perform + expect(old_remote_media.reload.file) # Remote and past retention period .to be_blank expect(old_local_media.reload.file) # Local and past retention diff --git a/spec/lib/vacuum/preview_cards_vacuum_spec.rb b/spec/lib/vacuum/preview_cards_vacuum_spec.rb index 9dbdf0bc2fe70c..caeedd3269b5db 100644 --- a/spec/lib/vacuum/preview_cards_vacuum_spec.rb +++ b/spec/lib/vacuum/preview_cards_vacuum_spec.rb @@ -15,24 +15,22 @@ before do old_preview_card.statuses << Fabricate(:status) new_preview_card.statuses << Fabricate(:status) + end + it 'handles preview card cleanup' do subject.perform - end - it 'deletes cache of preview cards last updated before the retention period' do - expect(old_preview_card.reload.image).to be_blank - end + expect(old_preview_card.reload.image) # last updated before retention period + .to be_blank - it 'does not delete cache of preview cards last updated within the retention period' do - expect(new_preview_card.reload.image).to_not be_blank - end + expect(new_preview_card.reload.image) # last updated within the retention period + .to_not be_blank - it 'does not delete attached preview cards' do - expect(new_preview_card.reload).to be_persisted - end + expect(new_preview_card.reload) # Keep attached preview cards + .to be_persisted - it 'does not delete orphaned preview cards in the retention period' do - expect(orphaned_preview_card.reload).to be_persisted + expect(orphaned_preview_card.reload) # keep orphaned cards in the retention period + .to be_persisted end end end diff --git a/spec/lib/vacuum/statuses_vacuum_spec.rb b/spec/lib/vacuum/statuses_vacuum_spec.rb index d5c01395064e16..1fff8648797a8e 100644 --- a/spec/lib/vacuum/statuses_vacuum_spec.rb +++ b/spec/lib/vacuum/statuses_vacuum_spec.rb @@ -15,24 +15,20 @@ let!(:local_status_old) { Fabricate(:status, created_at: (retention_period + 2.days).ago) } let!(:local_status_recent) { Fabricate(:status, created_at: (retention_period - 2.days).ago) } - before do + it 'deletes remote statuses past the retention period and keeps others' do subject.perform - end - it 'deletes remote statuses past the retention period' do - expect { remote_status_old.reload }.to raise_error ActiveRecord::RecordNotFound - end + expect { remote_status_old.reload } + .to raise_error ActiveRecord::RecordNotFound - it 'does not delete local statuses past the retention period' do - expect { local_status_old.reload }.to_not raise_error - end + expect { local_status_old.reload } + .to_not raise_error - it 'does not delete remote statuses within the retention period' do - expect { remote_status_recent.reload }.to_not raise_error - end + expect { remote_status_recent.reload } + .to_not raise_error - it 'does not delete local statuses within the retention period' do - expect { local_status_recent.reload }.to_not raise_error + expect { local_status_recent.reload } + .to_not raise_error end end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index eab196166d3219..d97c01858da6b9 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -3,43 +3,39 @@ require 'rails_helper' RSpec.describe NotificationMailer do - 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')) + 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 - 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)) + shared_examples 'delivery without status' do + context 'when notification target_status is missing' do + before { allow(notification).to receive(:target_status).and_return(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') } + 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 +43,12 @@ .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' + include_examples 'delivery without status' end describe 'follow' do @@ -56,14 +57,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 +75,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 +82,12 @@ .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' + include_examples 'delivery without status' end describe 'reblog' do @@ -90,8 +96,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 +103,12 @@ .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' + include_examples 'delivery without status' end describe 'follow_request' do @@ -108,14 +117,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/account_statuses_cleanup_policy_spec.rb b/spec/models/account_statuses_cleanup_policy_spec.rb index a08fd723a4d8f4..c142a0359ac6fe 100644 --- a/spec/models/account_statuses_cleanup_policy_spec.rb +++ b/spec/models/account_statuses_cleanup_policy_spec.rb @@ -16,6 +16,8 @@ describe 'save hooks' do context 'when widening a policy' do + subject { account_statuses_cleanup_policy.last_inspected } + let!(:account_statuses_cleanup_policy) do Fabricate(:account_statuses_cleanup_policy, account: account, @@ -33,64 +35,64 @@ account_statuses_cleanup_policy.record_last_inspected(42) end - it 'invalidates last_inspected when widened because of keep_direct' do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_direct' do + before { account_statuses_cleanup_policy.update(keep_direct: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of keep_pinned' do - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_pinned' do + before { account_statuses_cleanup_policy.update(keep_pinned: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of keep_polls' do - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_polls' do + before { account_statuses_cleanup_policy.update(keep_polls: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of keep_media' do - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_media' do + before { account_statuses_cleanup_policy.update(keep_media: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of keep_self_fav' do - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_self_fav' do + before { account_statuses_cleanup_policy.update(keep_self_fav: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of keep_self_bookmark' do - account_statuses_cleanup_policy.keep_self_bookmark = false - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of keep_self_bookmark' do + before { account_statuses_cleanup_policy.update(keep_self_bookmark: false) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of higher min_favs' do - account_statuses_cleanup_policy.min_favs = 5 - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of higher min_favs' do + before { account_statuses_cleanup_policy.update(min_favs: 5) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of disabled min_favs' do - account_statuses_cleanup_policy.min_favs = nil - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of disabled min_favs' do + before { account_statuses_cleanup_policy.update(min_favs: nil) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of higher min_reblogs' do - account_statuses_cleanup_policy.min_reblogs = 5 - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of higher min_reblogs' do + before { account_statuses_cleanup_policy.update(min_reblogs: 5) } + + it { is_expected.to be_nil } end - it 'invalidates last_inspected when widened because of disable min_reblogs' do - account_statuses_cleanup_policy.min_reblogs = nil - account_statuses_cleanup_policy.save - expect(account_statuses_cleanup_policy.last_inspected).to be_nil + context 'when widened because of disable min_reblogs' do + before { account_statuses_cleanup_policy.update(min_reblogs: nil) } + + it { is_expected.to be_nil } end end diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb index 84f0f318f42583..62d7e40e28cef7 100644 --- a/spec/models/block_spec.rb +++ b/spec/models/block_spec.rb @@ -3,11 +3,37 @@ require 'rails_helper' RSpec.describe Block do - describe 'validations' do + describe 'Associations' do it { is_expected.to belong_to(:account).required } it { is_expected.to belong_to(:target_account).required } end + describe '#local?' do + it { is_expected.to_not be_local } + end + + describe 'Callbacks' do + describe 'Setting a URI' do + context 'when URI exists' do + subject { Fabricate.build :block, uri: 'https://uri/value' } + + it 'does not change' do + expect { subject.save } + .to not_change(subject, :uri) + end + end + + context 'when URI is blank' do + subject { Fabricate.build :follow, uri: nil } + + it 'populates the value' do + expect { subject.save } + .to change(subject, :uri).to(be_present) + end + end + end + end + it 'removes blocking cache after creation' do account = Fabricate(:account) target_account = Fabricate(:account) diff --git a/spec/models/domain_block_spec.rb b/spec/models/domain_block_spec.rb index 8278454cd7811a..14f904ea7fa6a5 100644 --- a/spec/models/domain_block_spec.rb +++ b/spec/models/domain_block_spec.rb @@ -3,14 +3,13 @@ require 'rails_helper' RSpec.describe DomainBlock do - describe 'validations' do + describe 'Validations' do it { is_expected.to validate_presence_of(:domain) } - it 'is invalid if the same normalized domain already exists' do - _domain_block = Fabricate(:domain_block, domain: 'にゃん') - domain_block_with_normalized_value = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b') - domain_block_with_normalized_value.valid? - expect(domain_block_with_normalized_value).to model_have_error_on_field(:domain) + context 'when a normalized domain exists' do + before { Fabricate(:domain_block, domain: 'にゃん') } + + it { is_expected.to_not allow_value('xn--r9j5b5b').for(:domain) } end end @@ -105,4 +104,26 @@ end end end + + describe '#policies' do + subject { domain_block.policies } + + context 'when severity is suspend' do + let(:domain_block) { Fabricate.build :domain_block, severity: :suspend } + + it { is_expected.to eq(%i(suspend)) } + end + + context 'when severity is noop' do + let(:domain_block) { Fabricate.build :domain_block, severity: :noop, reject_media: true } + + it { is_expected.to eq(%i(reject_media)) } + end + + context 'when severity is silence' do + let(:domain_block) { Fabricate.build :domain_block, severity: :silence, reject_reports: true } + + it { is_expected.to eq(%i(silence reject_reports)) } + end + end end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index 06bf07ed78a314..81aaf8858556fe 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -3,66 +3,104 @@ require 'rails_helper' RSpec.describe Export do + subject { described_class.new(account) } + let(:account) { Fabricate(:account) } let(:target_accounts) do - [{}, { username: 'one', domain: 'local.host' }].map(&method(:Fabricate).curry(2).call(:account)) + [ + Fabricate(:account), + Fabricate(:account, username: 'one', domain: 'local.host'), + ] end - describe 'to_csv' do - it 'returns a csv of the blocked accounts' do - target_accounts.each { |target_account| account.block!(target_account) } + describe '#to_bookmarks_csv' do + before { Fabricate.times(2, :bookmark, account: account) } - export = described_class.new(account).to_blocked_accounts_csv - results = export.strip.split + let(:export) { CSV.parse(subject.to_bookmarks_csv) } - expect(results.size).to eq 2 - expect(results.first).to eq 'one@local.host' + it 'returns a csv of bookmarks' do + expect(export) + .to contain_exactly( + include(/statuses/), + include(/statuses/) + ) end + end - it 'returns a csv of the muted accounts' do - target_accounts.each { |target_account| account.mute!(target_account) } + describe '#to_blocked_accounts_csv' do + before { target_accounts.each { |target_account| account.block!(target_account) } } - export = described_class.new(account).to_muted_accounts_csv - results = export.strip.split("\n") + let(:export) { CSV.parse(subject.to_blocked_accounts_csv) } - expect(results.size).to eq 3 - expect(results.first).to eq 'Account address,Hide notifications' - expect(results.second).to eq 'one@local.host,true' + it 'returns a csv of the blocked accounts' do + expect(export) + .to contain_exactly( + include('one@local.host'), + include(be_present) + ) end + end - it 'returns a csv of the following accounts' do - target_accounts.each { |target_account| account.follow!(target_account) } + describe '#to_muted_accounts_csv' do + before { target_accounts.each { |target_account| account.mute!(target_account) } } - export = described_class.new(account).to_following_accounts_csv - results = export.strip.split("\n") + let(:export) { CSV.parse(subject.to_muted_accounts_csv) } - expect(results.size).to eq 3 - expect(results.first).to eq 'Account address,Show boosts,Notify on new posts,Languages' - expect(results.second).to eq 'one@local.host,true,false,' + it 'returns a csv of the muted accounts' do + expect(export) + .to contain_exactly( + contain_exactly('Account address', 'Hide notifications'), + include('one@local.host', 'true'), + include(be_present) + ) end end - describe 'total_storage' do - it 'returns the total size of the media attachments' do - media_attachment = Fabricate(:media_attachment, account: account) - expect(described_class.new(account).total_storage).to eq media_attachment.file_file_size || 0 + describe '#to_following_accounts_csv' do + before { target_accounts.each { |target_account| account.follow!(target_account) } } + + let(:export) { CSV.parse(subject.to_following_accounts_csv) } + + it 'returns a csv of the following accounts' do + expect(export) + .to contain_exactly( + contain_exactly('Account address', 'Show boosts', 'Notify on new posts', 'Languages'), + include('one@local.host', 'true', 'false', be_blank), + include(be_present) + ) end end - describe 'total_follows' do - it 'returns the total number of the followed accounts' do - target_accounts.each { |target_account| account.follow!(target_account) } - expect(described_class.new(account.reload).total_follows).to eq 2 + describe '#to_lists_csv' do + before do + target_accounts.each do |target_account| + account.follow!(target_account) + Fabricate(:list, account: account).accounts << target_account + end end - it 'returns the total number of the blocked accounts' do - target_accounts.each { |target_account| account.block!(target_account) } - expect(described_class.new(account.reload).total_blocks).to eq 2 + let(:export) { CSV.parse(subject.to_lists_csv) } + + it 'returns a csv of the lists' do + expect(export) + .to contain_exactly( + include('one@local.host'), + include(be_present) + ) end + end + + describe '#to_blocked_domains_csv' do + before { Fabricate.times(2, :account_domain_block, account: account) } + + let(:export) { CSV.parse(subject.to_blocked_domains_csv) } - it 'returns the total number of the muted accounts' do - target_accounts.each { |target_account| account.mute!(target_account) } - expect(described_class.new(account.reload).total_mutes).to eq 2 + it 'returns a csv of the blocked domains' do + expect(export) + .to contain_exactly( + include(/example/), + include(/example/) + ) end end end diff --git a/spec/models/notification_policy_spec.rb b/spec/models/notification_policy_spec.rb index 02a582bb0860c1..7d1b494dd533f0 100644 --- a/spec/models/notification_policy_spec.rb +++ b/spec/models/notification_policy_spec.rb @@ -7,19 +7,25 @@ subject { Fabricate(:notification_policy) } let(:sender) { Fabricate(:account) } + let(:suspended_sender) { Fabricate(:account) } before do Fabricate.times(2, :notification, account: subject.account, activity: Fabricate(:status, account: sender), filtered: true, type: :mention) Fabricate(:notification_request, account: subject.account, from_account: sender) - subject.summarize! - end - it 'sets pending_requests_count' do - expect(subject.pending_requests_count).to eq 1 + Fabricate(:notification, account: subject.account, activity: Fabricate(:status, account: suspended_sender), filtered: true, type: :mention) + Fabricate(:notification_request, account: subject.account, from_account: suspended_sender) + + suspended_sender.suspend! + + subject.summarize! end - it 'sets pending_notifications_count' do - expect(subject.pending_notifications_count).to eq 2 + it 'sets pending_requests_count and pending_notifications_count' do + expect(subject).to have_attributes( + pending_requests_count: 1, + pending_notifications_count: 2 + ) end end end 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/poll_spec.rb b/spec/models/poll_spec.rb index 736f3615d0d3c8..66f521ab3f64f5 100644 --- a/spec/models/poll_spec.rb +++ b/spec/models/poll_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe Poll do - describe 'scopes' do + describe 'Scopes' do let(:status) { Fabricate(:status) } let(:attached_poll) { Fabricate(:poll, status: status) } let(:not_attached_poll) do @@ -13,7 +13,7 @@ end end - describe 'attached' do + describe '.attached' do it 'finds the correct records' do results = described_class.attached @@ -21,7 +21,7 @@ end end - describe 'unattached' do + describe '.unattached' do it 'finds the correct records' do results = described_class.unattached @@ -30,11 +30,23 @@ end end - describe 'validations' do - context 'when not valid' do - subject { Fabricate.build(:poll) } - - it { is_expected.to validate_presence_of(:expires_at) } + describe '#reset_votes!' do + let(:poll) { Fabricate :poll, cached_tallies: [2, 3], votes_count: 5, voters_count: 5 } + let!(:vote) { Fabricate :poll_vote, poll: } + + it 'resets vote data and deletes votes' do + expect { poll.reset_votes! } + .to change(poll, :cached_tallies).to([0, 0]) + .and change(poll, :votes_count).to(0) + .and(change(poll, :voters_count).to(0)) + expect { vote.reload } + .to raise_error(ActiveRecord::RecordNotFound) end end + + describe 'Validations' do + subject { Fabricate.build(:poll) } + + it { is_expected.to validate_presence_of(:expires_at) } + end end diff --git a/spec/models/public_feed_spec.rb b/spec/models/public_feed_spec.rb index da143ac7b05323..2202b2815dbd05 100644 --- a/spec/models/public_feed_spec.rb +++ b/spec/models/public_feed_spec.rb @@ -135,12 +135,10 @@ context 'without a viewer' do let(:viewer) { nil } - it 'includes remote instances statuses' do - expect(subject).to include(remote_status.id) - end - - it 'includes local statuses' do - expect(subject).to include(local_status.id) + it 'includes remote instances statuses and local statuses' do + expect(subject) + .to include(remote_status.id) + .and include(local_status.id) end it 'does not include local-only statuses' do @@ -151,12 +149,10 @@ context 'with a viewer' do let(:viewer) { Fabricate(:account, username: 'viewer') } - it 'includes remote instances statuses' do - expect(subject).to include(remote_status.id) - end - - it 'includes local statuses' do - expect(subject).to include(local_status.id) + it 'includes remote instances statuses and local statuses' do + expect(subject) + .to include(remote_status.id) + .and include(local_status.id) end it 'does not include local-only statuses' do diff --git a/spec/models/report_filter_spec.rb b/spec/models/report_filter_spec.rb index 8668eb3d1085e8..51933e475adb70 100644 --- a/spec/models/report_filter_spec.rb +++ b/spec/models/report_filter_spec.rb @@ -30,4 +30,17 @@ expect(Report).to have_received(:resolved) end end + + context 'when given remote target_origin and also by_target_domain' do + let!(:matching_report) { Fabricate :report, target_account: Fabricate(:account, domain: 'match.example') } + let!(:non_matching_report) { Fabricate :report, target_account: Fabricate(:account, domain: 'other.example') } + + it 'preserves the domain value' do + filter = described_class.new(by_target_domain: 'match.example', target_origin: 'remote') + + expect(filter.results) + .to include(matching_report) + .and not_include(non_matching_report) + end + end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index c0b0c2420fdd7c..da98e6c577a69c 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -559,11 +559,53 @@ end end - describe 'validation' do - it 'disallow empty uri for remote status' do - alice.update(domain: 'example.com') - status = Fabricate.build(:status, uri: '', account: alice) - expect(status).to model_have_error_on_field(:uri) + describe 'Validations' do + context 'with a remote account' do + subject { Fabricate.build :status, account: remote_account } + + let(:remote_account) { Fabricate :account, domain: 'example.com' } + + it { is_expected.to_not allow_value('').for(:uri) } + end + end + + describe 'Callbacks' do + describe 'Stripping content when required' do + context 'with a remote account' do + subject { Fabricate.build :status, local: false, account:, text: ' text ', spoiler_text: ' spoiler ' } + + let(:account) { Fabricate.build :account, domain: 'host.example' } + + it 'preserves content' do + expect { subject.valid? } + .to not_change(subject, :text) + .and not_change(subject, :spoiler_text) + end + end + + context 'with a local account' do + let(:account) { Fabricate.build :account, domain: nil } + + context 'with populated fields' do + subject { Fabricate.build :status, local: true, account:, text: ' text ', spoiler_text: ' spoiler ' } + + it 'strips content' do + expect { subject.valid? } + .to change(subject, :text).to('text') + .and change(subject, :spoiler_text).to('spoiler') + end + end + + context 'with empty fields' do + subject { Fabricate.build :status, local: true, account:, text: nil, spoiler_text: nil } + + it 'preserves content' do + expect { subject.valid? } + .to not_change(subject, :text) + .and not_change(subject, :spoiler_text) + end + end + end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 972453cd690835..4393be5a4efd54 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -387,23 +387,43 @@ def within_duration_window_days end end - describe 'token_for_app' do + describe '#token_for_app' do let(:user) { Fabricate(:user) } - let(:app) { Fabricate(:application, owner: user) } - it 'returns a token' do - expect(user.token_for_app(app)).to be_a(Doorkeeper::AccessToken) + context 'when user owns app but does not have tokens' do + let(:app) { Fabricate(:application, owner: user) } + + it 'creates and returns a persisted token' do + expect { user.token_for_app(app) } + .to change(Doorkeeper::AccessToken.where(resource_owner_id: user.id, application: app), :count).by(1) + end end - it 'persists a token' do - t = user.token_for_app(app) - expect(user.token_for_app(app)).to eql(t) + context 'when user owns app and already has tokens' do + let(:app) { Fabricate(:application, owner: user) } + let!(:token) { Fabricate :access_token, application: app, resource_owner_id: user.id } + + it 'returns a persisted token' do + expect(user.token_for_app(app)) + .to be_a(Doorkeeper::AccessToken) + .and eq(token) + end end - it 'is nil if user does not own app' do - app.update!(owner: nil) + context 'when user does not own app' do + let(:app) { Fabricate(:application) } + + it 'returns nil' do + expect(user.token_for_app(app)) + .to be_nil + end + end - expect(user.token_for_app(app)).to be_nil + context 'when app is nil' do + it 'returns nil' do + expect(user.token_for_app(nil)) + .to be_nil + end end end @@ -434,7 +454,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 +464,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/policies/account_moderation_note_policy_spec.rb b/spec/policies/account_moderation_note_policy_spec.rb index 8c37acc39fee83..8b33a71012702a 100644 --- a/spec/policies/account_moderation_note_policy_spec.rb +++ b/spec/policies/account_moderation_note_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe AccountModerationNotePolicy do subject { described_class } @@ -12,13 +11,13 @@ permissions :create? do context 'when staff' do it 'grants to create' do - expect(subject).to permit(admin, described_class) + expect(subject).to permit(admin, AccountModerationNote) end end context 'when not staff' do it 'denies to create' do - expect(subject).to_not permit(john, described_class) + expect(subject).to_not permit(john, AccountModerationNote) end end end diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb index d7a21d8e39a77e..75724e831bed58 100644 --- a/spec/policies/account_policy_spec.rb +++ b/spec/policies/account_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe AccountPolicy do subject { described_class } @@ -24,7 +23,7 @@ end end - permissions :show?, :unsilence?, :unsensitive?, :remove_avatar?, :remove_header? do + permissions :show?, :unsilence?, :unsensitive?, :remove_avatar?, :remove_header?, :sensitive?, :warn? do context 'when staff' do it 'permits' do expect(subject).to permit(admin, alice) diff --git a/spec/policies/account_warning_policy_spec.rb b/spec/policies/account_warning_policy_spec.rb new file mode 100644 index 00000000000000..9abc9d35d638c7 --- /dev/null +++ b/spec/policies/account_warning_policy_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe AccountWarningPolicy do + subject { described_class } + + let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + let(:account) { Fabricate(:account) } + + permissions :show? do + context 'with an admin' do + it { is_expected.to permit(admin, AccountWarning.new) } + end + + context 'with a non-admin' do + context 'when account is not target' do + it { is_expected.to_not permit(account, AccountWarning.new) } + end + + context 'when account is target' do + it { is_expected.to permit(account, AccountWarning.new(target_account_id: account.id)) } + end + end + end + + permissions :appeal? do + context 'when account is not target' do + it { is_expected.to_not permit(account, AccountWarning.new) } + end + + context 'when account is target' do + context 'when record is appealable' do + it { is_expected.to permit(account, AccountWarning.new(target_account_id: account.id, created_at: Appeal::MAX_STRIKE_AGE.ago + 1.hour)) } + end + + context 'when record is not appealable' do + it { is_expected.to_not permit(account, AccountWarning.new(target_account_id: account.id, created_at: Appeal::MAX_STRIKE_AGE.ago - 1.hour)) } + end + end + end +end diff --git a/spec/policies/account_warning_preset_policy_spec.rb b/spec/policies/account_warning_preset_policy_spec.rb index 53e224f19f7f00..33f2fb11870b2c 100644 --- a/spec/policies/account_warning_preset_policy_spec.rb +++ b/spec/policies/account_warning_preset_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe AccountWarningPresetPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :create?, :update?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, AccountWarningPreset) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, AccountWarningPreset) end end end diff --git a/spec/policies/admin/status_policy_spec.rb b/spec/policies/admin/status_policy_spec.rb index 07af425516d93b..4df29393e3ae2d 100644 --- a/spec/policies/admin/status_policy_spec.rb +++ b/spec/policies/admin/status_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe Admin::StatusPolicy do let(:policy) { described_class } @@ -13,13 +12,13 @@ permissions :index?, :update?, :review?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, Status) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, Status) end end end diff --git a/spec/policies/announcement_policy_spec.rb b/spec/policies/announcement_policy_spec.rb index 503ffca6dca518..ab0c1dbaf5a2bb 100644 --- a/spec/policies/announcement_policy_spec.rb +++ b/spec/policies/announcement_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe AnnouncementPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :create?, :update?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, Announcement) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, Announcement) end end end diff --git a/spec/policies/appeal_policy_spec.rb b/spec/policies/appeal_policy_spec.rb index 1bf8ce0a0da0e6..cdb93bf56cdf46 100644 --- a/spec/policies/appeal_policy_spec.rb +++ b/spec/policies/appeal_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe AppealPolicy do let(:policy) { described_class } @@ -12,18 +11,18 @@ permissions :index? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, Appeal) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, Appeal) end end end - permissions :reject? do + permissions :reject?, :approve? do context 'with an admin' do context 'with a pending appeal' do before { allow(appeal).to receive(:pending?).and_return(true) } diff --git a/spec/policies/audit_log_policy_spec.rb b/spec/policies/audit_log_policy_spec.rb new file mode 100644 index 00000000000000..d9d9359433356e --- /dev/null +++ b/spec/policies/audit_log_policy_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe AuditLogPolicy do + subject { described_class } + + let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + let(:account) { Fabricate(:account) } + + permissions :index? do + context 'with an admin' do + it { is_expected.to permit(admin, nil) } + end + + context 'with a non-admin' do + it { is_expected.to_not permit(account, nil) } + end + end +end diff --git a/spec/policies/backup_policy_spec.rb b/spec/policies/backup_policy_spec.rb index 28cb65d7890730..031021d91dfe2c 100644 --- a/spec/policies/backup_policy_spec.rb +++ b/spec/policies/backup_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe BackupPolicy do subject { described_class } diff --git a/spec/policies/canonical_email_block_policy_spec.rb b/spec/policies/canonical_email_block_policy_spec.rb index f5029d9e6b60e8..b253b439a67dd4 100644 --- a/spec/policies/canonical_email_block_policy_spec.rb +++ b/spec/policies/canonical_email_block_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe CanonicalEmailBlockPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :show?, :test?, :create?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, CanonicalEmailBlock) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, CanonicalEmailBlock) end end end diff --git a/spec/policies/custom_emoji_policy_spec.rb b/spec/policies/custom_emoji_policy_spec.rb index cb869c7d9a7ed7..189885938cf469 100644 --- a/spec/policies/custom_emoji_policy_spec.rb +++ b/spec/policies/custom_emoji_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe CustomEmojiPolicy do subject { described_class } diff --git a/spec/policies/dashboard_policy_spec.rb b/spec/policies/dashboard_policy_spec.rb new file mode 100644 index 00000000000000..90c71db381b5cf --- /dev/null +++ b/spec/policies/dashboard_policy_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DashboardPolicy do + subject { described_class } + + let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + let(:account) { Fabricate(:account) } + + permissions :index? do + context 'with an admin' do + it { is_expected.to permit(admin, nil) } + end + + context 'with a non-admin' do + it { is_expected.to_not permit(account, nil) } + end + end +end diff --git a/spec/policies/delivery_policy_spec.rb b/spec/policies/delivery_policy_spec.rb index bb82389eec8a47..8bc200159ac6e1 100644 --- a/spec/policies/delivery_policy_spec.rb +++ b/spec/policies/delivery_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe DeliveryPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :clear_delivery_errors?, :restart_delivery?, :stop_delivery? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, nil) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, nil) end end end diff --git a/spec/policies/domain_allow_policy_spec.rb b/spec/policies/domain_allow_policy_spec.rb new file mode 100644 index 00000000000000..1d285065b854f5 --- /dev/null +++ b/spec/policies/domain_allow_policy_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DomainAllowPolicy do + subject { described_class } + + let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + let(:john) { Fabricate(:account) } + + permissions :index?, :show?, :create?, :destroy? do + context 'when admin' do + it 'permits' do + expect(subject).to permit(admin, DomainAllow) + end + end + + context 'when not admin' do + it 'denies' do + expect(subject).to_not permit(john, DomainAllow) + end + end + end +end diff --git a/spec/policies/domain_block_policy_spec.rb b/spec/policies/domain_block_policy_spec.rb index 4c89f3f37429ab..7c77d1870d0a9b 100644 --- a/spec/policies/domain_block_policy_spec.rb +++ b/spec/policies/domain_block_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe DomainBlockPolicy do subject { described_class } @@ -9,7 +8,7 @@ let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } let(:john) { Fabricate(:account) } - permissions :index?, :show?, :create?, :destroy? do + permissions :index?, :show?, :create?, :destroy?, :update? do context 'when admin' do it 'permits' do expect(subject).to permit(admin, DomainBlock) diff --git a/spec/policies/email_domain_block_policy_spec.rb b/spec/policies/email_domain_block_policy_spec.rb index 7ecff4be499a16..e98d65a3c73408 100644 --- a/spec/policies/email_domain_block_policy_spec.rb +++ b/spec/policies/email_domain_block_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe EmailDomainBlockPolicy do subject { described_class } diff --git a/spec/policies/follow_recommendation_policy_spec.rb b/spec/policies/follow_recommendation_policy_spec.rb index ae74d5c3a862ab..665ed9b0595085 100644 --- a/spec/policies/follow_recommendation_policy_spec.rb +++ b/spec/policies/follow_recommendation_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe FollowRecommendationPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :show?, :suppress?, :unsuppress? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, FollowRecommendation) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, FollowRecommendation) end end end diff --git a/spec/policies/instance_policy_spec.rb b/spec/policies/instance_policy_spec.rb index a0d9a008b7b4d6..6cdc7380228296 100644 --- a/spec/policies/instance_policy_spec.rb +++ b/spec/policies/instance_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe InstancePolicy do subject { described_class } diff --git a/spec/policies/invite_policy_spec.rb b/spec/policies/invite_policy_spec.rb index cbe3735d806ba5..3717a449993b95 100644 --- a/spec/policies/invite_policy_spec.rb +++ b/spec/policies/invite_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe InvitePolicy do subject { described_class } diff --git a/spec/policies/ip_block_policy_spec.rb b/spec/policies/ip_block_policy_spec.rb index 97bc239e9ac91e..33ea342c10bffc 100644 --- a/spec/policies/ip_block_policy_spec.rb +++ b/spec/policies/ip_block_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe IpBlockPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :show?, :create?, :update?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, IpBlock) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, IpBlock) end end end diff --git a/spec/policies/poll_policy_spec.rb b/spec/policies/poll_policy_spec.rb new file mode 100644 index 00000000000000..aa1701cb06b750 --- /dev/null +++ b/spec/policies/poll_policy_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PollPolicy do + subject { described_class } + + let(:account) { Fabricate(:account) } + let(:poll) { Fabricate :poll } + + permissions :vote? do + context 'when account cannot view status' do + before { poll.status.update(visibility: :private) } + + it { is_expected.to_not permit(account, poll) } + end + + context 'when account can view status' do + context 'when accounts do not block each other' do + it { is_expected.to permit(account, poll) } + end + + context 'when view blocks poll creator' do + before { Fabricate :block, account: account, target_account: poll.account } + + it { is_expected.to_not permit(account, poll) } + end + + context 'when poll creator blocks viewer' do + before { Fabricate :block, account: poll.account, target_account: account } + + it { is_expected.to_not permit(account, poll) } + end + end + end +end diff --git a/spec/policies/preview_card_policy_spec.rb b/spec/policies/preview_card_policy_spec.rb index a1944303e17ffc..d02a6016cd6944 100644 --- a/spec/policies/preview_card_policy_spec.rb +++ b/spec/policies/preview_card_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe PreviewCardPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :review? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, PreviewCard) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, PreviewCard) end end end diff --git a/spec/policies/preview_card_provider_policy_spec.rb b/spec/policies/preview_card_provider_policy_spec.rb index 676039a1b79a97..5e25b364a4afe0 100644 --- a/spec/policies/preview_card_provider_policy_spec.rb +++ b/spec/policies/preview_card_provider_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe PreviewCardProviderPolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :review? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, PreviewCardProvider) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, PreviewCardProvider) end end end diff --git a/spec/policies/relay_policy_spec.rb b/spec/policies/relay_policy_spec.rb index 29ba02c26a8bae..5983b2d2ffb20a 100644 --- a/spec/policies/relay_policy_spec.rb +++ b/spec/policies/relay_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe RelayPolicy do subject { described_class } diff --git a/spec/policies/report_note_policy_spec.rb b/spec/policies/report_note_policy_spec.rb index b40a8788875fe5..02317f763adad8 100644 --- a/spec/policies/report_note_policy_spec.rb +++ b/spec/policies/report_note_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe ReportNotePolicy do subject { described_class } diff --git a/spec/policies/report_policy_spec.rb b/spec/policies/report_policy_spec.rb index 4fc41780758933..67f40b518841e5 100644 --- a/spec/policies/report_policy_spec.rb +++ b/spec/policies/report_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe ReportPolicy do subject { described_class } diff --git a/spec/policies/rule_policy_spec.rb b/spec/policies/rule_policy_spec.rb index 5d435e38c1fe33..3086f304463ddf 100644 --- a/spec/policies/rule_policy_spec.rb +++ b/spec/policies/rule_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe RulePolicy do let(:policy) { described_class } @@ -11,13 +10,13 @@ permissions :index?, :create?, :update?, :destroy? do context 'with an admin' do it 'permits' do - expect(policy).to permit(admin, Tag) + expect(policy).to permit(admin, Rule) end end context 'with a non-admin' do it 'denies' do - expect(policy).to_not permit(john, Tag) + expect(policy).to_not permit(john, Rule) end end end diff --git a/spec/policies/settings_policy_spec.rb b/spec/policies/settings_policy_spec.rb index 4a993149052b15..48821c706a7fff 100644 --- a/spec/policies/settings_policy_spec.rb +++ b/spec/policies/settings_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe SettingsPolicy do subject { described_class } diff --git a/spec/policies/software_update_policy_spec.rb b/spec/policies/software_update_policy_spec.rb index e19ba616128db2..2bda84cce9e574 100644 --- a/spec/policies/software_update_policy_spec.rb +++ b/spec/policies/software_update_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe SoftwareUpdatePolicy do subject { described_class } diff --git a/spec/policies/status_policy_spec.rb b/spec/policies/status_policy_spec.rb index 725bd0bbb3f078..eb2af75d921921 100644 --- a/spec/policies/status_policy_spec.rb +++ b/spec/policies/status_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe StatusPolicy, type: :model do subject { described_class } diff --git a/spec/policies/tag_policy_spec.rb b/spec/policies/tag_policy_spec.rb index 35da3cc62a03df..23166e466921b6 100644 --- a/spec/policies/tag_policy_spec.rb +++ b/spec/policies/tag_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe TagPolicy do subject { described_class } diff --git a/spec/policies/user_policy_spec.rb b/spec/policies/user_policy_spec.rb index 7854547d26db60..11a166a24e0ffc 100644 --- a/spec/policies/user_policy_spec.rb +++ b/spec/policies/user_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe UserPolicy do subject { described_class } @@ -112,4 +111,42 @@ end end end + + permissions :approve?, :reject? do + context 'when admin' do + context 'when user is approved' do + it { is_expected.to_not permit(admin, User.new(approved: true)) } + end + + context 'when user is not approved' do + it { is_expected.to permit(admin, User.new(approved: false)) } + end + end + + context 'when not admin' do + it { is_expected.to_not permit(john, User.new) } + end + end + + permissions :change_role? do + context 'when not admin' do + it { is_expected.to_not permit(john, User.new) } + end + + context 'when admin' do + let(:user) { User.new(role: role) } + + context 'when role of admin overrides user role' do + let(:role) { UserRole.new(position: admin.user.role.position - 10, id: 123) } + + it { is_expected.to permit(admin, user) } + end + + context 'when role of admin does not override user role' do + let(:role) { UserRole.new(position: admin.user.role.position + 10, id: 123) } + + it { is_expected.to_not permit(admin, user) } + end + end + end end diff --git a/spec/policies/user_role_policy_spec.rb b/spec/policies/user_role_policy_spec.rb new file mode 100644 index 00000000000000..c48b345d68f6de --- /dev/null +++ b/spec/policies/user_role_policy_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe UserRolePolicy do + subject { described_class } + + let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + let(:account) { Fabricate(:account) } + + permissions :index?, :create? do + context 'when admin' do + it { is_expected.to permit(admin, UserRole.new) } + end + + context 'when not admin' do + it { is_expected.to_not permit(account, UserRole.new) } + end + end + + permissions :update? do + context 'when admin' do + context 'when role of admin overrides relevant role' do + it { is_expected.to permit(admin, UserRole.new(position: admin.user.role.position - 10, id: 123)) } + end + + context 'when role of admin does not override relevant role' do + it { is_expected.to_not permit(admin, UserRole.new(position: admin.user.role.position + 10, id: 123)) } + end + end + + context 'when not admin' do + it { is_expected.to_not permit(account, UserRole.new) } + end + end + + permissions :destroy? do + context 'when admin' do + context 'when role of admin overrides relevant role' do + it { is_expected.to permit(admin, UserRole.new(position: admin.user.role.position - 10)) } + end + + context 'when role of admin does not override relevant role' do + it { is_expected.to_not permit(admin, UserRole.new(position: admin.user.role.position + 10)) } + end + + context 'when everyone role' do + it { is_expected.to_not permit(admin, UserRole.everyone) } + end + end + + context 'when not admin' do + it { is_expected.to_not permit(account, UserRole.new) } + end + end +end diff --git a/spec/policies/webhook_policy_spec.rb b/spec/policies/webhook_policy_spec.rb index 96aaae2c306726..9899235d833673 100644 --- a/spec/policies/webhook_policy_spec.rb +++ b/spec/policies/webhook_policy_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rails_helper' -require 'pundit/rspec' RSpec.describe WebhookPolicy do let(:policy) { described_class } diff --git a/spec/presenters/export_summary_spec.rb b/spec/presenters/export_summary_spec.rb new file mode 100644 index 00000000000000..0ed46c857d5fee --- /dev/null +++ b/spec/presenters/export_summary_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ExportSummary do + subject { described_class.new(account) } + + let(:account) { Fabricate(:account) } + let(:target_accounts) do + [ + Fabricate(:account), + Fabricate(:account, username: 'one', domain: 'local.host'), + ] + end + + describe '#total_storage' do + it 'returns the total size of the media attachments' do + media_attachment = Fabricate(:media_attachment, account: account) + expect(subject.total_storage).to eq media_attachment.file_file_size || 0 + end + end + + describe '#total_statuses' do + before { Fabricate.times(2, :status, account: account) } + + it 'returns the total number of statuses' do + expect(subject.total_statuses).to eq(2) + end + end + + describe '#total_bookmarks' do + before { Fabricate.times(2, :bookmark, account: account) } + + it 'returns the total number of bookmarks' do + expect(subject.total_bookmarks).to eq(2) + end + end + + describe '#total_follows' do + before { target_accounts.each { |target_account| account.follow!(target_account) } } + + it 'returns the total number of the followed accounts' do + expect(subject.total_follows).to eq(2) + end + end + + describe '#total_lists' do + before { Fabricate.times(2, :list, account: account) } + + it 'returns the total number of lists' do + expect(subject.total_lists).to eq(2) + end + end + + describe '#total_followers' do + before { target_accounts.each { |target_account| target_account.follow!(account) } } + + it 'returns the total number of the follower accounts' do + expect(subject.total_followers).to eq(2) + end + end + + describe '#total_blocks' do + before { target_accounts.each { |target_account| account.block!(target_account) } } + + it 'returns the total number of the blocked accounts' do + expect(subject.total_blocks).to eq(2) + end + end + + describe '#total_mutes' do + before { target_accounts.each { |target_account| account.mute!(target_account) } } + + it 'returns the total number of the muted accounts' do + expect(subject.total_mutes).to eq(2) + end + end + + describe '#total_domain_blocks' do + before { Fabricate.times(2, :account_domain_block, account: account) } + + it 'returns the total number of account domain blocks' do + expect(subject.total_domain_blocks).to eq(2) + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index ee03b49bc6aa16..91a2e21bbbc796 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -43,6 +43,7 @@ require 'capybara/rspec' require 'chewy/rspec' require 'email_spec/rspec' +require 'pundit/rspec' require 'test_prof/recipes/rspec/before_all' Rails.root.glob('spec/support/**/*.rb').each { |f| require f } @@ -161,6 +162,11 @@ def sign_in(resource, _deprecated = nil, scope: nil) host! Rails.configuration.x.local_domain end + config.before :each, type: :system do + # Align with capybara config so that rails helpers called from rspec use matching host + host! 'localhost:3000' + end + config.after do Rails.cache.clear redis.del(redis.keys) 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/accounts_spec.rb b/spec/requests/api/v1/accounts_spec.rb index 45e66f07445d8d..16010ae2e780ea 100644 --- a/spec/requests/api/v1/accounts_spec.rb +++ b/spec/requests/api/v1/accounts_spec.rb @@ -163,6 +163,26 @@ end end + context 'when user tries to follow their own account' do + subject do + post "/api/v1/accounts/#{other_account.id}/follow", headers: headers + end + + let(:locked) { false } + let(:other_account) { user.account } + + it 'returns http forbidden and error message' do + subject + + error_msg = I18n.t('accounts.self_follow_error') + + expect(response).to have_http_status(403) + expect(response.parsed_body[:error]).to eq(error_msg) + end + + it_behaves_like 'forbidden for wrong scope', 'read:accounts' + end + context 'when modifying follow options' do let(:locked) { false } 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/auth/sessions/security_key_options_spec.rb b/spec/requests/auth/sessions/security_key_options_spec.rb index 6246e4beb315f7..e53b9802b4c820 100644 --- a/spec/requests/auth/sessions/security_key_options_spec.rb +++ b/spec/requests/auth/sessions/security_key_options_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Security Key Options' do describe 'GET /auth/sessions/security_key_options' do let!(:user) do - Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) + Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret) end context 'with WebAuthn and OTP enabled as second factor' do 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/statuses/embed_spec.rb b/spec/requests/statuses/embed_spec.rb new file mode 100644 index 00000000000000..33c7ea192c80a3 --- /dev/null +++ b/spec/requests/statuses/embed_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Status embed' do + describe 'GET /users/:account_username/statuses/:id/embed' do + subject { get "/users/#{account.username}/statuses/#{status.id}/embed" } + + let(:account) { Fabricate(:account) } + let(:status) { Fabricate(:status, account: account) } + + context 'when account is suspended' do + let(:account) { Fabricate(:account, suspended: true) } + + it 'returns http gone' do + subject + + expect(response) + .to have_http_status(410) + end + end + + context 'when status is a reblog' do + let(:original_account) { Fabricate(:account, domain: 'example.com') } + let(:original_status) { Fabricate(:status, account: original_account, url: 'https://example.com/123') } + let(:status) { Fabricate(:status, account: account, reblog: original_status) } + + it 'returns http not found' do + subject + + expect(response) + .to have_http_status(404) + end + end + + context 'when status is public' do + it 'renders status successfully', :aggregate_failures do + subject + + expect(response) + .to have_http_status(200) + expect(response.parsed_body.at('body.embed')) + .to be_present + expect(response.headers).to include( + 'Vary' => 'Accept, Accept-Language, Cookie', + 'Cache-Control' => include('public'), + 'Link' => include('activity+json') + ) + end + end + + context 'when status is private' do + let(:status) { Fabricate(:status, account: account, visibility: :private) } + + it 'returns http not found' do + subject + + expect(response) + .to have_http_status(404) + end + end + + context 'when status is direct' do + let(:status) { Fabricate(:status, account: account, visibility: :direct) } + + it 'returns http not found' do + subject + + expect(response) + .to have_http_status(404) + end + 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/host_meta_spec.rb b/spec/requests/well_known/host_meta_spec.rb index 09f17baa894d64..8d8e38f5217243 100644 --- a/spec/requests/well_known/host_meta_spec.rb +++ b/spec/requests/well_known/host_meta_spec.rb @@ -3,25 +3,62 @@ require 'rails_helper' RSpec.describe 'The /.well-known/host-meta request' do - it 'returns http success with valid XML response' do - get '/.well-known/host-meta' - - expect(response) - .to have_http_status(200) - .and have_attributes( - media_type: 'application/xrd+xml', - body: host_meta_xml_template - ) + context 'without extension format or accept header' do + it 'returns http success with expected XML' do + get '/.well-known/host-meta' + + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: 'application/xrd+xml' + ) + + expect(xrd_link_template_value) + .to eq 'https://cb6e6126.ngrok.io/.well-known/webfinger?resource={uri}' + end + + def xrd_link_template_value + response + .parsed_body + .at_xpath('/xrd:XRD/xrd:Link[@rel="lrdd"]/@template', 'xrd' => 'http://docs.oasis-open.org/ns/xri/xrd-1.0') + .value + end + end + + context 'with a .json format extension' do + it 'returns http success with expected JSON' do + get '/.well-known/host-meta.json' + + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: 'application/json' + ) + expect(response.parsed_body) + .to include(expected_json_template) + end end - private + context 'with a JSON `Accept` header' do + it 'returns http success with expected JSON' do + get '/.well-known/host-meta', headers: { 'Accept' => 'application/json' } + + expect(response) + .to have_http_status(200) + .and have_attributes( + media_type: 'application/json' + ) + expect(response.parsed_body) + .to include(expected_json_template) + end + end - def host_meta_xml_template - <<~XML - - - - - XML + def expected_json_template + { + links: [ + 'rel' => 'lrdd', + 'template' => 'https://cb6e6126.ngrok.io/.well-known/webfinger?resource={uri}', + ], + } end end 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/routing/well_known_routes_spec.rb b/spec/routing/well_known_routes_spec.rb index 6578e939ae1e14..84081059bba75e 100644 --- a/spec/routing/well_known_routes_spec.rb +++ b/spec/routing/well_known_routes_spec.rb @@ -4,9 +4,14 @@ RSpec.describe 'Well Known routes' do describe 'the host-meta route' do - it 'routes to correct place with xml format' do + it 'routes to correct place' do expect(get('/.well-known/host-meta')) - .to route_to('well_known/host_meta#show', format: 'xml') + .to route_to('well_known/host_meta#show') + end + + it 'routes to correct place with json format' do + expect(get('/.well-known/host-meta.json')) + .to route_to('well_known/host_meta#show', format: 'json') end end diff --git a/spec/serializers/activitypub/note_serializer_spec.rb b/spec/serializers/activitypub/note_serializer_spec.rb index 285b241ee237e3..a6976193b20ec1 100644 --- a/spec/serializers/activitypub/note_serializer_spec.rb +++ b/spec/serializers/activitypub/note_serializer_spec.rb @@ -14,7 +14,7 @@ let!(:reply_by_account_third) { Fabricate(:status, account: account, thread: parent, visibility: :public) } let!(:reply_by_account_visibility_direct) { Fabricate(:status, account: account, thread: parent, visibility: :direct) } - it 'has the expected shape' do + it 'has the expected shape and replies collection' do expect(subject).to include({ '@context' => include('https://www.w3.org/ns/activitystreams'), 'type' => 'Note', @@ -22,26 +22,23 @@ 'contentMap' => include({ 'zh-TW' => a_kind_of(String), }), + 'replies' => replies_collection_values, }) end - it 'has a replies collection' do - expect(subject['replies']['type']).to eql('Collection') + def replies_collection_values + include( + 'type' => eql('Collection'), + 'first' => include( + 'type' => eql('CollectionPage'), + 'items' => reply_items + ) + ) end - it 'has a replies collection with a first Page' do - expect(subject['replies']['first']['type']).to eql('CollectionPage') - end - - it 'includes public self-replies in its replies collection' do - expect(subject['replies']['first']['items']).to include(reply_by_account_first.uri, reply_by_account_next.uri, reply_by_account_third.uri) - end - - it 'does not include replies from others in its replies collection' do - expect(subject['replies']['first']['items']).to_not include(reply_by_other_first.uri) - end - - it 'does not include replies with direct visibility in its replies collection' do - expect(subject['replies']['first']['items']).to_not include(reply_by_account_visibility_direct.uri) + def reply_items + include(reply_by_account_first.uri, reply_by_account_next.uri, reply_by_account_third.uri) # Public self replies + .and(not_include(reply_by_other_first.uri)) # Replies from others + .and(not_include(reply_by_account_visibility_direct.uri)) # Replies with direct visibility end end diff --git a/spec/services/account_statuses_cleanup_service_spec.rb b/spec/services/account_statuses_cleanup_service_spec.rb index 857bd4fda499af..553d20029a6624 100644 --- a/spec/services/account_statuses_cleanup_service_spec.rb +++ b/spec/services/account_statuses_cleanup_service_spec.rb @@ -27,39 +27,35 @@ end context 'when given a normal budget of 10' do - it 'reports 3 deleted statuses' do - expect(subject.call(account_policy, 10)).to eq 3 - end - - it 'records the last deleted id' do - subject.call(account_policy, 10) - expect(account_policy.last_inspected).to eq [old_status.id, another_old_status.id].max - end - - it 'actually deletes the statuses' do - subject.call(account_policy, 10) - expect(Status.find_by(id: [very_old_status.id, old_status.id, another_old_status.id])).to be_nil - expect { recent_status.reload }.to_not raise_error - end - - it 'preserves recent and unrelated statuses' do - subject.call(account_policy, 10) - expect { unrelated_status.reload }.to_not raise_error - expect { recent_status.reload }.to_not raise_error + it 'reports 3 deleted statuses and records last deleted id, deletes statuses, preserves recent unrelated statuses' do + expect(subject.call(account_policy, 10)) + .to eq(3) + + expect(account_policy.last_inspected) + .to eq [old_status.id, another_old_status.id].max + + expect(Status.find_by(id: [very_old_status.id, old_status.id, another_old_status.id])) + .to be_nil + expect { recent_status.reload } + .to_not raise_error + expect { unrelated_status.reload } + .to_not raise_error + expect { recent_status.reload } + .to_not raise_error end end context 'when called repeatedly with a budget of 2' do - it 'reports 2 then 1 deleted statuses' do - expect(subject.call(account_policy, 2)).to eq 2 - expect(subject.call(account_policy, 2)).to eq 1 - end - - it 'actually deletes the statuses in the expected order' do - subject.call(account_policy, 2) - expect(Status.find_by(id: very_old_status.id)).to be_nil - subject.call(account_policy, 2) - expect(Status.find_by(id: [very_old_status.id, old_status.id, another_old_status.id])).to be_nil + it 'reports 2 then 1 deleted statuses and deletes in expected order' do + expect(subject.call(account_policy, 2)) + .to eq(2) + expect(Status.find_by(id: very_old_status.id)) + .to be_nil + + expect(subject.call(account_policy, 2)) + .to eq(1) + expect(Status.find_by(id: [very_old_status.id, old_status.id, another_old_status.id])) + .to be_nil end end @@ -90,19 +86,24 @@ end end - it 'reports 0 deleted statuses then 0 then 3 then 0 again' do - expect(subject.call(account_policy, 10)).to eq 0 - expect(subject.call(account_policy, 10)).to eq 0 - expect(subject.call(account_policy, 10)).to eq 3 - expect(subject.call(account_policy, 10)).to eq 0 + it 'reports 0 deleted statuses then 0 then 3 then 0 again, and keeps id under oldest deletable record' do + expect(subject.call(account_policy, 10)) + .to eq(0) + expect(subject.call(account_policy, 10)) + .to eq(0) + expect(subject.call(account_policy, 10)) + .to eq(3) + expect(subject.call(account_policy, 10)) + .to eq(0) + expect(account_policy.last_inspected) + .to be < oldest_deletable_record_id end - it 'never causes the recorded id to get higher than oldest deletable toot' do - subject.call(account_policy, 10) - subject.call(account_policy, 10) - subject.call(account_policy, 10) - subject.call(account_policy, 10) - expect(account_policy.last_inspected).to be < Mastodon::Snowflake.id_at(account_policy.min_status_age.seconds.ago, with_random: false) + def oldest_deletable_record_id + Mastodon::Snowflake.id_at( + account_policy.min_status_age.seconds.ago, + with_random: false + ) end 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/activitypub/process_status_update_service_spec.rb b/spec/services/activitypub/process_status_update_service_spec.rb index a97e8408026b7c..b6ceba374f7825 100644 --- a/spec/services/activitypub/process_status_update_service_spec.rb +++ b/spec/services/activitypub/process_status_update_service_spec.rb @@ -2,10 +2,6 @@ require 'rails_helper' -def poll_option_json(name, votes) - { type: 'Note', name: name, replies: { type: 'Collection', totalItems: votes } } -end - RSpec.describe ActivityPub::ProcessStatusUpdateService do subject { described_class.new } @@ -294,7 +290,6 @@ def poll_option_json(name, votes) context 'when originally without media attachments' do before do stub_request(:get, 'https://example.com/foo.png').to_return(body: attachment_fixture('emojo.png')) - subject.call(status, json, json) end let(:payload) do @@ -310,19 +305,18 @@ def poll_option_json(name, votes) } end - it 'updates media attachments' do - media_attachment = status.reload.ordered_media_attachments.first + it 'updates media attachments, fetches attachment, records media change in edit' do + subject.call(status, json, json) - expect(media_attachment).to_not be_nil - expect(media_attachment.remote_url).to eq 'https://example.com/foo.png' - end + expect(status.reload.ordered_media_attachments.first) + .to be_present + .and(have_attributes(remote_url: 'https://example.com/foo.png')) - it 'fetches the attachment' do - expect(a_request(:get, 'https://example.com/foo.png')).to have_been_made - end + expect(a_request(:get, 'https://example.com/foo.png')) + .to have_been_made - it 'records media change in edit' do - expect(status.edits.reload.last.ordered_media_attachment_ids).to_not be_empty + expect(status.edits.reload.last.ordered_media_attachment_ids) + .to_not be_empty end end @@ -344,27 +338,26 @@ def poll_option_json(name, votes) before do allow(RedownloadMediaWorker).to receive(:perform_async) - subject.call(status, json, json) end - it 'updates the existing media attachment in-place' do - media_attachment = status.media_attachments.ordered.reload.first + it 'updates the existing media attachment in-place, does not queue redownload, updates media, records media change' do + subject.call(status, json, json) - expect(media_attachment).to_not be_nil - expect(media_attachment.remote_url).to eq 'https://example.com/foo.png' - expect(media_attachment.description).to eq 'A picture' - end + expect(status.media_attachments.ordered.reload.first) + .to be_present + .and have_attributes( + remote_url: 'https://example.com/foo.png', + description: 'A picture' + ) - it 'does not queue redownload for the existing media attachment' do - expect(RedownloadMediaWorker).to_not have_received(:perform_async) - end + expect(RedownloadMediaWorker) + .to_not have_received(:perform_async) - it 'updates media attachments' do - expect(status.ordered_media_attachments.map(&:remote_url)).to eq %w(https://example.com/foo.png) - end + expect(status.ordered_media_attachments.map(&:remote_url)) + .to eq %w(https://example.com/foo.png) - it 'records media change in edit' do - expect(status.edits.reload.last.ordered_media_attachment_ids).to_not be_empty + expect(status.edits.reload.last.ordered_media_attachment_ids) + .to_not be_empty end end @@ -372,10 +365,11 @@ def poll_option_json(name, votes) before do poll = Fabricate(:poll, status: status) status.update(preloadable_poll: poll) - subject.call(status, json, json) end it 'removes poll and records media change in edit' do + subject.call(status, json, json) + expect(status.reload.poll).to be_nil expect(status.edits.reload.last.poll_options).to be_nil end @@ -398,15 +392,13 @@ def poll_option_json(name, votes) } end - before do + it 'creates a poll and records media change in edit' do subject.call(status, json, json) - end - it 'creates a poll and records media change in edit' do - poll = status.reload.poll + expect(status.reload.poll) + .to be_present + .and have_attributes(options: %w(Foo Bar Baz)) - expect(poll).to_not be_nil - expect(poll.options).to eq %w(Foo Bar Baz) expect(status.edits.reload.last.poll_options).to eq %w(Foo Bar Baz) end end @@ -419,4 +411,8 @@ def poll_option_json(name, votes) .to eq '2021-09-08 22:39:25 UTC' end end + + def poll_option_json(name, votes) + { type: 'Note', name: name, replies: { type: 'Collection', totalItems: votes } } + 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/services/authorize_follow_service_spec.rb b/spec/services/authorize_follow_service_spec.rb index 533b791fb7f6e7..de2857280249cb 100644 --- a/spec/services/authorize_follow_service_spec.rb +++ b/spec/services/authorize_follow_service_spec.rb @@ -12,15 +12,15 @@ before do FollowRequest.create(account: bob, target_account: sender) - subject.call(bob, sender) end - it 'removes follow request' do - expect(bob.requested?(sender)).to be false - end + it 'removes follow request and creates follow relation' do + subject.call(bob, sender) - it 'creates follow relation' do - expect(bob.following?(sender)).to be true + expect(bob) + .to_not be_requested(sender) + expect(bob) + .to be_following(sender) end end @@ -30,19 +30,17 @@ before do FollowRequest.create(account: bob, target_account: sender) stub_request(:post, bob.inbox_url).to_return(status: 200) - subject.call(bob, sender) end - it 'removes follow request' do - expect(bob.requested?(sender)).to be false - end - - it 'creates follow relation' do - expect(bob.following?(sender)).to be true - end + it 'removes follow request, creates follow relation, send accept activity', :inline_jobs do + subject.call(bob, sender) - it 'sends an accept activity', :inline_jobs do - expect(a_request(:post, bob.inbox_url)).to have_been_made.once + expect(bob) + .to_not be_requested(sender) + expect(bob) + .to be_following(sender) + expect(a_request(:post, bob.inbox_url)) + .to have_been_made.once end end end diff --git a/spec/services/batched_remove_status_service_spec.rb b/spec/services/batched_remove_status_service_spec.rb index 628bb198ef06f3..1ff73a633b1002 100644 --- a/spec/services/batched_remove_status_service_spec.rb +++ b/spec/services/batched_remove_status_service_spec.rb @@ -24,32 +24,38 @@ status_alice_hello status_alice_other + end + it 'removes status records, removes from author and local follower feeds, notifies stream, sends delete' do subject.call([status_alice_hello, status_alice_other]) - end - it 'removes statuses' do - expect { Status.find(status_alice_hello.id) }.to raise_error ActiveRecord::RecordNotFound - expect { Status.find(status_alice_other.id) }.to raise_error ActiveRecord::RecordNotFound - end + expect { Status.find(status_alice_hello.id) } + .to raise_error ActiveRecord::RecordNotFound + expect { Status.find(status_alice_other.id) } + .to raise_error ActiveRecord::RecordNotFound - it 'removes statuses from author\'s home feed' do - expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(status_alice_hello.id, status_alice_other.id) - end + expect(feed_ids_for(alice)) + .to_not include(status_alice_hello.id, status_alice_other.id) - it 'removes statuses from local follower\'s home feed' do - expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(status_alice_hello.id, status_alice_other.id) - end + expect(feed_ids_for(jeff)) + .to_not include(status_alice_hello.id, status_alice_other.id) - it 'notifies streaming API of followers' do - expect(redis).to have_received(:publish).with("timeline:#{jeff.id}", any_args).at_least(:once) - end + expect(redis) + .to have_received(:publish) + .with("timeline:#{jeff.id}", any_args).at_least(:once) + + expect(redis) + .to have_received(:publish) + .with('timeline:public', any_args).at_least(:once) - it 'notifies streaming API of public timeline' do - expect(redis).to have_received(:publish).with('timeline:public', any_args).at_least(:once) + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.at_least_once end - it 'sends delete activity to followers' do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.at_least_once + def feed_ids_for(account) + HomeFeed + .new(account) + .get(10) + .pluck(:id) end end diff --git a/spec/services/block_service_spec.rb b/spec/services/block_service_spec.rb index 46dd69198699a4..d9687a5404dc0a 100644 --- a/spec/services/block_service_spec.rb +++ b/spec/services/block_service_spec.rb @@ -26,15 +26,16 @@ before do stub_request(:post, 'http://example.com/inbox').to_return(status: 200) - subject.call(sender, bob) end - it 'creates a blocking relation' do - expect(sender.blocking?(bob)).to be true - end + it 'creates a blocking relation and send block activity', :inline_jobs do + subject.call(sender, bob) + + expect(sender) + .to be_blocking(bob) - it 'sends a block activity', :inline_jobs do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end end diff --git a/spec/services/bulk_import_service_spec.rb b/spec/services/bulk_import_service_spec.rb index 0197f81a448dd7..f52fc4d7d5e83a 100644 --- a/spec/services/bulk_import_service_spec.rb +++ b/spec/services/bulk_import_service_spec.rb @@ -24,30 +24,19 @@ ].map { |data| import.rows.create!(data: data) } end - before do - account.follow!(Fabricate(:account)) - end - - it 'does not immediately change who the account follows' do - expect { subject.call(import) }.to_not(change { account.reload.active_relationships.to_a }) - end + before { account.follow!(Fabricate(:account)) } - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows.map(&:id)) - end - - it 'requests to follow all the listed users once the workers have run' do - subject.call(import) + it 'does not immediately change who the account follows, enqueues workers, sends follow requests after worker run' do + expect { subject.call(import) } + .to_not(change { account.reload.active_relationships.to_a }) - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows.map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(FollowRequest.includes(:target_account).where(account: account).map { |follow_request| follow_request.target_account.acct }).to contain_exactly('user@foo.bar', 'unknown@unknown.bar') + expect(FollowRequest.includes(:target_account).where(account: account).map { |follow_request| follow_request.target_account.acct }) + .to contain_exactly('user@foo.bar', 'unknown@unknown.bar') end end @@ -71,31 +60,20 @@ account.follow!(to_be_unfollowed) end - it 'unfollows user not present on list' do - subject.call(import) - expect(account.following?(to_be_unfollowed)).to be false - end - - it 'updates the existing follow relationship as expected' do - expect { subject.call(import) }.to change { Follow.where(account: account, target_account: followed).pick(:show_reblogs, :notify, :languages) }.from([true, false, nil]).to([false, true, ['en']]) - end + it 'updates the existing follow relationship as expected and unfollows user not on list, enqueues workers, sends follow reqs after worker run' do + expect { subject.call(import) } + .to change { Follow.where(account: account, target_account: followed).pick(:show_reblogs, :notify, :languages) }.from([true, false, nil]).to([false, true, ['en']]) - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows[1..].map(&:id)) - end - - it 'requests to follow all the expected users once the workers have run' do - subject.call(import) + expect(account) + .to_not be_following(to_be_unfollowed) - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows[1..].map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(FollowRequest.includes(:target_account).where(account: account).map { |follow_request| follow_request.target_account.acct }).to contain_exactly('user@foo.bar', 'unknown@unknown.bar') + expect(FollowRequest.includes(:target_account).where(account: account).map { |follow_request| follow_request.target_account.acct }) + .to contain_exactly('user@foo.bar', 'unknown@unknown.bar') end end @@ -110,30 +88,19 @@ ].map { |data| import.rows.create!(data: data) } end - before do - account.block!(Fabricate(:account, username: 'already_blocked', domain: 'remote.org')) - end - - it 'does not immediately change who the account blocks' do - expect { subject.call(import) }.to_not(change { account.reload.blocking.to_a }) - end + before { account.block!(Fabricate(:account, username: 'already_blocked', domain: 'remote.org')) } - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows.map(&:id)) - end - - it 'blocks all the listed users once the workers have run' do - subject.call(import) + it 'does not immediately change who the account blocks, enqueues worker, blocks after run' do + expect { subject.call(import) } + .to_not(change { account.reload.blocking.to_a }) - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows.map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(account.blocking.map(&:acct)).to contain_exactly('already_blocked@remote.org', 'user@foo.bar', 'unknown@unknown.bar') + expect(account.reload.blocking.map(&:acct)) + .to contain_exactly('already_blocked@remote.org', 'user@foo.bar', 'unknown@unknown.bar') end end @@ -157,27 +124,18 @@ account.block!(to_be_unblocked) end - it 'unblocks user not present on list' do + it 'unblocks user not present on list, enqueues worker, requests follow after run' do subject.call(import) - expect(account.blocking?(to_be_unblocked)).to be false - end - - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows[1..].map(&:id)) - end - it 'requests to follow all the expected users once the workers have run' do - subject.call(import) + expect(account.blocking?(to_be_unblocked)).to be false - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows[1..].map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(account.blocking.map(&:acct)).to contain_exactly('blocked@foo.bar', 'user@foo.bar', 'unknown@unknown.bar') + expect(account.blocking.map(&:acct)) + .to contain_exactly('blocked@foo.bar', 'user@foo.bar', 'unknown@unknown.bar') end end @@ -192,30 +150,19 @@ ].map { |data| import.rows.create!(data: data) } end - before do - account.mute!(Fabricate(:account, username: 'already_muted', domain: 'remote.org')) - end - - it 'does not immediately change who the account blocks' do - expect { subject.call(import) }.to_not(change { account.reload.muting.to_a }) - end - - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows.map(&:id)) - end + before { account.mute!(Fabricate(:account, username: 'already_muted', domain: 'remote.org')) } - it 'mutes all the listed users once the workers have run' do - subject.call(import) + it 'does not immediately change who the account blocks, enqueures worker, mutes users after worker run' do + expect { subject.call(import) } + .to_not(change { account.reload.muting.to_a }) - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows.map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(account.muting.map(&:acct)).to contain_exactly('already_muted@remote.org', 'user@foo.bar', 'unknown@unknown.bar') + expect(account.reload.muting.map(&:acct)) + .to contain_exactly('already_muted@remote.org', 'user@foo.bar', 'unknown@unknown.bar') end end @@ -239,31 +186,19 @@ account.mute!(to_be_unmuted) end - it 'updates the existing mute as expected' do - expect { subject.call(import) }.to change { Mute.where(account: account, target_account: muted).pick(:hide_notifications) }.from(false).to(true) - end + it 'updates the existing mute as expected and unblocks user not on list, and enqueues worker, and requests follow after worker run' do + expect { subject.call(import) } + .to change { Mute.where(account: account, target_account: muted).pick(:hide_notifications) }.from(false).to(true) - it 'unblocks user not present on list' do - subject.call(import) expect(account.muting?(to_be_unmuted)).to be false - end - - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows[1..].map(&:id)) - end - - it 'requests to follow all the expected users once the workers have run' do - subject.call(import) - resolve_account_service_double = instance_double(ResolveAccountService) - allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double) - allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } - allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + expect(row_worker_job_args) + .to match_array(rows[1..].map(&:id)) - Import::RowWorker.drain + stub_resolve_account_and_drain_workers - expect(account.muting.map(&:acct)).to contain_exactly('muted@foo.bar', 'user@foo.bar', 'unknown@unknown.bar') + expect(account.muting.map(&:acct)) + .to contain_exactly('muted@foo.bar', 'user@foo.bar', 'unknown@unknown.bar') end end @@ -284,13 +219,11 @@ account.block_domain!('blocked.com') end - it 'blocks all the new domains' do + it 'blocks all the new domains and marks import finished' do subject.call(import) - expect(account.domain_blocks.pluck(:domain)).to contain_exactly('alreadyblocked.com', 'blocked.com', 'to-block.com') - end - it 'marks the import as finished' do - subject.call(import) + expect(account.domain_blocks.pluck(:domain)) + .to contain_exactly('alreadyblocked.com', 'blocked.com', 'to-block.com') expect(import.reload.state_finished?).to be true end end @@ -312,14 +245,13 @@ account.block_domain!('blocked.com') end - it 'blocks all the new domains' do + it 'blocks all the new domains and marks import finished' do subject.call(import) - expect(account.domain_blocks.pluck(:domain)).to contain_exactly('blocked.com', 'to-block.com') - end - it 'marks the import as finished' do - subject.call(import) - expect(import.reload.state_finished?).to be true + expect(account.domain_blocks.pluck(:domain)) + .to contain_exactly('blocked.com', 'to-block.com') + expect(import.reload.state_finished?) + .to be true end end @@ -347,22 +279,16 @@ account.bookmarks.create!(status: bookmarked) end - it 'enqueues workers for the expected rows' do - subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows.map(&:id)) - end - - it 'updates the bookmarks as expected once the workers have run' do + it 'enqueues workers for the expected rows and updates bookmarks after worker run' do subject.call(import) - service_double = instance_double(ActivityPub::FetchRemoteStatusService) - allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service_double) - allow(service_double).to receive(:call).with('https://domain.unknown/foo') { Fabricate(:status, uri: 'https://domain.unknown/foo') } - allow(service_double).to receive(:call).with('https://domain.unknown/private') { Fabricate(:status, uri: 'https://domain.unknown/private', visibility: :direct) } + expect(row_worker_job_args) + .to match_array(rows.map(&:id)) - Import::RowWorker.drain + stub_fetch_remote_and_drain_workers - expect(account.bookmarks.map { |bookmark| bookmark.status.uri }).to contain_exactly(already_bookmarked.uri, status.uri, bookmarked.uri, 'https://domain.unknown/foo') + expect(account.bookmarks.map { |bookmark| bookmark.status.uri }) + .to contain_exactly(already_bookmarked.uri, status.uri, bookmarked.uri, 'https://domain.unknown/foo') end end @@ -390,23 +316,48 @@ account.bookmarks.create!(status: bookmarked) end - it 'enqueues workers for the expected rows' do + it 'enqueues workers for the expected rows and updates bookmarks' do subject.call(import) - expect(Import::RowWorker.jobs.pluck('args').flatten).to match_array(rows.map(&:id)) + + expect(row_worker_job_args) + .to match_array(rows.map(&:id)) + + stub_fetch_remote_and_drain_workers + + expect(account.bookmarks.map { |bookmark| bookmark.status.uri }) + .to contain_exactly(status.uri, bookmarked.uri, 'https://domain.unknown/foo') end + end - it 'updates the bookmarks as expected once the workers have run' do - subject.call(import) + def row_worker_job_args + Import::RowWorker + .jobs + .pluck('args') + .flatten + end - service_double = instance_double(ActivityPub::FetchRemoteStatusService) - allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service_double) - allow(service_double).to receive(:call).with('https://domain.unknown/foo') { Fabricate(:status, uri: 'https://domain.unknown/foo') } - allow(service_double).to receive(:call).with('https://domain.unknown/private') { Fabricate(:status, uri: 'https://domain.unknown/private', visibility: :direct) } + def stub_resolve_account_and_drain_workers + resolve_account_service_double = instance_double(ResolveAccountService) + allow(ResolveAccountService) + .to receive(:new) + .and_return(resolve_account_service_double) + allow(resolve_account_service_double) + .to receive(:call) + .with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) } + allow(resolve_account_service_double) + .to receive(:call) + .with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) } + + Import::RowWorker.drain + end - Import::RowWorker.drain + def stub_fetch_remote_and_drain_workers + service_double = instance_double(ActivityPub::FetchRemoteStatusService) + allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service_double) + allow(service_double).to receive(:call).with('https://domain.unknown/foo') { Fabricate(:status, uri: 'https://domain.unknown/foo') } + allow(service_double).to receive(:call).with('https://domain.unknown/private') { Fabricate(:status, uri: 'https://domain.unknown/private', visibility: :direct) } - expect(account.bookmarks.map { |bookmark| bookmark.status.uri }).to contain_exactly(status.uri, bookmarked.uri, 'https://domain.unknown/foo') - end + Import::RowWorker.drain end end end diff --git a/spec/services/favourite_service_spec.rb b/spec/services/favourite_service_spec.rb index c39362def2f7f3..123e8699c7668f 100644 --- a/spec/services/favourite_service_spec.rb +++ b/spec/services/favourite_service_spec.rb @@ -11,11 +11,9 @@ let(:bob) { Fabricate(:account) } let(:status) { Fabricate(:status, account: bob) } - before do + it 'creates a favourite' do subject.call(sender, status) - end - it 'creates a favourite' do expect(status.favourites.first).to_not be_nil end end @@ -26,15 +24,16 @@ before do stub_request(:post, 'http://example.com/inbox').to_return(status: 200, body: '', headers: {}) - subject.call(sender, status) end - it 'creates a favourite' do - expect(status.favourites.first).to_not be_nil - end + it 'creates a favourite and sends like activity', :inline_jobs do + subject.call(sender, status) + + expect(status.favourites.first) + .to_not be_nil - it 'sends a like activity', :inline_jobs do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end end diff --git a/spec/services/follow_service_spec.rb b/spec/services/follow_service_spec.rb index 0c4cd600460922..bbd8a6f997ff60 100644 --- a/spec/services/follow_service_spec.rb +++ b/spec/services/follow_service_spec.rb @@ -143,15 +143,16 @@ before do stub_request(:post, 'http://example.com/inbox').to_return(status: 200, body: '', headers: {}) - subject.call(sender, bob) end - it 'creates follow request' do - expect(FollowRequest.find_by(account: sender, target_account: bob)).to_not be_nil - end + it 'creates follow request and sends an activity to inbox', :inline_jobs do + subject.call(sender, bob) + + expect(FollowRequest.find_by(account: sender, target_account: bob)) + .to_not be_nil - it 'sends a follow activity to the inbox', :inline_jobs do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end end diff --git a/spec/services/process_mentions_service_spec.rb b/spec/services/process_mentions_service_spec.rb index 2c202d3e57af18..3cc83d82f3cb08 100644 --- a/spec/services/process_mentions_service_spec.rb +++ b/spec/services/process_mentions_service_spec.rb @@ -16,20 +16,25 @@ before do account.block!(individually_blocked_account) account.domain_blocks.create!(domain: domain_blocked_account.domain) + end - subject.call(status) + it 'creates a mention to the non-blocked account but not the individually or domain blocked accounts' do + expect { subject.call(status) } + .to create_mention_for_non_blocked + .and skip_mention_for_individual + .and skip_mention_for_domain_blocked end - it 'creates a mention to the non-blocked account' do - expect(non_blocked_account.mentions.where(status: status).count).to eq 1 + def create_mention_for_non_blocked + change { non_blocked_account.mentions.where(status: status).count }.to(1) end - it 'does not create a mention to the individually blocked account' do - expect(individually_blocked_account.mentions.where(status: status).count).to eq 0 + def skip_mention_for_individual + not_change { individually_blocked_account.mentions.where(status: status).count }.from(0) end - it 'does not create a mention to the domain-blocked account' do - expect(domain_blocked_account.mentions.where(status: status).count).to eq 0 + def skip_mention_for_domain_blocked + not_change { domain_blocked_account.mentions.where(status: status).count }.from(0) end end @@ -40,11 +45,9 @@ context 'with a valid remote user' do let!(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } - before do + it 'creates a mention' do subject.call(status) - end - it 'creates a mention' do expect(remote_user.mentions.where(status: status).count).to eq 1 end end @@ -53,11 +56,9 @@ let!(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } let(:status) { Fabricate(:status, account: account, text: "Hello @#{remote_user.acct} @#{remote_user.acct} @#{remote_user.acct}", visibility: :public) } - before do + it 'creates exactly one mention' do subject.call(status, save_records: false) - end - it 'creates exactly one mention' do expect(status.mentions.size).to eq 1 end end @@ -66,11 +67,9 @@ let!(:remote_user) { Fabricate(:account, username: 'sneak', protocol: :activitypub, domain: 'xn--hresiar-mxa.ch', inbox_url: 'http://example.com/inbox') } let!(:status) { Fabricate(:status, account: account, text: 'Hello @sneak@hæresiar.ch') } - before do + it 'creates a mention' do subject.call(status) - end - it 'creates a mention' do expect(remote_user.mentions.where(status: status).count).to eq 1 end end @@ -79,11 +78,9 @@ let!(:remote_user) { Fabricate(:account, username: 'foo', protocol: :activitypub, domain: 'xn--y9a3aq.xn--y9a3aq', inbox_url: 'http://example.com/inbox') } let!(:status) { Fabricate(:status, account: account, text: 'Hello @foo@հայ.հայ') } - before do + it 'creates a mention' do subject.call(status) - end - it 'creates a mention' do expect(remote_user.mentions.where(status: status).count).to eq 1 end end @@ -95,10 +92,11 @@ before do stub_request(:get, 'https://example.com/.well-known/host-meta').to_return(status: 404) stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:remote_user@example.com').to_return(status: 500) - subject.call(status) end it 'creates a mention' do + subject.call(status) + expect(remote_user.mentions.where(status: status).count).to eq 1 end end diff --git a/spec/services/reject_follow_service_spec.rb b/spec/services/reject_follow_service_spec.rb index d2c7a00206210b..eec0d6c1e05f93 100644 --- a/spec/services/reject_follow_service_spec.rb +++ b/spec/services/reject_follow_service_spec.rb @@ -10,17 +10,15 @@ describe 'local' do let(:bob) { Fabricate(:account) } - before do - FollowRequest.create(account: bob, target_account: sender) - subject.call(bob, sender) - end + before { FollowRequest.create(account: bob, target_account: sender) } - it 'removes follow request' do - expect(bob.requested?(sender)).to be false - end + it 'removes follow request and does not create relation' do + subject.call(bob, sender) - it 'does not create follow relation' do - expect(bob.following?(sender)).to be false + expect(bob) + .to_not be_requested(sender) + expect(bob) + .to_not be_following(sender) end end @@ -30,19 +28,17 @@ before do FollowRequest.create(account: bob, target_account: sender) stub_request(:post, bob.inbox_url).to_return(status: 200) - subject.call(bob, sender) - end - - it 'removes follow request' do - expect(bob.requested?(sender)).to be false end - it 'does not create follow relation' do - expect(bob.following?(sender)).to be false - end + it 'removes follow request, does not create relation, sends reject activity', :inline_jobs do + subject.call(bob, sender) - it 'sends a reject activity', :inline_jobs do - expect(a_request(:post, bob.inbox_url)).to have_been_made.once + expect(bob) + .to_not be_requested(sender) + expect(bob) + .to_not be_following(sender) + expect(a_request(:post, bob.inbox_url)) + .to have_been_made.once end end end diff --git a/spec/services/remove_from_followers_service_spec.rb b/spec/services/remove_from_followers_service_spec.rb index 515600096cfc04..381daf1a5913b1 100644 --- a/spec/services/remove_from_followers_service_spec.rb +++ b/spec/services/remove_from_followers_service_spec.rb @@ -10,13 +10,13 @@ describe 'local' do let(:sender) { Fabricate(:account, username: 'alice') } - before do - Follow.create(account: sender, target_account: bob) - subject.call(bob, sender) - end + before { Follow.create(account: sender, target_account: bob) } it 'does not create follow relation' do - expect(bob.followed_by?(sender)).to be false + subject.call(bob, sender) + + expect(bob) + .to_not be_followed_by(sender) end end @@ -26,15 +26,16 @@ before do Follow.create(account: sender, target_account: bob) stub_request(:post, sender.inbox_url).to_return(status: 200) - subject.call(bob, sender) end - it 'does not create follow relation' do - expect(bob.followed_by?(sender)).to be false - end + it 'does not create follow relation and sends reject activity', :inline_jobs do + subject.call(bob, sender) + + expect(bob) + .to_not be_followed_by(sender) - it 'sends a reject activity', :inline_jobs do - expect(a_request(:post, sender.inbox_url)).to have_been_made.once + expect(a_request(:post, sender.inbox_url)) + .to have_been_made.once end end end diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 08f519b5360d99..f2b46f05b002ba 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -28,42 +28,38 @@ Fabricate(:status, account: bill, reblog: status, uri: 'hoge') end - it 'removes status from author\'s home feed' do - subject.call(status) - expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(status.id) - end - - it 'removes status from local follower\'s home feed' do - subject.call(status) - expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(status.id) - end - - it 'publishes to public media timeline' do + it 'removes status from notifications and from author and local follower home feeds, publishes to media timeline, sends delete activities' do allow(redis).to receive(:publish).with(any_args) - subject.call(status) + expect { subject.call(status) } + .to remove_status_from_notifications - expect(redis).to have_received(:publish).with('timeline:public:media', Oj.dump(event: :delete, payload: status.id.to_s)) - end + expect(home_feed_ids(alice)) + .to_not include(status.id) + expect(home_feed_ids(jeff)) + .to_not include(status.id) - it 'sends Delete activity to followers' do - subject.call(status) + expect(redis) + .to have_received(:publish).with('timeline:public:media', Oj.dump(event: :delete, payload: status.id.to_s)) expect(delete_delivery(hank, status)) .to have_been_made.once - end - - it 'sends Delete activity to rebloggers' do - subject.call(status) expect(delete_delivery(bill, status)) .to have_been_made.once end - it 'remove status from notifications' do - expect { subject.call(status) }.to change { - Notification.where(activity_type: 'Favourite', from_account: jeff, account: alice).count - }.from(1).to(0) + def home_feed_ids(personage) + HomeFeed + .new(personage) + .get(10) + .pluck(:id) + end + + def remove_status_from_notifications + change { Notification.where(activity_type: 'Favourite', from_account: jeff, account: alice).count } + .from(1) + .to(0) end def delete_delivery(target, status) diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index 6518c5c27ad3a0..4659e1c7a13ed5 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -31,14 +31,13 @@ context 'when forward is true', :inline_jobs do let(:forward) { true } - it 'sends ActivityPub payload when forward is true' do - subject.call(source_account, remote_account, forward: forward) - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made - end - - it 'has an uri' do + it 'has a URI and sends ActivityPub payload' do report = subject.call(source_account, remote_account, forward: forward) - expect(report.uri).to_not be_nil + + expect(report.uri) + .to_not be_nil + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made end context 'when reporting a reply on a different remote server' do @@ -122,13 +121,12 @@ status.mentions.create(account: source_account) end - it 'creates a report' do - expect { subject.call }.to change { target_account.targeted_reports.count }.from(0).to(1) - end + it 'creates a report and attaches the DM to the report' do + expect { subject.call } + .to change { target_account.targeted_reports.count }.from(0).to(1) - it 'attaches the DM to the report' do - subject.call - expect(target_account.targeted_reports.pluck(:status_ids)).to eq [[status.id]] + expect(target_account.targeted_reports.pluck(:status_ids)) + .to eq [[status.id]] end end @@ -146,13 +144,12 @@ status.mentions.create(account: source_account) end - it 'creates a report' do - expect { subject.call }.to change { target_account.targeted_reports.count }.from(0).to(1) - end + it 'creates a report and attaches DM to report' do + expect { subject.call } + .to change { target_account.targeted_reports.count }.from(0).to(1) - it 'attaches the DM to the report' do - subject.call - expect(target_account.targeted_reports.pluck(:status_ids)).to eq [[status.id]] + expect(target_account.targeted_reports.pluck(:status_ids)) + .to eq [[status.id]] end end diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index a856e019a7fe2f..1bd4e9a8e3bfcc 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -22,37 +22,38 @@ context 'when domain is banned' do before { Fabricate(:domain_block, domain: 'ap.example.com', severity: :suspend) } - it 'does not return an account' do - expect(subject.call('foo@ap.example.com', skip_webfinger: true)).to be_nil - end - - it 'does not make a webfinger query' do - subject.call('foo@ap.example.com', skip_webfinger: true) - expect(a_request(:get, 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com')).to_not have_been_made + it 'does not return an account or make a webfinger query' do + expect(subject.call('foo@ap.example.com', skip_webfinger: true)) + .to be_nil + expect(webfinger_discovery_request) + .to_not have_been_made end end context 'when domain is not banned' do - it 'returns the expected account' do - expect(subject.call('foo@ap.example.com', skip_webfinger: true)).to eq remote_account - end - - it 'does not make a webfinger query' do - subject.call('foo@ap.example.com', skip_webfinger: true) - expect(a_request(:get, 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com')).to_not have_been_made + it 'returns the expected account and does not make a webfinger query' do + expect(subject.call('foo@ap.example.com', skip_webfinger: true)) + .to eq remote_account + expect(webfinger_discovery_request) + .to_not have_been_made end end end context 'when account is not known' do - it 'does not return an account' do - expect(subject.call('foo@ap.example.com', skip_webfinger: true)).to be_nil + it 'does not return an account and does not make webfinger query' do + expect(subject.call('foo@ap.example.com', skip_webfinger: true)) + .to be_nil + expect(webfinger_discovery_request) + .to_not have_been_made end + end - it 'does not make a webfinger query' do - subject.call('foo@ap.example.com', skip_webfinger: true) - expect(a_request(:get, 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com')).to_not have_been_made - end + def webfinger_discovery_request + a_request( + :get, + 'https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com' + ) end end @@ -84,13 +85,11 @@ allow(AccountDeletionWorker).to receive(:perform_async) end - it 'returns nil' do - expect(subject.call('hoge@example.com')).to be_nil - end - - it 'queues account deletion worker' do - subject.call('hoge@example.com') - expect(AccountDeletionWorker).to have_received(:perform_async) + it 'returns nil and queues deletion worker' do + expect(subject.call('hoge@example.com')) + .to be_nil + expect(AccountDeletionWorker) + .to have_received(:perform_async) end end @@ -110,9 +109,12 @@ it 'returns new remote account' do account = subject.call('Foo@redirected.example.com') - expect(account.activitypub?).to be true - expect(account.acct).to eq 'foo@ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + expect(account) + .to have_attributes( + activitypub?: true, + acct: 'foo@ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox' + ) end end @@ -125,9 +127,12 @@ it 'returns new remote account' do account = subject.call('Foo@redirected.example.com') - expect(account.activitypub?).to be true - expect(account.acct).to eq 'foo@ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + expect(account) + .to have_attributes( + activitypub?: true, + acct: 'foo@ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox' + ) end end @@ -161,9 +166,12 @@ it 'returns new remote account' do account = subject.call('foo@ap.example.com') - expect(account.activitypub?).to be true - expect(account.domain).to eq 'ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' + expect(account) + .to have_attributes( + activitypub?: true, + domain: 'ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox' + ) end context 'with multiple types' do @@ -174,10 +182,13 @@ it 'returns new remote account' do account = subject.call('foo@ap.example.com') - expect(account.activitypub?).to be true - expect(account.domain).to eq 'ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' - expect(account.actor_type).to eq 'Person' + expect(account) + .to have_attributes( + activitypub?: true, + domain: 'ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox', + actor_type: 'Person' + ) end end end @@ -186,20 +197,21 @@ let!(:duplicate) { Fabricate(:account, username: 'foo', domain: 'old.example.com', uri: 'https://ap.example.com/users/foo') } let!(:status) { Fabricate(:status, account: duplicate, text: 'foo') } - it 'returns new remote account' do + it 'returns new remote account and merges accounts', :inline_jobs do account = subject.call('foo@ap.example.com') - expect(account.activitypub?).to be true - expect(account.domain).to eq 'ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' - expect(account.uri).to eq 'https://ap.example.com/users/foo' - end - - it 'merges accounts', :inline_jobs do - account = subject.call('foo@ap.example.com') + expect(account) + .to have_attributes( + activitypub?: true, + domain: 'ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox', + uri: 'https://ap.example.com/users/foo' + ) - expect(status.reload.account_id).to eq account.id - expect(Account.where(uri: account.uri).count).to eq 1 + expect(status.reload.account_id) + .to eq account.id + expect(Account.where(uri: account.uri).count) + .to eq 1 end end @@ -210,11 +222,15 @@ it 'returns new remote account' do account = subject.call('foo@ap.example.com') - expect(account.activitypub?).to be true - expect(account.domain).to eq 'ap.example.com' - expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox' - expect(account.uri).to eq 'https://ap.example.com/users/foo' - expect(status.reload.account).to eq(account) + expect(account) + .to have_attributes( + activitypub?: true, + domain: 'ap.example.com', + inbox_url: 'https://ap.example.com/users/foo/inbox', + uri: 'https://ap.example.com/users/foo' + ) + expect(status.reload.account) + .to eq(account) end end diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb index 80f2a5a4baf55d..eaf00c1ed84cd2 100644 --- a/spec/services/resolve_url_service_spec.rb +++ b/spec/services/resolve_url_service_spec.rb @@ -51,12 +51,11 @@ let(:url) { 'https://example.com/@foo/42' } let(:uri) { 'https://example.com/users/foo/statuses/42' } - it 'returns status by url' do - expect(subject.call(url, on_behalf_of: account)).to eq(status) - end - - it 'returns status by uri' do - expect(subject.call(uri, on_behalf_of: account)).to eq(status) + it 'returns status by URL or URI' do + expect(subject.call(url, on_behalf_of: account)) + .to eq(status) + expect(subject.call(uri, on_behalf_of: account)) + .to eq(status) end end @@ -75,12 +74,11 @@ let(:url) { 'https://example.com/@foo/42' } let(:uri) { 'https://example.com/users/foo/statuses/42' } - it 'does not return the status by url' do - expect(subject.call(url, on_behalf_of: account)).to be_nil - end - - it 'does not return the status by uri' do - expect(subject.call(uri, on_behalf_of: account)).to be_nil + it 'does not return the status by URL or URI' do + expect(subject.call(url, on_behalf_of: account)) + .to be_nil + expect(subject.call(uri, on_behalf_of: account)) + .to be_nil end end @@ -107,22 +105,20 @@ account.follow!(poster) end - it 'returns status by url' do - expect(subject.call(url, on_behalf_of: account)).to eq(status) - end - - it 'returns status by uri' do - expect(subject.call(uri, on_behalf_of: account)).to eq(status) + it 'returns status by URL or URI' do + expect(subject.call(url, on_behalf_of: account)) + .to eq(status) + expect(subject.call(uri, on_behalf_of: account)) + .to eq(status) end end context 'when the account does not follow the poster' do - it 'does not return the status by url' do - expect(subject.call(url, on_behalf_of: account)).to be_nil - end - - it 'does not return the status by uri' do - expect(subject.call(uri, on_behalf_of: account)).to be_nil + it 'does not return the status by URL or URI' do + expect(subject.call(url, on_behalf_of: account)) + .to be_nil + expect(subject.call(uri, on_behalf_of: account)) + .to be_nil end end end diff --git a/spec/services/translate_status_service_spec.rb b/spec/services/translate_status_service_spec.rb index 0779fbbe6c52bc..ac7a43ff2af4f4 100644 --- a/spec/services/translate_status_service_spec.rb +++ b/spec/services/translate_status_service_spec.rb @@ -18,7 +18,7 @@ describe '#call' do before do translation_service = TranslationService.new - allow(translation_service).to receive(:languages).and_return({ 'en' => ['es'] }) + allow(translation_service).to receive(:languages).and_return({ 'en' => ['es', 'es-MX'] }) allow(translation_service).to receive(:translate) do |texts| texts.map do |text| TranslationService::Translation.new( @@ -32,20 +32,15 @@ allow(TranslationService).to receive_messages(configured?: true, configured: translation_service) end - it 'returns translated status content' do - expect(service.call(status, 'es').content).to eq '

Hola

' - end - - it 'returns source language' do - expect(service.call(status, 'es').detected_source_language).to eq 'en' - end - - it 'returns translation provider' do - expect(service.call(status, 'es').provider).to eq 'Dummy' - end - - it 'returns original status' do - expect(service.call(status, 'es').status).to eq status + it 'returns translated status content and source language and provider and original status' do + expect(service.call(status, 'es')) + .to have_attributes( + content: '

Hola

', + detected_source_language: 'en', + language: 'es', + provider: 'Dummy', + status: status + ) end describe 'status has content with custom emoji' do @@ -107,6 +102,16 @@ expect(media_attachment.description).to eq 'Hola & :highfive:' end end + + describe 'target language is regional' do + it 'uses regional variant' do + expect(service.call(status, 'es-MX').language).to eq 'es-MX' + end + + it 'uses parent locale for unsupported regional variant' do + expect(service.call(status, 'es-XX').language).to eq 'es' + end + end end describe '#source_texts' do @@ -155,26 +160,16 @@ let!(:source_texts) { service.send(:source_texts) } it 'returns formatted poll options' do - expect(source_texts.size).to eq 3 - expect(source_texts.values).to eq %w(

Hello

Blue Green) - end - - it 'has a first key with content' do - expect(source_texts.keys.first).to eq :content - end - - it 'has the first option in the second key with correct options' do - option1 = source_texts.keys.second - expect(option1).to be_a Poll::Option - expect(option1.id).to eq '0' - expect(option1.title).to eq 'Blue' - end - - it 'has the second option in the third key with correct options' do - option2 = source_texts.keys.third - expect(option2).to be_a Poll::Option - expect(option2.id).to eq '1' - expect(option2.title).to eq 'Green' + expect(source_texts) + .to have_attributes( + size: 3, + values: %w(

Hello

Blue Green), + keys: contain_exactly( + eq(:content), + be_a(Poll::Option).and(have_attributes(id: '0', title: 'Blue')), + be_a(Poll::Option).and(have_attributes(id: '1', title: 'Green')) + ) + ) end end end diff --git a/spec/services/unblock_domain_service_spec.rb b/spec/services/unblock_domain_service_spec.rb index 405fe1cfd2f8a3..daa1d480a6bc9d 100644 --- a/spec/services/unblock_domain_service_spec.rb +++ b/spec/services/unblock_domain_service_spec.rb @@ -12,26 +12,32 @@ let!(:silenced) { Fabricate(:account, domain: 'example.com', silenced_at: domain_block.created_at) } let!(:suspended) { Fabricate(:account, domain: 'example.com', suspended_at: domain_block.created_at) } - it 'unsilences accounts and removes block' do - domain_block.update(severity: :silence) - - subject.call(domain_block) - expect_deleted_domain_block - expect(silenced.reload.silenced?).to be false - expect(suspended.reload.suspended?).to be true - expect(independently_suspended.reload.suspended?).to be true - expect(independently_silenced.reload.silenced?).to be true + context 'with severity of silence' do + before { domain_block.update(severity: :silence) } + + it 'unsilences accounts and removes block' do + subject.call(domain_block) + + expect_deleted_domain_block + expect(silenced.reload.silenced?).to be false + expect(suspended.reload.suspended?).to be true + expect(independently_suspended.reload.suspended?).to be true + expect(independently_silenced.reload.silenced?).to be true + end end - it 'unsuspends accounts and removes block' do - domain_block.update(severity: :suspend) + context 'with severity of suspend' do + before { domain_block.update(severity: :suspend) } - subject.call(domain_block) - expect_deleted_domain_block - expect(suspended.reload.suspended?).to be false - expect(silenced.reload.silenced?).to be false - expect(independently_suspended.reload.suspended?).to be true - expect(independently_silenced.reload.silenced?).to be true + it 'unsuspends accounts and removes block' do + subject.call(domain_block) + + expect_deleted_domain_block + expect(suspended.reload.suspended?).to be false + expect(silenced.reload.silenced?).to be false + expect(independently_suspended.reload.suspended?).to be true + expect(independently_silenced.reload.silenced?).to be true + end end end diff --git a/spec/services/unblock_service_spec.rb b/spec/services/unblock_service_spec.rb index 6132e74415ecd6..a2c5188f06335a 100644 --- a/spec/services/unblock_service_spec.rb +++ b/spec/services/unblock_service_spec.rb @@ -10,13 +10,13 @@ describe 'local' do let(:bob) { Fabricate(:account) } - before do - sender.block!(bob) - subject.call(sender, bob) - end + before { sender.block!(bob) } it 'destroys the blocking relation' do - expect(sender.blocking?(bob)).to be false + subject.call(sender, bob) + + expect(sender) + .to_not be_blocking(bob) end end @@ -26,15 +26,15 @@ before do sender.block!(bob) stub_request(:post, 'http://example.com/inbox').to_return(status: 200) - subject.call(sender, bob) end - it 'destroys the blocking relation' do - expect(sender.blocking?(bob)).to be false - end + it 'destroys the blocking relation and sends unblock activity', :inline_jobs do + subject.call(sender, bob) - it 'sends an unblock activity', :inline_jobs do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(sender) + .to_not be_blocking(bob) + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end end diff --git a/spec/services/unfollow_service_spec.rb b/spec/services/unfollow_service_spec.rb index 0c206c4b983215..6cf24ca5e1ce65 100644 --- a/spec/services/unfollow_service_spec.rb +++ b/spec/services/unfollow_service_spec.rb @@ -10,13 +10,13 @@ describe 'local' do let(:bob) { Fabricate(:account, username: 'bob') } - before do - sender.follow!(bob) - subject.call(sender, bob) - end + before { sender.follow!(bob) } it 'destroys the following relation' do - expect(sender.following?(bob)).to be false + subject.call(sender, bob) + + expect(sender) + .to_not be_following(bob) end end @@ -26,15 +26,15 @@ before do sender.follow!(bob) stub_request(:post, 'http://example.com/inbox').to_return(status: 200) - subject.call(sender, bob) end - it 'destroys the following relation' do - expect(sender.following?(bob)).to be false - end + it 'destroys the following relation and sends unfollow activity' do + subject.call(sender, bob) - it 'sends an unfollow activity' do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(sender) + .to_not be_following(bob) + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end @@ -44,15 +44,15 @@ before do bob.follow!(sender) stub_request(:post, 'http://example.com/inbox').to_return(status: 200) - subject.call(bob, sender) end - it 'destroys the following relation' do - expect(bob.following?(sender)).to be false - end + it 'destroys the following relation and sends a reject activity' do + subject.call(bob, sender) - it 'sends a reject activity' do - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once + expect(sender) + .to_not be_following(bob) + expect(a_request(:post, 'http://example.com/inbox')) + .to have_been_made.once end end end diff --git a/spec/services/update_account_service_spec.rb b/spec/services/update_account_service_spec.rb index d066db481e5568..f9059af07f5ab3 100644 --- a/spec/services/update_account_service_spec.rb +++ b/spec/services/update_account_service_spec.rb @@ -18,23 +18,19 @@ FollowService.new.call(alice, account) FollowService.new.call(bob, account) FollowService.new.call(eve, account) + end + it 'auto accepts pending follow requests from appropriate accounts' do subject.call(account, { locked: false }) - end - it 'auto-accepts pending follow requests' do - expect(alice.following?(account)).to be true - expect(alice.requested?(account)).to be false - end + expect(alice).to be_following(account) + expect(alice).to_not be_requested(account) - it 'does not auto-accept pending follow requests from silenced users' do - expect(bob.following?(account)).to be false - expect(bob.requested?(account)).to be true - end + expect(bob).to_not be_following(account) + expect(bob).to be_requested(account) - it 'auto-accepts pending follow requests from muted users so as to not leak mute' do - expect(eve.following?(account)).to be true - expect(eve.requested?(account)).to be false + expect(eve).to be_following(account) + expect(eve).to_not be_requested(account) end end end diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb index de06fb13c63ad5..7c92adeffd2335 100644 --- a/spec/services/update_status_service_spec.rb +++ b/spec/services/update_status_service_spec.rb @@ -10,15 +10,15 @@ before do allow(ActivityPub::DistributionWorker).to receive(:perform_async) - subject.call(status, status.account_id, text: 'Foo') end - it 'does not create an edit' do - expect(status.reload.edits).to be_empty - end + it 'does not create an edit or notify anyone' do + subject.call(status, status.account_id, text: 'Foo') - it 'does not notify anyone' do - expect(ActivityPub::DistributionWorker).to_not have_received(:perform_async) + expect(status.reload.edits) + .to be_empty + expect(ActivityPub::DistributionWorker) + .to_not have_received(:perform_async) end end @@ -28,18 +28,16 @@ before do PreviewCardsStatus.create(status: status, preview_card: preview_card) - subject.call(status, status.account_id, text: 'Bar') - end - - it 'updates text' do - expect(status.reload.text).to eq 'Bar' end - it 'resets preview card' do - expect(status.reload.preview_card).to be_nil - end + it 'updates text, resets card, saves edit history' do + subject.call(status, status.account_id, text: 'Bar') - it 'saves edit history' do + expect(status.reload) + .to have_attributes( + text: 'Bar', + preview_card: be_nil + ) expect(status.edits.ordered.pluck(:text)).to eq %w(Foo Bar) end end @@ -50,15 +48,15 @@ before do PreviewCardsStatus.create(status: status, preview_card: preview_card) - subject.call(status, status.account_id, text: 'Foo', spoiler_text: 'Bar') end - it 'updates content warning' do - expect(status.reload.spoiler_text).to eq 'Bar' - end + it 'updates content warning and saves history' do + subject.call(status, status.account_id, text: 'Foo', spoiler_text: 'Bar') - it 'saves edit history' do - expect(status.edits.ordered.pluck(:text, :spoiler_text)).to eq [['Foo', ''], ['Foo', 'Bar']] + expect(status.reload.spoiler_text) + .to eq 'Bar' + expect(status.edits.ordered.pluck(:text, :spoiler_text)) + .to eq [['Foo', ''], ['Foo', 'Bar']] end end @@ -69,23 +67,19 @@ before do status.media_attachments << detached_media_attachment - subject.call(status, status.account_id, text: 'Foo', media_ids: [attached_media_attachment.id.to_s]) - end - - it 'updates media attachments' do - expect(status.ordered_media_attachments).to eq [attached_media_attachment] - end - - it 'does not detach detached media attachments' do - expect(detached_media_attachment.reload.status_id).to eq status.id end - it 'attaches attached media attachments' do - expect(attached_media_attachment.reload.status_id).to eq status.id - end + it 'updates media attachments, handles attachments, saves history' do + subject.call(status, status.account_id, text: 'Foo', media_ids: [attached_media_attachment.id.to_s]) - it 'saves edit history' do - expect(status.edits.ordered.pluck(:ordered_media_attachment_ids)).to eq [[detached_media_attachment.id], [attached_media_attachment.id]] + expect(status.ordered_media_attachments) + .to eq [attached_media_attachment] + expect(detached_media_attachment.reload.status_id) + .to eq status.id + expect(attached_media_attachment.reload.status_id) + .to eq status.id + expect(status.edits.ordered.pluck(:ordered_media_attachment_ids)) + .to eq [[detached_media_attachment.id], [attached_media_attachment.id]] end end @@ -95,19 +89,18 @@ before do status.media_attachments << media_attachment - subject.call(status, status.account_id, text: 'Foo', media_ids: [media_attachment.id.to_s], media_attributes: [{ id: media_attachment.id, description: 'New description' }]) end - it 'does not detach media attachment' do - expect(media_attachment.reload.status_id).to eq status.id - end - - it 'updates the media attachment description' do - expect(media_attachment.reload.description).to eq 'New description' - end + it 'does not detach media attachment, updates description, and saves history' do + subject.call(status, status.account_id, text: 'Foo', media_ids: [media_attachment.id.to_s], media_attributes: [{ id: media_attachment.id, description: 'New description' }]) - it 'saves edit history' do - expect(status.edits.ordered.map { |edit| edit.ordered_media_attachments.map(&:description) }).to eq [['Old description'], ['New description']] + expect(media_attachment.reload) + .to have_attributes( + status_id: status.id, + description: 'New description' + ) + expect(status.edits.ordered.map { |edit| edit.ordered_media_attachments.map(&:description) }) + .to eq [['Old description'], ['New description']] end end @@ -120,28 +113,27 @@ before do status.update(poll: poll) VoteService.new.call(voter, poll, [0]) - subject.call(status, status.account_id, text: 'Foo', poll: { options: %w(Bar Baz Foo), expires_in: 5.days.to_i }) end - it 'updates poll' do - poll = status.poll.reload - expect(poll.options).to eq %w(Bar Baz Foo) - end + it 'updates poll, resets votes, saves history, requeues notifications' do + subject.call(status, status.account_id, text: 'Foo', poll: { options: %w(Bar Baz Foo), expires_in: 5.days.to_i }) - it 'resets votes' do poll = status.poll.reload - expect(poll.votes_count).to eq 0 - expect(poll.votes.count).to eq 0 - expect(poll.cached_tallies).to eq [0, 0, 0] - end - it 'saves edit history' do - expect(status.edits.ordered.pluck(:poll_options)).to eq [%w(Foo Bar), %w(Bar Baz Foo)] - end + expect(poll) + .to have_attributes( + options: %w(Bar Baz Foo), + votes_count: 0, + cached_tallies: [0, 0, 0] + ) + expect(poll.votes.count) + .to eq(0) - it 'requeues expiration notification' do - poll = status.poll.reload - expect(PollExpirationNotifyWorker).to have_enqueued_sidekiq_job(poll.id).at(poll.expires_at + 5.minutes) + expect(status.edits.ordered.pluck(:poll_options)) + .to eq [%w(Foo Bar), %w(Bar Baz Foo)] + + expect(PollExpirationNotifyWorker) + .to have_enqueued_sidekiq_job(poll.id).at(poll.expires_at + 5.minutes) end end @@ -151,16 +143,13 @@ let!(:bob) { Fabricate(:account, username: 'bob') } let!(:status) { PostStatusService.new.call(account, text: 'Hello @alice') } - before do + it 'changes mentions and keeps old as silent' do subject.call(status, status.account_id, text: 'Hello @bob') - end - - it 'changes mentions' do - expect(status.active_mentions.pluck(:account_id)).to eq [bob.id] - end - it 'keeps old mentions as silent mentions' do - expect(status.mentions.pluck(:account_id)).to contain_exactly(alice.id, bob.id) + expect(status.active_mentions.pluck(:account_id)) + .to eq [bob.id] + expect(status.mentions.pluck(:account_id)) + .to contain_exactly(alice.id, bob.id) end end @@ -168,11 +157,9 @@ let!(:account) { Fabricate(:account) } let!(:status) { PostStatusService.new.call(account, text: 'Hello #foo') } - before do + it 'changes tags' do subject.call(status, status.account_id, text: 'Hello #bar') - end - it 'changes tags' do expect(status.tags.pluck(:name)).to eq %w(bar) 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/support/response_encoders.rb b/spec/support/response_encoders.rb new file mode 100644 index 00000000000000..548dba7132486f --- /dev/null +++ b/spec/support/response_encoders.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +ActionDispatch::IntegrationTest + .register_encoder :xml, response_parser: ->(body) { Nokogiri::XML(body) } diff --git a/spec/system/admin/invites_spec.rb b/spec/system/admin/invites_spec.rb new file mode 100644 index 00000000000000..f2cee626c68e27 --- /dev/null +++ b/spec/system/admin/invites_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Admin Invites' do + describe 'Invite interaction' do + let!(:invite) { Fabricate(:invite, expires_at: nil) } + + let(:user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + before { sign_in user } + + it 'allows invite listing and creation' do + visit admin_invites_path + + expect(page) + .to have_title(I18n.t('admin.invites.title')) + for_invite(invite) do + expect(find('input').value) + .to include(invite.code) + end + + select I18n.t('invites.max_uses', count: 10), from: max_use_field + + expect { generate_invite } + .to change(Invite, :count).by(1) + expect(user.invites.last) + .to have_attributes(max_uses: 10) + end + + it 'allows invite expiration' do + visit admin_invites_path + + for_invite(invite) do + expect { expire_invite } + .to change { invite.reload.expired? }.from(false).to(true) + end + end + + it 'allows invite deactivation' do + visit admin_invites_path + + expect { click_on I18n.t('admin.invites.deactivate_all') } + .to change { Invite.exists?(expires_at: nil) }.from(true).to(false) + end + + def for_invite(invite, &block) + within("#invite_#{invite.id}", &block) + end + + def expire_invite + click_on I18n.t('invites.delete') + end + + def generate_invite + click_on I18n.t('invites.generate') + end + + def max_use_field + I18n.t('simple_form.labels.defaults.max_uses') + end + end +end diff --git a/spec/system/admin/reset_spec.rb b/spec/system/admin/reset_spec.rb index 1e787ea110f2d4..d0f70a93f029d8 100644 --- a/spec/system/admin/reset_spec.rb +++ b/spec/system/admin/reset_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' RSpec.describe 'Admin::Reset' do - it 'Resets password for account user' do + it 'Resets password for account user', :inline_jobs do account = Fabricate :account sign_in admin_user visit admin_account_path(account.id) diff --git a/spec/system/admin/tags_spec.rb b/spec/system/admin/tags_spec.rb new file mode 100644 index 00000000000000..a3eca80d13614a --- /dev/null +++ b/spec/system/admin/tags_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Admin Tags' do + describe 'Tag interaction' do + let!(:tag) { Fabricate(:tag, name: 'test') } + + before { sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } + + it 'allows tags listing and editing' do + visit admin_tags_path + + expect(page) + .to have_title(I18n.t('admin.tags.title')) + + click_on '#test' + + fill_in display_name_field, with: 'NewTagName' + expect { click_on submit_button } + .to_not(change { tag.reload.display_name }) + expect(page) + .to have_content(match_error_text) + + fill_in display_name_field, with: 'TEST' + expect { click_on submit_button } + .to(change { tag.reload.display_name }.to('TEST')) + end + + def display_name_field + I18n.t('simple_form.labels.defaults.display_name') + end + + def match_error_text + I18n.t('tags.does_not_match_previous_name') + end + end +end diff --git a/spec/system/invites_spec.rb b/spec/system/invites_spec.rb index c57de871cc6e1a..fc60ce5913bc03 100644 --- a/spec/system/invites_spec.rb +++ b/spec/system/invites_spec.rb @@ -7,10 +7,7 @@ let(:user) { Fabricate :user } - before do - host! 'localhost:3000' # TODO: Move into before for all system specs? - sign_in user - end + before { sign_in user } describe 'Viewing invites' do it 'Lists existing user invites' do diff --git a/spec/system/oauth_spec.rb b/spec/system/oauth_spec.rb index 0f96a59675803b..14ffc163f0a3f1 100644 --- a/spec/system/oauth_spec.rb +++ b/spec/system/oauth_spec.rb @@ -24,28 +24,28 @@ subject # It presents the user with an authorization page - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) - - # Upon authorizing, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.authorize') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_authorize_text) # It grants the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true + expect { click_on oauth_authorize_text } + .to change { user_has_grant_with_client_app? }.to(true) + + # Upon authorizing, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end it 'when rejecting the authorization request' do subject # It presents the user with an authorization page - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.deny')) - - # Upon denying, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.deny') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_deny_text) # It does not grant the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false + expect { click_on oauth_deny_text } + .to_not change { user_has_grant_with_client_app? }.from(false) + + # Upon denying, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end # The tests in this context ensures that requests without PKCE parameters @@ -133,7 +133,6 @@ end it 'when accepting the authorization request' do - params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' } visit "/oauth/authorize?#{params.to_query}" # It presents the user with a log-in page @@ -145,18 +144,17 @@ # Logging in redirects to an authorization page fill_in_auth_details(email, password) - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) - - # Upon authorizing, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.authorize') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_authorize_text) # It grants the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true + expect { click_on oauth_authorize_text } + .to change { user_has_grant_with_client_app? }.to(true) + + # Upon authorizing, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end it 'when rejecting the authorization request' do - params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' } visit "/oauth/authorize?#{params.to_query}" # It presents the user with a log-in page @@ -168,21 +166,20 @@ # Logging in redirects to an authorization page fill_in_auth_details(email, password) - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) - - # Upon denying, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.deny') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_authorize_text) # It does not grant the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false + expect { click_on oauth_deny_text } + .to_not change { user_has_grant_with_client_app? }.from(false) + + # Upon denying, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end context 'when the user has set up TOTP' do - let(:user) { Fabricate(:user, email: email, password: password, otp_required_for_login: true, otp_secret: User.generate_otp_secret(32)) } + let(:user) { Fabricate(:user, email: email, password: password, otp_required_for_login: true, otp_secret: User.generate_otp_secret) } it 'when accepting the authorization request' do - params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' } visit "/oauth/authorize?#{params.to_query}" # It presents the user with a log-in page @@ -202,18 +199,17 @@ # Filling in the correct TOTP code redirects to an app authorization page fill_in_otp_details(user.current_otp) - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) - - # Upon authorizing, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.authorize') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_authorize_text) # It grants the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be true + expect { click_on oauth_authorize_text } + .to change { user_has_grant_with_client_app? }.to(true) + + # Upon authorizing, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end it 'when rejecting the authorization request' do - params = { client_id: client_app.uid, response_type: 'code', redirect_uri: client_app.redirect_uri, scope: 'read' } visit "/oauth/authorize?#{params.to_query}" # It presents the user with a log-in page @@ -233,14 +229,14 @@ # Filling in the correct TOTP code redirects to an app authorization page fill_in_otp_details(user.current_otp) - expect(page).to have_content(I18n.t('doorkeeper.authorizations.buttons.authorize')) - - # Upon denying, it redirects to the apps' callback URL - click_on I18n.t('doorkeeper.authorizations.buttons.deny') - expect(page).to have_current_path(/\A#{client_app.redirect_uri}/, url: true) + expect(page).to have_content(oauth_authorize_text) # It does not grant the app access to the account - expect(Doorkeeper::AccessGrant.exists?(application: client_app, resource_owner_id: user.id)).to be false + expect { click_on oauth_deny_text } + .to_not change { user_has_grant_with_client_app? }.from(false) + + # Upon denying, it redirects to the apps' callback URL + expect(page).to redirect_to_callback_url end end # TODO: external auth @@ -252,4 +248,24 @@ def fill_in_otp_details(value) fill_in 'user_otp_attempt', with: value click_on I18n.t('auth.login') end + + def oauth_authorize_text + I18n.t('doorkeeper.authorizations.buttons.authorize') + end + + def oauth_deny_text + I18n.t('doorkeeper.authorizations.buttons.deny') + end + + def redirect_to_callback_url + have_current_path(/\A#{client_app.redirect_uri}/, url: true) + end + + def user_has_grant_with_client_app? + Doorkeeper::AccessGrant + .exists?( + application: client_app, + resource_owner_id: user.id + ) + end end diff --git a/spec/system/report_interface_spec.rb b/spec/system/report_interface_spec.rb index 257a1cd6fd371c..6a90aa5bc66655 100644 --- a/spec/system/report_interface_spec.rb +++ b/spec/system/report_interface_spec.rb @@ -28,4 +28,17 @@ page.scroll_to(page.find('.batch-table__row')) expect(page).to have_css('.spoiler-button__overlay__label') end + + it 'marks a report resolved from the show page actions area' do + visit admin_report_path(report) + + expect { resolve_report } + .to change { report.reload.action_taken_at }.to(be_present).from(nil) + end + + def resolve_report + within '.report-actions' do + click_on I18n.t('admin.reports.mark_as_resolved') + end + 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/spec/workers/mention_resolve_worker_spec.rb b/spec/workers/mention_resolve_worker_spec.rb new file mode 100644 index 00000000000000..5e23876b4ae4f8 --- /dev/null +++ b/spec/workers/mention_resolve_worker_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe MentionResolveWorker do + let(:status_id) { -42 } + let(:uri) { 'https://example.com/users/unknown' } + + describe '#perform' do + subject { described_class.new.perform(status_id, uri, {}) } + + context 'with a non-existent status' do + it 'returns nil' do + expect(subject).to be_nil + end + end + + context 'with a valid user' do + let(:status) { Fabricate(:status) } + let(:status_id) { status.id } + + let(:service_double) { instance_double(ActivityPub::FetchRemoteAccountService) } + + before do + allow(ActivityPub::FetchRemoteAccountService).to receive(:new).and_return(service_double) + + allow(service_double).to receive(:call).with(uri, anything) { Fabricate(:account, domain: 'example.com', uri: uri) } + end + + it 'resolves the account and adds a new mention', :aggregate_failures do + expect { subject } + .to change { status.reload.mentions }.from([]).to(a_collection_including(having_attributes(account: having_attributes(uri: uri), silent: false))) + + expect(service_double).to have_received(:call).once + end + end + end +end diff --git a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb index 7071fa6e984e2f..98150aa5efd3bf 100644 --- a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb @@ -5,9 +5,50 @@ RSpec.describe Scheduler::IpCleanupScheduler do let(:worker) { described_class.new } - describe 'perform' do - it 'runs without error' do - expect { worker.perform }.to_not raise_error + describe '#perform' do + context 'with IP-related data past retention times' do + let!(:future_ip_block) { Fabricate :ip_block, expires_at: 1.week.from_now } + let!(:old_ip_block) { Fabricate :ip_block, expires_at: 1.week.ago } + let!(:session_past_retention) { Fabricate :session_activation, ip: '10.0.0.0', updated_at: 18.months.ago } + let!(:inactive_user) { Fabricate :user, current_sign_in_at: 18.months.ago, sign_up_ip: '10.0.0.0' } + let!(:old_login_activity) { Fabricate :login_activity, created_at: 18.months.ago } + let!(:old_token) { Fabricate :access_token, last_used_at: 18.months.ago, last_used_ip: '10.0.0.0' } + + before { stub_const 'Scheduler::IpCleanupScheduler::SESSION_RETENTION_PERIOD', 10.years.to_i.seconds } + + it 'deletes the expired block' do + expect { worker.perform } + .to_not raise_error + expect { old_ip_block.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect { old_login_activity.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect(session_past_retention.reload.ip) + .to be_nil + expect(inactive_user.reload.sign_up_ip) + .to be_nil + expect(old_token.reload.last_used_ip) + .to be_nil + expect(future_ip_block.reload) + .to be_present + end + end + + context 'with old session data' do + let!(:new_activation) { Fabricate :session_activation, updated_at: 1.week.ago } + let!(:old_activation) { Fabricate :session_activation, updated_at: 1.month.ago } + + before { stub_const 'Scheduler::IpCleanupScheduler::SESSION_RETENTION_PERIOD', 10.days.to_i.seconds } + + it 'clears old sessions' do + expect { worker.perform } + .to_not raise_error + + expect { old_activation.reload } + .to raise_error(ActiveRecord::RecordNotFound) + expect(new_activation.reload) + .to be_present + end end end end diff --git a/spec/workers/web/push_notification_worker_spec.rb b/spec/workers/web/push_notification_worker_spec.rb index ced21d5bf799b4..7f836d99e431f9 100644 --- a/spec/workers/web/push_notification_worker_spec.rb +++ b/spec/workers/web/push_notification_worker_spec.rb @@ -22,27 +22,48 @@ let(:payload) { { ciphertext: ciphertext, salt: salt, server_public_key: server_public_key, shared_secret: shared_secret } } describe 'perform' do + around do |example| + original_private = Rails.configuration.x.vapid_private_key + original_public = Rails.configuration.x.vapid_public_key + Rails.configuration.x.vapid_private_key = vapid_private_key + Rails.configuration.x.vapid_public_key = vapid_public_key + example.run + Rails.configuration.x.vapid_private_key = original_private + Rails.configuration.x.vapid_public_key = original_public + end + before do - allow(subscription).to receive_messages(contact_email: contact_email, vapid_key: vapid_key) - allow(Web::PushSubscription).to receive(:find).with(subscription.id).and_return(subscription) + Setting.site_contact_email = contact_email + allow(Webpush::Encryption).to receive(:encrypt).and_return(payload) allow(JWT).to receive(:encode).and_return('jwt.encoded.payload') stub_request(:post, endpoint).to_return(status: 201, body: '') + end + it 'calls the relevant service with the correct headers' do subject.perform(subscription.id, notification.id) + + expect(web_push_endpoint_request) + .to have_been_made end - it 'calls the relevant service with the correct headers' do - expect(a_request(:post, endpoint).with(headers: { - 'Content-Encoding' => 'aesgcm', - 'Content-Type' => 'application/octet-stream', - 'Crypto-Key' => "dh=BAgtUks5d90kFmxGevk9tH7GEmvz9DB0qcEMUsOBgKwMf-TMjsKIIG6LQvGcFAf6jcmAod15VVwmYwGIIxE4VWE;p256ecdsa=#{vapid_public_key.delete('=')}", - 'Encryption' => 'salt=WJeVM-RY-F9351SVxTFx_g', - 'Ttl' => '172800', - 'Urgency' => 'normal', - 'Authorization' => 'WebPush jwt.encoded.payload', - }, body: "+\xB8\xDBT}\u0013\xB6\xDD.\xF9\xB0\xA7\xC8Ҁ\xFD\x99#\xF7\xAC\x83\xA4\xDB,\u001F\xB5\xB9w\x85>\xF7\xADr")).to have_been_made + def web_push_endpoint_request + a_request( + :post, + endpoint + ).with( + headers: { + 'Content-Encoding' => 'aesgcm', + 'Content-Type' => 'application/octet-stream', + 'Crypto-Key' => "dh=BAgtUks5d90kFmxGevk9tH7GEmvz9DB0qcEMUsOBgKwMf-TMjsKIIG6LQvGcFAf6jcmAod15VVwmYwGIIxE4VWE;p256ecdsa=#{vapid_public_key.delete('=')}", + 'Encryption' => 'salt=WJeVM-RY-F9351SVxTFx_g', + 'Ttl' => '172800', + 'Urgency' => 'normal', + 'Authorization' => 'WebPush jwt.encoded.payload', + }, + body: "+\xB8\xDBT}\u0013\xB6\xDD.\xF9\xB0\xA7\xC8Ҁ\xFD\x99#\xF7\xAC\x83\xA4\xDB,\u001F\xB5\xB9w\x85>\xF7\xADr" + ) end end end diff --git a/streaming/Dockerfile b/streaming/Dockerfile index 938f1655d15d24..bed6b637380dac 100644 --- a/streaming/Dockerfile +++ b/streaming/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.9 +# syntax=docker/dockerfile:1.10 # Please see https://docs.docker.com/engine/reference/builder for information about # the extended buildx capabilities used in this file. diff --git a/streaming/index.js b/streaming/index.js index d792f95acf944b..7bbcc1497f9e50 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -235,7 +235,7 @@ const startServer = async () => { app.get('/favicon.ico', (_req, res) => res.status(404).end()); app.get('/api/v1/streaming/health', (_req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.writeHead(200, { 'Content-Type': 'text/plain', 'Cache-Control': 'private, no-store' }); res.end('OK'); }); @@ -865,7 +865,7 @@ const startServer = async () => { } res.setHeader('Content-Type', 'text/event-stream'); - res.setHeader('Cache-Control', 'no-store'); + res.setHeader('Cache-Control', 'private, no-store'); res.setHeader('Transfer-Encoding', 'chunked'); res.write(':)\n'); diff --git a/streaming/metrics.js b/streaming/metrics.js index bb6bce3f3c16a4..263339a1cafb6c 100644 --- a/streaming/metrics.js +++ b/streaming/metrics.js @@ -98,9 +98,11 @@ export function setupMetrics(channels, pgPool) { const requestHandler = (req, res) => { metrics.register.metrics().then((output) => { res.set('Content-Type', metrics.register.contentType); + res.set('Cache-Control', 'private, no-store'); res.end(output); }).catch((err) => { req.log.error(err, "Error collecting metrics"); + res.set('Cache-Control', 'private, no-store'); res.status(500).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/streaming/redis.js b/streaming/redis.js index 2a36b89dc553a3..0b582ef2f5eb04 100644 --- a/streaming/redis.js +++ b/streaming/redis.js @@ -50,9 +50,9 @@ function getSentinelConfiguration(env, commonOptions) { return { db: redisDatabase, name: env.REDIS_SENTINEL_MASTER, - username: env.REDIS_USERNAME, + username: env.REDIS_USER, password: env.REDIS_PASSWORD, - sentinelUsername: env.REDIS_SENTINEL_USERNAME ?? env.REDIS_USERNAME, + sentinelUsername: env.REDIS_SENTINEL_USERNAME ?? env.REDIS_USER, sentinelPassword: env.REDIS_SENTINEL_PASSWORD ?? env.REDIS_PASSWORD, sentinels, ...commonOptions, @@ -104,7 +104,7 @@ export function configFromEnv(env) { host: env.REDIS_HOST ?? '127.0.0.1', port: redisPort, db: redisDatabase, - username: env.REDIS_USERNAME, + username: env.REDIS_USER, password: env.REDIS_PASSWORD, ...commonOptions, }; diff --git a/yarn.lock b/yarn.lock index 5de514cc5a1204..58f0410bbd978b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,127 +42,127 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/code-frame@npm:7.24.7" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/code-frame@npm:7.25.7" dependencies: - "@babel/highlight": "npm:^7.24.7" + "@babel/highlight": "npm:^7.25.7" picocolors: "npm:^1.0.0" - checksum: 10c0/ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6 + checksum: 10c0/14825c298bdec914caf3d24d1383b6d4cd6b030714686004992f4fc251831ecf432236652896f99d5d341f17170ae9a07b58d8d7b15aa0df8cfa1c5a7d5474bc languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.2, @babel/compat-data@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/compat-data@npm:7.25.4" - checksum: 10c0/50d79734d584a28c69d6f5b99adfaa064d0f41609a378aef04eb06accc5b44f8520e68549eba3a082478180957b7d5783f1bfb1672e4ae8574e797ce8bae79fa +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.7, @babel/compat-data@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/compat-data@npm:7.25.8" + checksum: 10c0/8b81c17580e5fb4cbb6a3c52079f8c283fc59c0c6bd2fe14cfcf9c44b32d2eaab71b02c5633e2c679f5896f73f8ac4036ba2e67a4c806e8f428e4b11f526d7f4 languageName: node linkType: hard -"@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1, @babel/core@npm:^7.24.4": - version: 7.25.2 - resolution: "@babel/core@npm:7.25.2" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1, @babel/core@npm:^7.24.4, @babel/core@npm:^7.25.0": + version: 7.25.8 + resolution: "@babel/core@npm:7.25.8" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.25.0" - "@babel/helper-compilation-targets": "npm:^7.25.2" - "@babel/helper-module-transforms": "npm:^7.25.2" - "@babel/helpers": "npm:^7.25.0" - "@babel/parser": "npm:^7.25.0" - "@babel/template": "npm:^7.25.0" - "@babel/traverse": "npm:^7.25.2" - "@babel/types": "npm:^7.25.2" + "@babel/code-frame": "npm:^7.25.7" + "@babel/generator": "npm:^7.25.7" + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-module-transforms": "npm:^7.25.7" + "@babel/helpers": "npm:^7.25.7" + "@babel/parser": "npm:^7.25.8" + "@babel/template": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.8" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401 + checksum: 10c0/8411ea506e6f7c8a39ab5c1524b00589fa3b087edb47389708f7fe07170929192171734666e3ea10b95a951643a531a6d09eedfe071572c9ea28516646265086 languageName: node linkType: hard -"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.4, @babel/generator@npm:^7.7.2": - version: 7.25.4 - resolution: "@babel/generator@npm:7.25.4" +"@babel/generator@npm:^7.25.7, @babel/generator@npm:^7.7.2": + version: 7.25.7 + resolution: "@babel/generator@npm:7.25.7" dependencies: - "@babel/types": "npm:^7.25.4" + "@babel/types": "npm:^7.25.7" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" - jsesc: "npm:^2.5.1" - checksum: 10c0/a2d8cc39e759214740f836360c8d9c17aa93e16e41afe73368a9e7ccd1d5c3303a420ce3aca1c9a31fdb93d1899de471d5aac97d1c64f741f8750a25a6e91fbc + jsesc: "npm:^3.0.2" + checksum: 10c0/c03a26c79864d60d04ce36b649c3fa0d6fd7b2bf6a22e22854a0457aa09206508392dd73ee40e7bc8d50b3602f9ff068afa47770cda091d332e7db1ca382ee96 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" +"@babel/helper-annotate-as-pure@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.25.7" dependencies: - "@babel/types": "npm:^7.24.7" - checksum: 10c0/4679f7df4dffd5b3e26083ae65228116c3da34c3fff2c11ae11b259a61baec440f51e30fd236f7a0435b9d471acd93d0bc5a95df8213cbf02b1e083503d81b9a + "@babel/types": "npm:^7.25.7" + checksum: 10c0/2f020b0fa9d336b5778485cc2de3141561ec436a7591b685457a5bcdae4ce41d9ddee68169c95504e0789e5a4327e73b8b7e72e5b60e82e96d730c4d19255248 languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.25.7" dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/0ed84abf848c79fb1cd4c1ddac12c771d32c1904d87fc3087f33cfdeb0c2e0db4e7892b74b407d9d8d0c000044f3645a7391a781f788da8410c290bb123a1f13 + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/e9dc5a7920a1d74150dec53ccd5e34f2b31ae307df7cdeec6289866f7bda97ecb1328b49a7710ecde5db5b6daad768c904a030f9a0fa3184963b0017622c42aa languageName: node linkType: hard -"@babel/helper-builder-react-jsx@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-builder-react-jsx@npm:7.24.7" +"@babel/helper-builder-react-jsx@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-builder-react-jsx@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/c95c8856c67c57060461f39b669707b2dca3501149bcc54b7c3e49c95069afce52179fc7c2bd809981acfbfdf0860ef1035dd7512cdba46c83bdb1ad6f6dc53f + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/f8123a76e8c3fcdbb24cc14bfefc80e4c7bf58112ab26bea3247298748c674cbaee70591c362d0d881e4d88154ea4809b145f3ddcf96221cf55ba27bfde535c6 languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8, @babel/helper-compilation-targets@npm:^7.25.2": - version: 7.25.2 - resolution: "@babel/helper-compilation-targets@npm:7.25.2" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-compilation-targets@npm:7.25.7" dependencies: - "@babel/compat-data": "npm:^7.25.2" - "@babel/helper-validator-option": "npm:^7.24.8" - browserslist: "npm:^4.23.1" + "@babel/compat-data": "npm:^7.25.7" + "@babel/helper-validator-option": "npm:^7.25.7" + browserslist: "npm:^4.24.0" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/de10e986b5322c9f807350467dc845ec59df9e596a5926a3b5edbb4710d8e3b8009d4396690e70b88c3844fe8ec4042d61436dd4b92d1f5f75655cf43ab07e99 + checksum: 10c0/705be7e5274a3fdade68e3e2cf42e2b600316ab52794e13b91299a16f16c926f15886b6e9d6df20eb943ccc1cdba5a363d4766f8d01e47b8e6f4e01175f5e66c languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.24.7, @babel/helper-create-class-features-plugin@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/helper-create-class-features-plugin@npm:7.25.4" +"@babel/helper-create-class-features-plugin@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-member-expression-to-functions": "npm:^7.24.8" - "@babel/helper-optimise-call-expression": "npm:^7.24.7" - "@babel/helper-replace-supers": "npm:^7.25.0" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.4" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-member-expression-to-functions": "npm:^7.25.7" + "@babel/helper-optimise-call-expression": "npm:^7.25.7" + "@babel/helper-replace-supers": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/a765d9e0482e13cf96642fa8aa28e6f7d4d7d39f37840d6246e5e10a7c47f47c52d52522edd3073f229449d17ec0db6f9b7b5e398bff6bb0b4994d65957a164c + checksum: 10c0/405c3c1a137acda1206380a96993cf2cfd808b3bee1c11c4af47ee0f03a20858497aa53394d6adc5431793c543be5e02010620e871a5ab39d938ae90a54b50f2 languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7, @babel/helper-create-regexp-features-plugin@npm:^7.25.0, @babel/helper-create-regexp-features-plugin@npm:^7.25.2": - version: 7.25.2 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.2" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - regexpu-core: "npm:^5.3.1" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + regexpu-core: "npm:^6.1.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/85a7e3639c118856fb1113f54fb7e3bf7698171ddfd0cd6fccccd5426b3727bc1434fe7f69090441dcde327feef9de917e00d35e47ab820047057518dd675317 + checksum: 10c0/75919fd5a67cd7be8497b56f7b9ed6b4843cb401956ba8d403aa9ae5b005bc28e35c7f27e704d820edbd1154394ed7a7984d4719916795d89d716f6980fe8bd4 languageName: node linkType: hard @@ -181,223 +181,223 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-member-expression-to-functions@npm:7.24.8" +"@babel/helper-member-expression-to-functions@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.25.7" dependencies: - "@babel/traverse": "npm:^7.24.8" - "@babel/types": "npm:^7.24.8" - checksum: 10c0/7e14a5acc91f6cd26305a4441b82eb6f616bd70b096a4d2099a968f16b26d50207eec0b9ebfc466fefd62bd91587ac3be878117cdfec819b7151911183cb0e5a + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/1e948162ab48d84593a7c6ec9570d14c906146f1697144fc369c59dbeb00e4a062da67dd06cb0d8f98a044cd8389002dcf2ab6f5613d99c35748307846ec63fc languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.0.0-beta.49, @babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-module-imports@npm:7.24.7" +"@babel/helper-module-imports@npm:^7.0.0-beta.49, @babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-module-imports@npm:7.25.7" dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/97c57db6c3eeaea31564286e328a9fb52b0313c5cfcc7eee4bc226aebcf0418ea5b6fe78673c0e4a774512ec6c86e309d0f326e99d2b37bfc16a25a032498af0 + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/0fd0c3673835e5bf75558e184bcadc47c1f6dd2fe2016d53ebe1e5a6ae931a44e093015c2f9a6651c1a89f25c76d9246710c2b0b460b95ee069c464f2837fa2c languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.25.0, @babel/helper-module-transforms@npm:^7.25.2": - version: 7.25.2 - resolution: "@babel/helper-module-transforms@npm:7.25.2" +"@babel/helper-module-transforms@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-module-transforms@npm:7.25.7" dependencies: - "@babel/helper-module-imports": "npm:^7.24.7" - "@babel/helper-simple-access": "npm:^7.24.7" - "@babel/helper-validator-identifier": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.2" + "@babel/helper-module-imports": "npm:^7.25.7" + "@babel/helper-simple-access": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/adaa15970ace0aee5934b5a633789b5795b6229c6a9cf3e09a7e80aa33e478675eee807006a862aa9aa517935d81f88a6db8a9f5936e3a2a40ec75f8062bc329 + checksum: 10c0/f37fa7d1d4df21690535b278468cbd5faf0133a3080f282000cfa4f3ffc9462a1458f866b04b6a2f2d1eec4691236cba9a867da61270dab3ab19846e62f05090 languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" +"@babel/helper-optimise-call-expression@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.25.7" dependencies: - "@babel/types": "npm:^7.24.7" - checksum: 10c0/ca6a9884705dea5c95a8b3ce132d1e3f2ae951ff74987d400d1d9c215dae9c0f9e29924d8f8e131e116533d182675bc261927be72f6a9a2968eaeeaa51eb1d0f + "@babel/types": "npm:^7.25.7" + checksum: 10c0/19b4cc7e77811b1fedca4928dbc14026afef913c2ba4142e5e110ebdcb5c3b2efc0f0fbee9f362c23a194674147b9d627adea71c289b9be08b9067bc0085308b languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.24.8 - resolution: "@babel/helper-plugin-utils@npm:7.24.8" - checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.25.0, @babel/helper-plugin-utils@npm:^7.25.7, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.25.7 + resolution: "@babel/helper-plugin-utils@npm:7.25.7" + checksum: 10c0/241f8cf3c5b7700e91cab7cfe5b432a3c710ae3cd5bb96dc554da536a6d25f5b9f000cc0c0917501ceb4f76ba92599ee3beb25e10adaf96be59f8df89a842faf languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.24.7, @babel/helper-remap-async-to-generator@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/helper-remap-async-to-generator@npm:7.25.0" +"@babel/helper-remap-async-to-generator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-wrap-function": "npm:^7.25.0" - "@babel/traverse": "npm:^7.25.0" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-wrap-function": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/0d17b5f7bb6a607edc9cc62fff8056dd9f341bf2f919884f97b99170d143022a5e7ae57922c4891e4fc360ad291e708d2f8cd8989f1d3cd7a17600159984f5a6 + checksum: 10c0/972d84876adce6ab61c87a2df47e1afc790b73cff0d1767d0a1c5d9f7aa5e91d8c581a272b66b2051a26cfbb167d8a780564705e488e3ce1f477f1c15059bc5f languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.24.7, @babel/helper-replace-supers@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/helper-replace-supers@npm:7.25.0" +"@babel/helper-replace-supers@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-replace-supers@npm:7.25.7" dependencies: - "@babel/helper-member-expression-to-functions": "npm:^7.24.8" - "@babel/helper-optimise-call-expression": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.0" + "@babel/helper-member-expression-to-functions": "npm:^7.25.7" + "@babel/helper-optimise-call-expression": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b4b6650ab3d56c39a259367cd97f8df2f21c9cebb3716fea7bca40a150f8847bfb82f481e98927c7c6579b48a977b5a8f77318a1c6aeb497f41ecd6dbc3fdfef + checksum: 10c0/761d64ee74429f7326a6aa65e2cd5bfcb8de9e3bc3f1efb14b8f610d2410f003b0fca52778dc801d49ff8fbc90b057e8f51b27c62b0b05c95eaf23140ca1287b languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-simple-access@npm:7.24.7" +"@babel/helper-simple-access@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-simple-access@npm:7.25.7" dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/7230e419d59a85f93153415100a5faff23c133d7442c19e0cd070da1784d13cd29096ee6c5a5761065c44e8164f9f80e3a518c41a0256df39e38f7ad6744fed7 + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/eed1b499bfb4f613c18debd61517e3de77b6da2727ca025aa05ac81599e0269f1dddb5237db04e8bb598115d015874752e0a7f11ff38672d74a4976097417059 languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.7" dependencies: - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/e3a9b8ac9c262ac976a1bcb5fe59694db5e6f0b4f9e7bdba5c7693b8b5e28113c23bdaa60fe8d3ec32a337091b67720b2053bcb3d5655f5406536c3d0584242b + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/5804adb893849a9d8cfb548e3812566a81d95cb0c9a10d66b52912d13f488e577c33063bf19bc06ac70e6333162a7370d67ba1a1c3544d37fb50d5f4a00db4de languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-string-parser@npm:7.24.8" - checksum: 10c0/6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08 +"@babel/helper-string-parser@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-string-parser@npm:7.25.7" + checksum: 10c0/73ef2ceb81f8294678a0afe8ab0103729c0370cac2e830e0d5128b03be5f6a2635838af31d391d763e3c5a4460ed96f42fd7c9b552130670d525be665913bc4c languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-identifier@npm:7.24.7" - checksum: 10c0/87ad608694c9477814093ed5b5c080c2e06d44cb1924ae8320474a74415241223cc2a725eea2640dd783ff1e3390e5f95eede978bc540e870053152e58f1d651 +"@babel/helper-validator-identifier@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-validator-identifier@npm:7.25.7" + checksum: 10c0/07438e5bf01ab2882a15027fdf39ac3b0ba1b251774a5130917907014684e2f70fef8fd620137ca062c4c4eedc388508d2ea7a3a7d9936a32785f4fe116c68c0 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-validator-option@npm:7.24.8" - checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f +"@babel/helper-validator-option@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-validator-option@npm:7.25.7" + checksum: 10c0/12ed418c8e3ed9ed44c8c80d823f4e42d399b5eb2e423adccb975e31a31a008cd3b5d8eab688b31f740caff4a1bb28fe06ea2fa7d635aee34cc0ad6995d50f0a languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/helper-wrap-function@npm:7.25.0" +"@babel/helper-wrap-function@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helper-wrap-function@npm:7.25.7" dependencies: - "@babel/template": "npm:^7.25.0" - "@babel/traverse": "npm:^7.25.0" - "@babel/types": "npm:^7.25.0" - checksum: 10c0/d54601a98384c191cbc1ff07b03a19e288ef8d5c6bfafe270b2a303d96e7304eb296002921ed464cc1b105a547d1db146eb86b0be617924dee1ba1b379cdc216 + "@babel/template": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/b5d412f72697f4a4ce4cb9784fbaf82501c63cf95066c0eadd3179e3439cbbf0aa5fa4858d93590083671943cd357aeb87286958df34aa56fdf8a4c9dea39755 languageName: node linkType: hard -"@babel/helpers@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/helpers@npm:7.25.0" +"@babel/helpers@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/helpers@npm:7.25.7" dependencies: - "@babel/template": "npm:^7.25.0" - "@babel/types": "npm:^7.25.0" - checksum: 10c0/b7fe007fc4194268abf70aa3810365085e290e6528dcb9fbbf7a765d43c74b6369ce0f99c5ccd2d44c413853099daa449c9a0123f0b212ac8d18643f2e8174b8 + "@babel/template": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/3b3ae9e373bd785414195ef8f59976a69d5a6ebe0ef2165fdcc5165e5c3ee09e0fcee94bb457df2ddb8c0532e4146d0a9b7a96b3497399a4bff4ffe196b30228 languageName: node linkType: hard -"@babel/highlight@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/highlight@npm:7.24.7" +"@babel/highlight@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/highlight@npm:7.25.7" dependencies: - "@babel/helper-validator-identifier": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.25.7" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: 10c0/674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a + checksum: 10c0/1f5894fdb0a0af6101fb2822369b2eeeae32cbeae2ef73ff73fc6a0a4a20471565cd9cfa589f54ed69df66adeca7c57266031ca9134b7bd244d023a488d419aa languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/parser@npm:7.25.4" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.7, @babel/parser@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/parser@npm:7.25.8" dependencies: - "@babel/types": "npm:^7.25.4" + "@babel/types": "npm:^7.25.8" bin: parser: ./bin/babel-parser.js - checksum: 10c0/bdada5662f15d1df11a7266ec3bc9bb769bf3637ecf3d051eafcfc8f576dcf5a3ac1007c5e059db4a1e1387db9ae9caad239fc4f79e4c2200930ed610e779993 + checksum: 10c0/a1a13845b7e8dda4c970791814a4bbf60004969882f18f470e260ad822d2e1f8941948f851e9335895563610f240fa6c98481ce8019865e469502bbf21daafa4 languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.3": - version: 7.25.3 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.3" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/traverse": "npm:^7.25.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/814b4d3f102e7556a5053d1acf57ef601cfcff39a2c81b8cdc6a5c842e3cb9838f5925d1466a5f1e6416e74c9c83586a3c07fbd7fb8610a396c2becdf9ae5790 + checksum: 10c0/c6ba97c39973897a2ab021c4a77221e1e93e853a5811d498db325da1bd692e41fa521db6d91bb709ccafd4e54ddd00869ffb35846923c3ccd49d46124b316904 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.0" +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/9645a1f47b3750acadb1353c02e71cc712d072aafe5ce115ed3a886bc14c5d9200cfb0b5b5e60e813baa549b800cf798f8714019fd246c699053cf68c428e426 + checksum: 10c0/ac284868bf410f952c6959b0d77708464127160416f003b05c8127d30e64792d671abc167ebf778b17707e32174223ea8d3ff487276991fa90297d92f0dac6e2 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.0" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/ed1ce1c90cac46c01825339fd0f2a96fa071b016fb819d8dfaf8e96300eae30e74870cb47e4dc80d4ce2fb287869f102878b4f3b35bc927fec8b1d0d76bcf612 + checksum: 10c0/1bffc0a20c8c82b4c77515eb4c99b961b38184116f008bb42bed4e12d3379ba7b2bc6cf299bcea8118d645bb7a5e0caa83969842f16dd1fce49fb3a050e4ac65 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.7" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.13.0 - checksum: 10c0/aeb6e7aa363a47f815cf956ea1053c5dd8b786a17799f065c9688ba4b0051fe7565d258bbe9400bfcbfb3114cb9fda66983e10afe4d750bc70ff75403e15dd36 + checksum: 10c0/32223f012614a0b2657579317ded7d0d09af2aa316285715c5012f974d0f15c2ce2fe0d8e80fdd9bac6c10c21c93cc925a9dfd6c8e21ce7ba1a9fe06a58088b4 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.0" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/traverse": "npm:^7.25.0" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/45988025537a9d4a27b610fd696a18fd9ba9336621a69b4fb40560eeb10c79657f85c92a37f30c7c8fb29c22970eea0b373315795a891f1a05549a6cfe5a6bfe + checksum: 10c0/aa2ee7a5954d187de6cbcca0e0b64cfb79c4d224c332d1eb1e0e4afd92ef1a1f4bc4af24f66154097ccb348c08121a875456f47baed220b1b9e93584e6a19b65 languageName: node linkType: hard @@ -432,7 +432,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": +"@babel/plugin-syntax-class-properties@npm:^7.8.3": version: 7.12.13 resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: @@ -443,62 +443,29 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-static-block@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 - languageName: node - linkType: hard - -"@babel/plugin-syntax-dynamic-import@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/9c50927bf71adf63f60c75370e2335879402648f468d0172bc912e303c6a3876927d8eb35807331b57f415392732ed05ab9b42c68ac30a936813ab549e0246c5 - languageName: node - linkType: hard - -"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.3" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/5100d658ba563829700cd8d001ddc09f4c0187b1a13de300d729c5b3e87503f75a6d6c99c1794182f7f1a9f546ee009df4f15a0ce36376e206ed0012fa7cdc24 - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-assertions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.7" +"@babel/plugin-syntax-import-assertions@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b82c53e095274ee71c248551352d73441cf65b3b3fc0107258ba4e9aef7090772a425442b3ed1c396fa207d0efafde8929c87a17d3c885b3ca2021316e87e246 + checksum: 10c0/0fee0d971f3c654749fdf92e09b6556bba26ab014c8e99b7252f6a7f1ca108f17edd7ceefb5401d7b7008e98ab1b6f8c3c6a5db72862e7c7b2fcd649d000d690 languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" +"@babel/plugin-syntax-import-attributes@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/eccc54d0f03c96d0eec7a6e2fa124dadbc7298345b62ffc4238f173308c4325b5598f139695ff05a95cf78412ef6903599e4b814496612bf39aad4715a16375b + checksum: 10c0/fe00cdb96fd289ab126830a98e1dcf5ab7b529a6ef1c01a72506b5e7b1197d6e46c3c4d029cd90d1d61eb9a15ef77c282d156d0c02c7e32f168bb09d84150db4 languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.10.4, @babel/plugin-syntax-import-meta@npm:^7.8.3": +"@babel/plugin-syntax-import-meta@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" dependencies: @@ -520,18 +487,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:7, @babel/plugin-syntax-jsx@npm:^7.24.7, @babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.24.7 - resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" +"@babel/plugin-syntax-jsx@npm:^7.25.0, @babel/plugin-syntax-jsx@npm:^7.25.7, @babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.25.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f44d927a9ae8d5ef016ff5b450e1671e56629ddc12e56b938e41fd46e141170d9dfc9a53d6cb2b9a20a7dd266a938885e6a3981c60c052a2e1daed602ac80e51 + checksum: 10c0/17db499c31fcfaa94d5408726d943955d51d478353d1e2dd84eda6024f7e3d104b9456a77f8aabfae0db7f4dc32f810d08357112f7fcbe305e7c9fcf5b3cac13 languageName: node linkType: hard -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" dependencies: @@ -553,7 +520,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-numeric-separator@npm:^7.10.4, @babel/plugin-syntax-numeric-separator@npm:^7.8.3": +"@babel/plugin-syntax-numeric-separator@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" dependencies: @@ -597,18 +564,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": - version: 7.14.5 - resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 - languageName: node - linkType: hard - -"@babel/plugin-syntax-top-level-await@npm:^7.14.5, @babel/plugin-syntax-top-level-await@npm:^7.8.3": +"@babel/plugin-syntax-top-level-await@npm:^7.8.3": version: 7.14.5 resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" dependencies: @@ -619,14 +575,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.24.7, @babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.24.7 - resolution: "@babel/plugin-syntax-typescript@npm:7.24.7" +"@babel/plugin-syntax-typescript@npm:^7.25.7, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.25.7 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/cdabd2e8010fb0ad15b49c2c270efc97c4bfe109ead36c7bbcf22da7a74bc3e49702fc4f22f12d2d6049e8e22a5769258df1fd05f0420ae45e11bdd5bc07805a + checksum: 10c0/ed51fd81a5cf571a89fc4cf4c0e3b0b91285c367237374c133d2e5e718f3963cfa61b81997df39220a8837dc99f9e9a8ab7701d259c09fae379e4843d9db60c2 languageName: node linkType: hard @@ -642,466 +598,454 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.7" +"@babel/plugin-transform-arrow-functions@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6ac05a54e5582f34ac6d5dc26499e227227ec1c7fa6fc8de1f3d40c275f140d3907f79bbbd49304da2d7008a5ecafb219d0b71d78ee3290ca22020d878041245 + checksum: 10c0/c8d75ead93f130bf113b6d29493aca695092661ef039336d2a227169c3b7895aa5e9bcc548c42a95a6eaaaf49e512317b00699940bd40ccefd77443e703d3935 languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.4" +"@babel/plugin-transform-async-generator-functions@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-remap-async-to-generator": "npm:^7.25.0" - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/traverse": "npm:^7.25.4" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-remap-async-to-generator": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/efed6f6be90b25ad77c15a622a0dc0b22dbf5d45599c207ab8fbc4e959aef21f574fa467d9cf872e45de664a46c32334e78dee2332d82f5f27e26249a34a0920 + checksum: 10c0/1698d0757d3dc895047120346cdbe6d539dae4a7bb930caf958c3623e89c850d378d1ebd971a1a8b4cba39c8f001cd9c25a1d6f430099022ab1e87aeddb5dd88 languageName: node linkType: hard -"@babel/plugin-transform-async-to-generator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" +"@babel/plugin-transform-async-to-generator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.25.7" dependencies: - "@babel/helper-module-imports": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-remap-async-to-generator": "npm:^7.24.7" + "@babel/helper-module-imports": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-remap-async-to-generator": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/83c82e243898875af8457972a26ab29baf8a2078768ee9f35141eb3edff0f84b165582a2ff73e90a9e08f5922bf813dbf15a85c1213654385198f4591c0dc45d + checksum: 10c0/1dbefba9c1455f7a92b8c59a93c622091db945294c936fc2c09b1648308c5b4cb2ecaae92baae0d07a324ab890a8a2ee27ceb046bc120932845d27aede275821 languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.7" +"@babel/plugin-transform-block-scoped-functions@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/113e86de4612ae91773ff5cb6b980f01e1da7e26ae6f6012127415d7ae144e74987bc23feb97f63ba4bc699331490ddea36eac004d76a20d5369e4cc6a7f61cd + checksum: 10c0/b1e77492295d1b271ef850a81b0404cf3d0dd6a2bcbeab28a0fd99e61c6de4bda91dff583bb42138eec61bf71282bdd3b1bebcb53b7e373035e77fd6ba66caeb languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-transform-block-scoping@npm:7.25.0" +"@babel/plugin-transform-block-scoping@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/382931c75a5d0ea560387e76cb57b03461300527e4784efcb2fb62f36c1eb0ab331327b6034def256baa0cad9050925a61f9c0d56261b6afd6a29c3065fb0bd4 + checksum: 10c0/b2057e00535cd0e8bd5ee5d4640aa2e952564aeafb1bcf4e7b6de33442422877bb0ca8669ad0a48262ec077271978c61eae87b6b3bc8f472d830fa781d6f7e44 languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-class-properties@npm:7.25.4" +"@babel/plugin-transform-class-properties@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.25.4" - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/0b41bc8a5920d3d17c7c06220b601cf43e0a32ac34f05f05cd0cdf08915e4521b1b707cb1e60942b4fc68a5dfac09f0444a8720e0c72ce76fb039e8ec5263115 + checksum: 10c0/1f41e6934b20ad3e05df63959cff9bc600ff3119153b9acbbd44c1731e7df04866397e6e17799173f4c53cdee6115e155632859aee20bf47ec7dcef3f2168a47 languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" +"@babel/plugin-transform-class-static-block@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-class-static-block@npm:7.25.8" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.12.0 - checksum: 10c0/b0ade39a3d09dce886f79dbd5907c3d99b48167eddb6b9bbde24a0598129654d7017e611c20494cdbea48b07ac14397cd97ea34e3754bbb2abae4e698128eccb + checksum: 10c0/4f37853aef6920875022bbb2d7c6523218d9d718291464e2cacd9cc6f2c22d86a69948d8ea38f9248843bbfe9343f3fd18cf16b1615560124198bf999e3ba612 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-classes@npm:7.25.4" +"@babel/plugin-transform-classes@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-classes@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.25.2" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-replace-supers": "npm:^7.25.0" - "@babel/traverse": "npm:^7.25.4" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-replace-supers": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c68424d9dd64860825111aa4a4ed5caf29494b7a02ddb9c36351d768c41e8e05127d89274795cdfcade032d9d299e6c677418259df58c71e68f1741583dcf467 + checksum: 10c0/8121781e1d8acd80e6169019106f73a399475ad9c895c1988a344dfed5a6ddd340938ac55123dc1e423bb8f25f255f5d11031116ad756ba3c314595a97c973af languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-computed-properties@npm:7.24.7" +"@babel/plugin-transform-computed-properties@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/template": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/template": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/25636dbc1f605c0b8bc60aa58628a916b689473d11551c9864a855142e36742fe62d4a70400ba3b74902338e77fb3d940376c0a0ba154b6b7ec5367175233b49 + checksum: 10c0/7ad0a1c126f50935a02e77d438ebc39078a9d644b3a60de60bec32c5d9f49e7f2b193fcecb8c61bb1bc3cdd4af1e93f72d022d448511fa76a171527c633cd1bf languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" +"@babel/plugin-transform-destructuring@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-destructuring@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/804968c1d5f5072c717505296c1e5d5ec33e90550423de66de82bbcb78157156e8470bbe77a04ab8c710a88a06360a30103cf223ac7eff4829adedd6150de5ce + checksum: 10c0/a563123b2fb267e03aa50104005f00b56226a685938906c42c1b251462e0cc9fc89e587d5656d3324159071eb8ebda8c68a6011f11d5a00fb1436cb5a5411b7b languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.7" +"@babel/plugin-transform-dotall-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/793f14c9494972d294b7e7b97b747f47874b6d57d7804d3443c701becf5db192c9311be6a1835c07664486df1f5c60d33196c36fb7e11a53015e476b4c145b33 + checksum: 10c0/7f1db3ec20b7fae46db4a9c4c257d75418b0896b72c0a3de20b3044f952801480f0a2e75ebb0d64f13e8cd4db0e49aa42c5c0edff372b23c41679b1ea5dd3ed4 languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.7" +"@babel/plugin-transform-duplicate-keys@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/75ff7ec1117ac500e77bf20a144411d39c0fdd038f108eec061724123ce6d1bb8d5bd27968e466573ee70014f8be0043361cdb0ef388f8a182d1d97ad67e51b9 + checksum: 10c0/b4079981e2db19737a0f1a00254e7388e2d3c01ce36e9fd826e4d86d3c1755339495e29c71fd7c84a068201ec24687328d48f3bf53b32b6d6224f51d9a34da74 languageName: node linkType: hard -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.0" +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.0" - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/1c9b57ddd9b33696e88911d0e7975e1573ebc46219c4b30eb1dc746cbb71aedfac6f6dab7fdfdec54dd58f31468bf6ab56b157661ea4ffe58f906d71f89544c8 + checksum: 10c0/e4946090ff6d88d54b78265ee653079ec34c117ac046e22f66f7c4ac44249cdc2dfca385bc5bf4386db668b9948eeb12985589500188bc252e684c7714c31475 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" +"@babel/plugin-transform-dynamic-import@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/eeda48372efd0a5103cb22dadb13563c975bce18ae85daafbb47d57bb9665d187da9d4fe8d07ac0a6e1288afcfcb73e4e5618bf75ff63fddf9736bfbf225203b + checksum: 10c0/9726abc1b07771a9c1e3670908ac425d21e29f54c775d10ed7a4e2bc0a18e07600f70bbc531deba3fb3ff7f6763c189200593264c6f784dac583e653b66fe754 languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.7" +"@babel/plugin-transform-exponentiation-operator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.25.7" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ace3e11c94041b88848552ba8feb39ae4d6cad3696d439ff51445bd2882d8b8775d85a26c2c0edb9b5e38c9e6013cc11b0dea89ec8f93c7d9d7ee95e3645078c + checksum: 10c0/c8537b9f3cddc5a8d3710f6980196dc7a0f4389f8f82617312a5f7b8b15bcd8ddaeba783c687c3ac6031eb0a4ba0bc380a98da6bf7efe98e225602a98ad42a1e languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.7" +"@babel/plugin-transform-export-namespace-from@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4e144d7f1c57bc63b4899dbbbdfed0880f2daa75ea9c7251c7997f106e4b390dc362175ab7830f11358cb21f6b972ca10a43a2e56cd789065f7606b082674c0c + checksum: 10c0/8a2e1205dd727a96a9adef0e981d68c61b1c286480b9136e2aa67ce3e2c742be4f87feb9fb4c5548a401aba0953d43d66e9ec36a54dea6a7c15f1ee9345baf57 languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-for-of@npm:7.24.7" +"@babel/plugin-transform-for-of@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-for-of@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/77629b1173e55d07416f05ba7353caa09d2c2149da2ca26721ab812209b63689d1be45116b68eadc011c49ced59daf5320835b15245eb7ae93ae0c5e8277cfc0 + checksum: 10c0/08a37a1742368a422d095c998ed76f60f6bf3f9cc060033be121d803fd2dddc08fe543e48ee49c022bdc9ed80893ca79d084958d83d30684178b088774754277 languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.25.1": - version: 7.25.1 - resolution: "@babel/plugin-transform-function-name@npm:7.25.1" +"@babel/plugin-transform-function-name@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-function-name@npm:7.25.7" dependencies: - "@babel/helper-compilation-targets": "npm:^7.24.8" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/traverse": "npm:^7.25.1" + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e74912174d5e33d1418b840443c2e226a7b76cc017c1ed20ee30a566e4f1794d4a123be03180da046241576e8b692731807ba1f52608922acf1cb2cb6957593f + checksum: 10c0/ca98e1116c0ada7211ed43e4b7f21ca15f95bbbdad70f2fbe1ec2d90a97daedf9f22fcb0a25c8b164a5e394f509f2e4d1f7609d26dc938a58d37c5ee9b80088a languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-json-strings@npm:7.24.7" +"@babel/plugin-transform-json-strings@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-json-strings@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/17c72cd5bf3e90e722aabd333559275f3309e3fa0b9cea8c2944ab83ae01502c71a2be05da5101edc02b3fc8df15a8dbb9b861cbfcc8a52bf5e797cf01d3a40a + checksum: 10c0/2a6cf69ebe8deebc39c56adae75d609e16786dc4cbd83577eefdc838bd89ca8974671d47e2669b8e65ef9b7ace427f7c2c5a9fc6aa09247b10e141d15fee81cf languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.25.2": - version: 7.25.2 - resolution: "@babel/plugin-transform-literals@npm:7.25.2" +"@babel/plugin-transform-literals@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-literals@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/0796883217b0885d37e7f6d350773be349e469a812b6bf11ccf862a6edf65103d3e7c849529d65381b441685c12e756751d8c2489a0fd3f8139bb5ef93185f58 + checksum: 10c0/c2c2488102f33e566f45becdcb632e53bd052ecfb2879deb07a614b3e9437e3b624c3b16d080096d50b0b622edebd03e438acbf9260bcc41167897963f64560e languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.7" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/dbe882eb9053931f2ab332c50fc7c2a10ef507d6421bd9831adbb4cb7c9f8e1e5fbac4fbd2e007f6a1bf1df1843547559434012f118084dc0bf42cda3b106272 + checksum: 10c0/9adc2634c94b283b682fbf71bbec553bd8448196213491a0ef9ea167993c9c36dcb2fbefbd834e113cfed843a67290131bc99e463f8702043c3f4e3a99bb807e languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" +"@babel/plugin-transform-member-expression-literals@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e789ae359bdf2d20e90bedef18dfdbd965c9ebae1cee398474a0c349590fda7c8b874e1a2ceee62e47e5e6ec1730e76b0f24e502164357571854271fc12cc684 + checksum: 10c0/d6936b98ae4d3daed850dc4e064042ea4375f815219ba9d8591373bf1fba4cfdb5be42623ae8882f2d666cc34af650a4855e2a5ad89e3c235d73a6f172f9969c languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-amd@npm:7.24.7" +"@babel/plugin-transform-modules-amd@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.25.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6df7de7fce34117ca4b2fa07949b12274c03668cbfe21481c4037b6300796d50ae40f4f170527b61b70a67f26db906747797e30dbd0d9809a441b6e220b5728f + checksum: 10c0/c0bc999206c3834c090e6559a6c8a55d7672d3573104e832223ebe7df99bd1b82fc850e15ba32f512c84b0db1cdb613b66fa60abe9abb9c7e8dcbff91649b356 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.7, @babel/plugin-transform-modules-commonjs@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" +"@babel/plugin-transform-modules-commonjs@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.25.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.8" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-simple-access": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-simple-access": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f1cf552307ebfced20d3907c1dd8be941b277f0364aa655e2b5fee828c84c54065745183104dae86f1f93ea0406db970a463ef7ceaaed897623748e99640e5a7 + checksum: 10c0/2f1c945fc3c9b690b0ddcf2c80156b2e4fbf2cf15aac43ac8fe6e4b34125869528839a53d07c564e62e4aed394ebdc1d2c3b796b547374455522581c11b7599c languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.25.0": - version: 7.25.0 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.0" +"@babel/plugin-transform-modules-systemjs@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.25.0" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-validator-identifier": "npm:^7.24.7" - "@babel/traverse": "npm:^7.25.0" + "@babel/helper-module-transforms": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.7" + "@babel/traverse": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/fca6198da71237e4bb1274b3b67a0c81d56013c9535361242b6bfa87d70a9597854aadb45d4d8203369be4a655e158be2a5d20af0040b1f8d1bfc47db3ad7b68 + checksum: 10c0/95eaea7082636710c61e49e58b3907e85ec79db4327411d3784f28592509fbe94a53cc3d20a36a1cf245efc6d3f0017eae15b45ffd645c1ab949bb4e1670e6bb languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-umd@npm:7.24.7" +"@babel/plugin-transform-modules-umd@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.25.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7791d290121db210e4338b94b4a069a1a79e4c7a8d7638d8159a97b281851bbed3048dac87a4ae718ad963005e6c14a5d28e6db2eeb2b04e031cee92fb312f85 + checksum: 10c0/8849ab04eecdb73cd37e2d7289449fa5256331832b0304c220b2a6aaa12e2d2dd87684f2813412d1fc5bdb3d6b55cc08c6386d3273fe05a65177c09bee5b6769 languageName: node linkType: hard -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.24.7" +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/41a0b0f2d0886318237440aa3b489f6d0305361d8671121777d9ff89f9f6de9d0c02ce93625049061426c8994064ef64deae8b819d1b14c00374a6a2336fb5d9 + checksum: 10c0/eb55fec55dc930cd122911f3e4a421320fa8b1b4de85bfd7ef11b46c611ec69b0213c114a6e1c6bc224d6b954ff183a0caa7251267d5258ecc0f00d6d9ca1d52 languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-new-target@npm:7.24.7" +"@babel/plugin-transform-new-target@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-new-target@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2540808a35e1a978e537334c43dab439cf24c93e7beb213a2e71902f6710e60e0184316643790c0a6644e7a8021e52f7ab8165e6b3e2d6651be07bdf517b67df + checksum: 10c0/8e5dce6d027e0f3fd394578ea1af7f515de157793a15c23a5aad7034a6d8a4005ef280238e67a232bb4dd4fafd3a264fed462deb149128ddd9ce59ff6f575cff languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.7" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7243c8ff734ed5ef759dd8768773c4b443c12e792727e759a1aec2c7fa2bfdd24f1ecb42e292a7b3d8bd3d7f7b861cf256a8eb4ba144fc9cc463892c303083d9 + checksum: 10c0/3cb7c44cffccae42e104755acb31b4f00bc27d8c88102ae6f30dca508832f98fa5b746bead0fc7c0c6ddcf83f336829be4b64245c6c7ce26b3ef591937ec54a4 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" +"@babel/plugin-transform-numeric-separator@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e18e09ca5a6342645d00ede477731aa6e8714ff357efc9d7cda5934f1703b3b6fb7d3298dce3ce3ba53e9ff1158eab8f1aadc68874cc21a6099d33a1ca457789 + checksum: 10c0/d23b3ebc50513f24510791ac2cad43e3c6ea08579f54dccfd4ed5e5d5084f02da0576ea42ea999fb51e1f94f42857cac96a1a29ac6728fc262fbe87ec966dc18 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" +"@babel/plugin-transform-object-rest-spread@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.25.8" dependencies: - "@babel/helper-compilation-targets": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-transform-parameters": "npm:^7.24.7" + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/plugin-transform-parameters": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/9ad64bc003f583030f9da50614b485852f8edac93f8faf5d1cd855201a4852f37c5255ae4daf70dd4375bdd4874e16e39b91f680d4668ec219ba05441ce286eb + checksum: 10c0/058d5f5bb61068997fb78855011dd175d441da84717640852bbfd12a5919acf8d8c5a14c1debfe87d230f3f4c47c22fcad3d7fa1acd72e5e48b2fff93b6c1dd9 languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-object-super@npm:7.24.7" +"@babel/plugin-transform-object-super@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-object-super@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-replace-supers": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-replace-supers": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/770cebb4b4e1872c216b17069db9a13b87dfee747d359dc56d9fcdd66e7544f92dc6ab1861a4e7e0528196aaff2444e4f17dc84efd8eaf162d542b4ba0943869 + checksum: 10c0/7f2968d4da997101b63fd3b74445c9b16f56bd32cd8a0a16c368af9d3e983e7675c1b05d18601f32307cb06e7d884ee11d13ff18a1f6830c0db243a9a852afab languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.7" +"@babel/plugin-transform-optional-catch-binding@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/1e2f10a018f7d03b3bde6c0b70d063df8d5dd5209861d4467726cf834f5e3d354e2276079dc226aa8e6ece35f5c9b264d64b8229a8bb232829c01e561bcfb07a + checksum: 10c0/f4360e62ca4aa998db31548d0ef06836d958bcb29dee58f5c62d0c29b6b2bff1b54871195bd032825fe3dd79a4fd8275e165148c8d4b57694bcf72135c8f7d24 languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" +"@babel/plugin-transform-optional-chaining@npm:^7.25.7, @babel/plugin-transform-optional-chaining@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.25.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4ffbe1aad7dec7c9aa2bf6ceb4b2f91f96815b2784f2879bde80e46934f59d64a12cb2c6262e40897c4754d77d2c35d8a5cfed63044fdebf94978b1ed3d14b17 + checksum: 10c0/a1cdbfc249619fa6b37e57f81600701281629d86a57e616b0c2b29816d0c43114a2296ce089564afd3aa7870c8aad62e907658ffef2c110662af14ee23d5247f languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-parameters@npm:7.24.7" +"@babel/plugin-transform-parameters@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-parameters@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/53bf190d6926771545d5184f1f5f3f5144d0f04f170799ad46a43f683a01fab8d5fe4d2196cf246774530990c31fe1f2b9f0def39f0a5ddbb2340b924f5edf01 + checksum: 10c0/b40ba70278842ce1e800d7ab400df730994941550da547ef453780023bd61a9b8acf4b9fb8419c1b5bcbe09819a1146ff59369db11db07eb71870bef86a12422 languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-private-methods@npm:7.25.4" +"@babel/plugin-transform-private-methods@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-private-methods@npm:7.25.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.25.4" - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7abdb427c3984a2c8a2e9d806297d8509b02f78a3501b7760e544be532446e9df328b876daa8fc38718f3dce7ccc45083016ee7aeaab169b81c142bc18700794 + checksum: 10c0/92e076f63f7c4696e1321dafdd56c4212eb41784cdadba0ebc39091f959a76d357c3df61a6c668be81d6b6ad8964ee458e85752ab0c6cfbbaf2066903edda732 languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.7" +"@babel/plugin-transform-private-property-in-object@npm:^7.25.8": + version: 7.25.8 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.25.8" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-create-class-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c6fa7defb90b1b0ed46f24ff94ff2e77f44c1f478d1090e81712f33cf992dda5ba347016f030082a2f770138bac6f4a9c2c1565e9f767a125901c77dd9c239ba + checksum: 10c0/61b5e3a4eb94caf38d6e9ff7bff1ac8927758141aaa4891036d3490866ecee53beaefd7893519fec42a4c55f33374a17fc0e49694cdaf95668082073f0fe4a79 languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-property-literals@npm:7.24.7" +"@babel/plugin-transform-property-literals@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/52564b58f3d111dc02d241d5892a4b01512e98dfdf6ef11b0ed62f8b11b0acacccef0fc229b44114fe8d1a57a8b70780b11bdd18b807d3754a781a07d8f57433 + checksum: 10c0/6d5bccdc772207906666ad5201bd91e4e132e1d806dbcf4163a1d08e18c57cc3795578c4e10596514bcd6afaf9696f478ea4f0dea890176d93b9cb077b9e5c55 languageName: node linkType: hard @@ -1116,313 +1060,299 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-display-name@npm:7.24.7" +"@babel/plugin-transform-react-display-name@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-react-display-name@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c14a07a9e75723c96f1a0a306b8a8e899ff1c6a0cc3d62bcda79bb1b54e4319127b258651c513a1a47da152cdc22e16525525a30ae5933a2980c7036fd0b4d24 + checksum: 10c0/a0c537cc7c328ed7468d3b6a37bf0d9cb15d94afcdf3f2849ce6e5a68494fc61f0fa4fc529482a6b95b00f3c5c734f310bf18085293bff40702789f06c816f36 languageName: node linkType: hard "@babel/plugin-transform-react-inline-elements@npm:^7.21.0": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-inline-elements@npm:7.24.7" + version: 7.25.7 + resolution: "@babel/plugin-transform-react-inline-elements@npm:7.25.7" dependencies: - "@babel/helper-builder-react-jsx": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-builder-react-jsx": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/affe44efc641e5dc4de077db74c80e3dee896a5dfea04491cbd8167ac40dcbb6eaa1ad0ba599e4a85071acdaa08732e7f5d9cf3236a2aa635406c232c8f08236 + checksum: 10c0/de85180c09002083cb330ef28d5b31b44e6ac6565c700b603be76e629f5a92c59ff69f79c08cc1dbd2dd1f271f44fe8d4c751deaf66c059ba721aa3cb43c881e languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-development@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.24.7" +"@babel/plugin-transform-react-jsx-development@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.25.7" dependencies: - "@babel/plugin-transform-react-jsx": "npm:^7.24.7" + "@babel/plugin-transform-react-jsx": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/fce647db50f90a5291681f0f97865d9dc76981262dff71d6d0332e724b85343de5860c26f9e9a79e448d61e1d70916b07ce91e8c7f2b80dceb4b16aee41794d8 + checksum: 10c0/a3dc14644d09a6d22875af7b5584393ab53e467e0531cd192fc6242504dacaffa421e89265ba7f84fd4edef2b7b100d2e2ebf092a4dce2b55cf9c5fe29390c18 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx@npm:7.24.7" +"@babel/plugin-transform-react-jsx@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-react-jsx@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-module-imports": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-jsx": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-module-imports": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/plugin-syntax-jsx": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5c46d2c1c06a30e6bde084839df9cc689bf9c9cb0292105d61c225ca731f64247990724caee7dfc7f817dc964c062e8319e7f05394209590c476b65d75373435 + checksum: 10c0/6766b0357b8bbfcb77fca5350f06cf822c89bbe75ddcaea24614601ef23957504da24e76597d743038ce8fa081373b0663c8ad0c86d7c7226e8185f0680b8b56 languageName: node linkType: hard -"@babel/plugin-transform-react-pure-annotations@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.24.7" +"@babel/plugin-transform-react-pure-annotations@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/fae517d293d9c93b7b920458c3e4b91cb0400513889af41ba184a5f3acc8bfef27242cc262741bb8f87870df376f1733a0d0f52b966d342e2aaaf5607af8f73d + checksum: 10c0/d92c9b511850fb6dea71966a0d4f313d67e317db7fc3633a7ff2e27d6df2e95cbc91c4c25abdb6c8db651fcda842a0cb7433835a8a9d4a3fdc5d452068428101 languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" +"@babel/plugin-transform-regenerator@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" regenerator-transform: "npm:^0.15.2" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d2dc2c788fdae9d97217e70d46ba8ca9db0035c398dc3e161552b0c437113719a75c04f201f9c91ddc8d28a1da60d0b0853f616dead98a396abb9c845c44892b + checksum: 10c0/7ee3a57c4050bc908ef7ac392d810826b294970a7182f4ec34a8ca93dbe36deb21bc862616d46a6f3d881d6b5749930e1679e875b638a00866d844a4250df212 languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-reserved-words@npm:7.24.7" +"@babel/plugin-transform-reserved-words@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2229de2768615e7f5dc0bbc55bc121b5678fd6d2febd46c74a58e42bb894d74cd5955c805880f4e02d0e1cf94f6886270eda7fafc1be9305a1ec3b9fd1d063f5 + checksum: 10c0/920c98130daff6c1288fb13a9a2d2e45863bba93e619cb88d90e1f5b5cb358a3ee8880a425a3adb1b4bd5dbb6bd0500eea3370fc612633045eec851b08cc586c languageName: node linkType: hard "@babel/plugin-transform-runtime@npm:^7.22.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-runtime@npm:7.25.4" + version: 7.25.7 + resolution: "@babel/plugin-transform-runtime@npm:7.25.7" dependencies: - "@babel/helper-module-imports": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-module-imports": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" babel-plugin-polyfill-corejs2: "npm:^0.4.10" babel-plugin-polyfill-corejs3: "npm:^0.10.6" babel-plugin-polyfill-regenerator: "npm:^0.6.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c08698276596d58bf49e222ead3c414c35d099a7e5a6174b11e2db9b74420e94783ada596820437622c3eccc8852c0e750ad053bd8e775f0050839479ba76e6a + checksum: 10c0/9b2514e9079361ac8e7e500ffd522dad869d61a3894302da7e29bbac80de00276c8a1b4394d1dcf0b51c57b2c854919928df9648be336139fdf1d6ecd6d1bb32 languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.7" +"@babel/plugin-transform-shorthand-properties@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/41b155bdbb3be66618358488bf7731b3b2e8fff2de3dbfd541847720a9debfcec14db06a117abedd03c9cd786db20a79e2a86509a4f19513f6e1b610520905cf + checksum: 10c0/4250f89a0072f0f400be7a2e3515227b8e2518737899bd57d497e5173284a0e05d812e4a3c219ffcd484e9fa9a01c19fce5acd77bbb898f4d594512c56701eb4 languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-spread@npm:7.24.7" +"@babel/plugin-transform-spread@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-spread@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/facba1553035f76b0d2930d4ada89a8cd0f45b79579afd35baefbfaf12e3b86096995f4b0c402cf9ee23b3f2ea0a4460c3b1ec0c192d340962c948bb223d4e66 + checksum: 10c0/258bd1b52388cd7425d0ae25fa39538734f7540ea503a1d8a72211d33f6f214cb4e3b73d6cd03016cbcff5d41169f1e578b9ea331965ad224d223591983e90a7 languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.7" +"@babel/plugin-transform-sticky-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5a74ed2ed0a3ab51c3d15fcaf09d9e2fe915823535c7a4d7b019813177d559b69677090e189ec3d5d08b619483eb5ad371fbcfbbff5ace2a76ba33ee566a1109 + checksum: 10c0/0e466cfc3ca1e0db4bb11eb630215b0e1f43066d7678325e5ddadcf5a118b2351a528f67205729c32ac5b78ab68ab7f40517dd33bcb1fb6b456509f5f54ce097 languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-template-literals@npm:7.24.7" +"@babel/plugin-transform-template-literals@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/3630f966257bcace122f04d3157416a09d40768c44c3a800855da81146b009187daa21859d1c3b7d13f4e19e8888e60613964b175b2275d451200fb6d8d6cfe6 + checksum: 10c0/a3455303b6841cb536ac66d1a2d03c194b9f371519482d8d1e8edbd33bf5ca7cdd5db1586b2b0ea5f909ebf74a0eafacf0fb28d257e4905445282dcdccfa6139 languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" +"@babel/plugin-transform-typeof-symbol@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2f570a4fbbdc5fd85f48165a97452826560051e3b8efb48c3bb0a0a33ee8485633439e7b71bfe3ef705583a1df43f854f49125bd759abdedc195b2cf7e60012a + checksum: 10c0/ce1a0744a900b05de1372a70508c4148f17eb941c482da26eb369b9f0347570dce45470c8a86d907bc3a0443190344da1e18489ecfecb30388ab6178e8a9916b languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-typescript@npm:7.24.7" +"@babel/plugin-transform-typescript@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-typescript@npm:7.25.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-create-class-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/plugin-syntax-typescript": "npm:^7.24.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-create-class-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/plugin-syntax-typescript": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e8dacdc153a4c4599014b66eb01b94e3dc933d58d4f0cc3039c1a8f432e77b9df14f34a61964e014b975bf466f3fefd8c4768b3e887d3da1be9dc942799bdfdf + checksum: 10c0/5fa839b9560221698edff5e00b5cccc658c7875efaa7971c66d478f5b026770f12dd47b1be024463a44f9e29b4e14e8ddddbf4a2b324b0b94f58370dd5ae7195 languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" +"@babel/plugin-transform-unicode-escapes@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8b18e2e66af33471a6971289492beff5c240e56727331db1d34c4338a6a368a82a7ed6d57ec911001b6d65643aed76531e1e7cac93265fb3fb2717f54d845e69 + checksum: 10c0/8b1f71fda0a832c6e26ba4c00f99e9033e6f9b36ced542a512921f4ad861a70e2fec2bd54a91a5ca2efa46aaa8c8893e4c602635c4ef172bd3ed6eef3178c70b languageName: node linkType: hard -"@babel/plugin-transform-unicode-property-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-property-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/bc57656eb94584d1b74a385d378818ac2b3fca642e3f649fead8da5fb3f9de22f8461185936915dfb33d5a9104e62e7a47828331248b09d28bb2d59e9276de3e + checksum: 10c0/b4bfcf7529138d00671bf5cdfe606603d52cfe57ec1be837da57683f404fc0b0c171834a02515eb03379e5c806121866d097b90e31cb437d21d0ea59368ad82b languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/83f72a345b751566b601dc4d07e9f2c8f1bc0e0c6f7abb56ceb3095b3c9d304de73f85f2f477a09f8cc7edd5e65afd0ff9e376cdbcbea33bc0c28f3705b38fd9 + checksum: 10c0/73ae34c02ea8b7ac7e4efa690f8c226089c074e3fef658d2a630ad898a93550d84146ce05e073c271c8b2bbba61cbbfd5a2002a7ea940dcad3274e5b5dcb6bcf languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.4" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.2" - "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/f65749835a98d8d6242e961f9276bdcdb09020e791d151ccc145acaca9a66f025b2c7cb761104f139180d35eb066a429596ee6edece81f5fd9244e0edb97d7ec + checksum: 10c0/39e45ae3db7adfc3457b1d6ba5608ffbace957ad019785967e5357a6639f261765bda12363f655d39265f5a2834af26327037751420191d0b73152ccc7ce3c35 languageName: node linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.25.4 - resolution: "@babel/preset-env@npm:7.25.4" - dependencies: - "@babel/compat-data": "npm:^7.25.4" - "@babel/helper-compilation-targets": "npm:^7.25.2" - "@babel/helper-plugin-utils": "npm:^7.24.8" - "@babel/helper-validator-option": "npm:^7.24.8" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.25.3" - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.25.0" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.25.0" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.7" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.25.0" + version: 7.25.8 + resolution: "@babel/preset-env@npm:7.25.8" + dependencies: + "@babel/compat-data": "npm:^7.25.8" + "@babel/helper-compilation-targets": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-validator-option": "npm:^7.25.7" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.25.7" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.25.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.25.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.25.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.25.7" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/plugin-syntax-class-properties": "npm:^7.12.13" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" - "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" - "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" - "@babel/plugin-syntax-import-assertions": "npm:^7.24.7" - "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" - "@babel/plugin-syntax-import-meta": "npm:^7.10.4" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" - "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" + "@babel/plugin-syntax-import-assertions": "npm:^7.25.7" + "@babel/plugin-syntax-import-attributes": "npm:^7.25.7" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" - "@babel/plugin-transform-arrow-functions": "npm:^7.24.7" - "@babel/plugin-transform-async-generator-functions": "npm:^7.25.4" - "@babel/plugin-transform-async-to-generator": "npm:^7.24.7" - "@babel/plugin-transform-block-scoped-functions": "npm:^7.24.7" - "@babel/plugin-transform-block-scoping": "npm:^7.25.0" - "@babel/plugin-transform-class-properties": "npm:^7.25.4" - "@babel/plugin-transform-class-static-block": "npm:^7.24.7" - "@babel/plugin-transform-classes": "npm:^7.25.4" - "@babel/plugin-transform-computed-properties": "npm:^7.24.7" - "@babel/plugin-transform-destructuring": "npm:^7.24.8" - "@babel/plugin-transform-dotall-regex": "npm:^7.24.7" - "@babel/plugin-transform-duplicate-keys": "npm:^7.24.7" - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.25.0" - "@babel/plugin-transform-dynamic-import": "npm:^7.24.7" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.24.7" - "@babel/plugin-transform-export-namespace-from": "npm:^7.24.7" - "@babel/plugin-transform-for-of": "npm:^7.24.7" - "@babel/plugin-transform-function-name": "npm:^7.25.1" - "@babel/plugin-transform-json-strings": "npm:^7.24.7" - "@babel/plugin-transform-literals": "npm:^7.25.2" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7" - "@babel/plugin-transform-member-expression-literals": "npm:^7.24.7" - "@babel/plugin-transform-modules-amd": "npm:^7.24.7" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" - "@babel/plugin-transform-modules-systemjs": "npm:^7.25.0" - "@babel/plugin-transform-modules-umd": "npm:^7.24.7" - "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7" - "@babel/plugin-transform-new-target": "npm:^7.24.7" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.7" - "@babel/plugin-transform-numeric-separator": "npm:^7.24.7" - "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7" - "@babel/plugin-transform-object-super": "npm:^7.24.7" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.8" - "@babel/plugin-transform-parameters": "npm:^7.24.7" - "@babel/plugin-transform-private-methods": "npm:^7.25.4" - "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7" - "@babel/plugin-transform-property-literals": "npm:^7.24.7" - "@babel/plugin-transform-regenerator": "npm:^7.24.7" - "@babel/plugin-transform-reserved-words": "npm:^7.24.7" - "@babel/plugin-transform-shorthand-properties": "npm:^7.24.7" - "@babel/plugin-transform-spread": "npm:^7.24.7" - "@babel/plugin-transform-sticky-regex": "npm:^7.24.7" - "@babel/plugin-transform-template-literals": "npm:^7.24.7" - "@babel/plugin-transform-typeof-symbol": "npm:^7.24.8" - "@babel/plugin-transform-unicode-escapes": "npm:^7.24.7" - "@babel/plugin-transform-unicode-property-regex": "npm:^7.24.7" - "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" - "@babel/plugin-transform-unicode-sets-regex": "npm:^7.25.4" + "@babel/plugin-transform-arrow-functions": "npm:^7.25.7" + "@babel/plugin-transform-async-generator-functions": "npm:^7.25.8" + "@babel/plugin-transform-async-to-generator": "npm:^7.25.7" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.25.7" + "@babel/plugin-transform-block-scoping": "npm:^7.25.7" + "@babel/plugin-transform-class-properties": "npm:^7.25.7" + "@babel/plugin-transform-class-static-block": "npm:^7.25.8" + "@babel/plugin-transform-classes": "npm:^7.25.7" + "@babel/plugin-transform-computed-properties": "npm:^7.25.7" + "@babel/plugin-transform-destructuring": "npm:^7.25.7" + "@babel/plugin-transform-dotall-regex": "npm:^7.25.7" + "@babel/plugin-transform-duplicate-keys": "npm:^7.25.7" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.25.7" + "@babel/plugin-transform-dynamic-import": "npm:^7.25.8" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.25.7" + "@babel/plugin-transform-export-namespace-from": "npm:^7.25.8" + "@babel/plugin-transform-for-of": "npm:^7.25.7" + "@babel/plugin-transform-function-name": "npm:^7.25.7" + "@babel/plugin-transform-json-strings": "npm:^7.25.8" + "@babel/plugin-transform-literals": "npm:^7.25.7" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.25.8" + "@babel/plugin-transform-member-expression-literals": "npm:^7.25.7" + "@babel/plugin-transform-modules-amd": "npm:^7.25.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.25.7" + "@babel/plugin-transform-modules-systemjs": "npm:^7.25.7" + "@babel/plugin-transform-modules-umd": "npm:^7.25.7" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.25.7" + "@babel/plugin-transform-new-target": "npm:^7.25.7" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.25.8" + "@babel/plugin-transform-numeric-separator": "npm:^7.25.8" + "@babel/plugin-transform-object-rest-spread": "npm:^7.25.8" + "@babel/plugin-transform-object-super": "npm:^7.25.7" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.25.8" + "@babel/plugin-transform-optional-chaining": "npm:^7.25.8" + "@babel/plugin-transform-parameters": "npm:^7.25.7" + "@babel/plugin-transform-private-methods": "npm:^7.25.7" + "@babel/plugin-transform-private-property-in-object": "npm:^7.25.8" + "@babel/plugin-transform-property-literals": "npm:^7.25.7" + "@babel/plugin-transform-regenerator": "npm:^7.25.7" + "@babel/plugin-transform-reserved-words": "npm:^7.25.7" + "@babel/plugin-transform-shorthand-properties": "npm:^7.25.7" + "@babel/plugin-transform-spread": "npm:^7.25.7" + "@babel/plugin-transform-sticky-regex": "npm:^7.25.7" + "@babel/plugin-transform-template-literals": "npm:^7.25.7" + "@babel/plugin-transform-typeof-symbol": "npm:^7.25.7" + "@babel/plugin-transform-unicode-escapes": "npm:^7.25.7" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.25.7" + "@babel/plugin-transform-unicode-regex": "npm:^7.25.7" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.25.7" "@babel/preset-modules": "npm:0.1.6-no-external-plugins" babel-plugin-polyfill-corejs2: "npm:^0.4.10" babel-plugin-polyfill-corejs3: "npm:^0.10.6" babel-plugin-polyfill-regenerator: "npm:^0.6.1" - core-js-compat: "npm:^3.37.1" + core-js-compat: "npm:^3.38.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ed210a1974b5a1e7f80a933c87253907ec869457cea900bc97892642fa9a690c47627a9bac08a7c9495deb992a2b15f308ffca2741e1876ba47172c96fa27e14 + checksum: 10c0/a45cd64ca082262998f6cf508b413ff8a9e967bf33e58337a1fe41c6c939a4c25cc73cd58387792c00d43905cf5fb0ea5ef88dfdc2addf2e8133743088c86c72 languageName: node linkType: hard @@ -1440,40 +1370,33 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.22.3": - version: 7.24.7 - resolution: "@babel/preset-react@npm:7.24.7" + version: 7.25.7 + resolution: "@babel/preset-react@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" - "@babel/plugin-transform-react-display-name": "npm:^7.24.7" - "@babel/plugin-transform-react-jsx": "npm:^7.24.7" - "@babel/plugin-transform-react-jsx-development": "npm:^7.24.7" - "@babel/plugin-transform-react-pure-annotations": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-validator-option": "npm:^7.25.7" + "@babel/plugin-transform-react-display-name": "npm:^7.25.7" + "@babel/plugin-transform-react-jsx": "npm:^7.25.7" + "@babel/plugin-transform-react-jsx-development": "npm:^7.25.7" + "@babel/plugin-transform-react-pure-annotations": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/9658b685b25cedaadd0b65c4e663fbc7f57394b5036ddb4c99b1a75b0711fb83292c1c625d605c05b73413fc7a6dc20e532627f6a39b6dc8d4e00415479b054c + checksum: 10c0/b133b1a2f46c70a337d8b1ef442e09e3dbdaecb0d6bed8f1cb64dfddc31c16e248b017385ab909caeebd8462111c9c0e1c5409deb10f2be5cb5bcfdaa4d27718 languageName: node linkType: hard "@babel/preset-typescript@npm:^7.21.5": - version: 7.24.7 - resolution: "@babel/preset-typescript@npm:7.24.7" + version: 7.25.7 + resolution: "@babel/preset-typescript@npm:7.25.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" - "@babel/plugin-syntax-jsx": "npm:^7.24.7" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.7" - "@babel/plugin-transform-typescript": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-validator-option": "npm:^7.25.7" + "@babel/plugin-syntax-jsx": "npm:^7.25.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.25.7" + "@babel/plugin-transform-typescript": "npm:^7.25.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/986bc0978eedb4da33aba8e1e13a3426dd1829515313b7e8f4ba5d8c18aff1663b468939d471814e7acf4045d326ae6cff37239878d169ac3fe53a8fde71f8ee - languageName: node - linkType: hard - -"@babel/regjsgen@npm:^0.8.0": - version: 0.8.0 - resolution: "@babel/regjsgen@npm:0.8.0" - checksum: 10c0/4f3ddd8c7c96d447e05c8304c1d5ba3a83fcabd8a716bc1091c2f31595cdd43a3a055fff7cb5d3042b8cb7d402d78820fcb4e05d896c605a7d8bcf30f2424c4a + checksum: 10c0/8dc1258e3c5230bbe42ff9811f08924509238e6bd32fa0b7b0c0a6c5e1419512a8e1f733e1b114454d367b7c164beca2cf33acf2ed9e0d99be010c1c5cdbef0c languageName: node linkType: hard @@ -1487,48 +1410,48 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.25.6 - resolution: "@babel/runtime@npm:7.25.6" + version: 7.25.7 + resolution: "@babel/runtime@npm:7.25.7" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/d6143adf5aa1ce79ed374e33fdfd74fa975055a80bc6e479672ab1eadc4e4bfd7484444e17dd063a1d180e051f3ec62b357c7a2b817e7657687b47313158c3d2 + checksum: 10c0/86b7829d2fc9343714a9afe92757cf96c4dc799006ca61d73cda62f4b9e29bfa1ce36794955bc6cb4c188f5b10db832c949339895e1bbe81a69022d9d578ce29 languageName: node linkType: hard -"@babel/template@npm:^7.24.7, @babel/template@npm:^7.25.0, @babel/template@npm:^7.3.3": - version: 7.25.0 - resolution: "@babel/template@npm:7.25.0" +"@babel/template@npm:^7.25.7, @babel/template@npm:^7.3.3": + version: 7.25.7 + resolution: "@babel/template@npm:7.25.7" dependencies: - "@babel/code-frame": "npm:^7.24.7" - "@babel/parser": "npm:^7.25.0" - "@babel/types": "npm:^7.25.0" - checksum: 10c0/4e31afd873215744c016e02b04f43b9fa23205d6d0766fb2e93eb4091c60c1b88897936adb895fb04e3c23de98dfdcbe31bc98daaa1a4e0133f78bb948e1209b + "@babel/code-frame": "npm:^7.25.7" + "@babel/parser": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" + checksum: 10c0/8ae9e36e4330ee83d4832531d1d9bec7dc2ef6a2a8afa1ef1229506fd60667abcb17f306d1c3d7e582251270597022990c845d5d69e7add70a5aea66720decb9 languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.1, @babel/traverse@npm:^7.25.2, @babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.25.4": - version: 7.25.4 - resolution: "@babel/traverse@npm:7.25.4" +"@babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.7": + version: 7.25.7 + resolution: "@babel/traverse@npm:7.25.7" dependencies: - "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.25.4" - "@babel/parser": "npm:^7.25.4" - "@babel/template": "npm:^7.25.0" - "@babel/types": "npm:^7.25.4" + "@babel/code-frame": "npm:^7.25.7" + "@babel/generator": "npm:^7.25.7" + "@babel/parser": "npm:^7.25.7" + "@babel/template": "npm:^7.25.7" + "@babel/types": "npm:^7.25.7" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/37c9b49b277e051fe499ef5f6f217370c4f648d6370564d70b5e6beb2da75bfda6d7dab1d39504d89e9245448f8959bc1a5880d2238840cdc3979b35338ed0f5 + checksum: 10c0/75d73e52c507a7a7a4c7971d6bf4f8f26fdd094e0d3a0193d77edf6a5efa36fc3db91ec5cc48e8b94e6eb5d5ad21af0a1040e71309172851209415fd105efb1a languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.4, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.25.4 - resolution: "@babel/types@npm:7.25.4" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.7, @babel/types@npm:^7.25.8, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.25.8 + resolution: "@babel/types@npm:7.25.8" dependencies: - "@babel/helper-string-parser": "npm:^7.24.8" - "@babel/helper-validator-identifier": "npm:^7.24.7" + "@babel/helper-string-parser": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.7" to-fast-properties: "npm:^2.0.0" - checksum: 10c0/9aa25dfcd89cc4e4dde3188091c34398a005a49e2c2b069d0367b41e1122c91e80fd92998c52a90f2fb500f7e897b6090ec8be263d9cb53d0d75c756f44419f2 + checksum: 10c0/55ca2d6df6426c98db2769ce884ce5e9de83a512ea2dd7bcf56c811984dc14351cacf42932a723630c5afcff2455809323decd645820762182f10b7b5252b59f languageName: node linkType: hard @@ -1539,13 +1462,13 @@ __metadata: languageName: node linkType: hard -"@csstools/cascade-layer-name-parser@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/cascade-layer-name-parser@npm:2.0.1" +"@csstools/cascade-layer-name-parser@npm:^2.0.2": + version: 2.0.2 + resolution: "@csstools/cascade-layer-name-parser@npm:2.0.2" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.1 - "@csstools/css-tokenizer": ^3.0.1 - checksum: 10c0/e1f9030285d1a16ca0424018289e5288e58dee2d6f6cc392e27d9e8eca0deeea4ced9b749eef09a8322746cb15b6304bc7e2d04bb9dc7405c29b3717ec80e736 + "@csstools/css-parser-algorithms": ^3.0.2 + "@csstools/css-tokenizer": ^3.0.2 + checksum: 10c0/2cc840445328400bb3e1e4186e6081e6519a23d9abde36a16c95892b6ad75155b3af3410d79fdda1c53a068384f970cabff4b5f5ba6867578168cbd3419016c8 languageName: node linkType: hard @@ -1556,42 +1479,42 @@ __metadata: languageName: node linkType: hard -"@csstools/css-calc@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/css-calc@npm:2.0.1" +"@csstools/css-calc@npm:^2.0.2": + version: 2.0.2 + resolution: "@csstools/css-calc@npm:2.0.2" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.1 - "@csstools/css-tokenizer": ^3.0.1 - checksum: 10c0/84c0ba3dac51466c9ac22c3540360f6058cf351a3676d71d4412584b165a91abc7c69a4ddf5a5dacc6e6082806d2317cf50ddbc0a0562275b2aedaee41cb87a9 + "@csstools/css-parser-algorithms": ^3.0.2 + "@csstools/css-tokenizer": ^3.0.2 + checksum: 10c0/b36e655b4abc8ea39b300725e33cd43b1875d759dd60bee8155bf7841065615a7f24cf53199382e30aa10bb137f64021043e4af7e11b7199b674a6e6cf3ccd01 languageName: node linkType: hard -"@csstools/css-color-parser@npm:^3.0.2": - version: 3.0.2 - resolution: "@csstools/css-color-parser@npm:3.0.2" +"@csstools/css-color-parser@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/css-color-parser@npm:3.0.3" dependencies: "@csstools/color-helpers": "npm:^5.0.1" - "@csstools/css-calc": "npm:^2.0.1" + "@csstools/css-calc": "npm:^2.0.2" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.1 - "@csstools/css-tokenizer": ^3.0.1 - checksum: 10c0/31f42cc22426c937f5c6999889f72b40aec8504189a6badf3319552f27a5af73dd5f46be9ebc54eb87e526468eb2546ffbd60a6879fe599efa6c98e51d6cfa3d + "@csstools/css-parser-algorithms": ^3.0.2 + "@csstools/css-tokenizer": ^3.0.2 + checksum: 10c0/02367ffc222254132c47f9cbc856f65fe0b81ee4a5e7381251b95c4064138b5ed99a5e5a79c0c8689f9e75e3d900f94773258a161a97f467c3f0420838c10e04 languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^3.0.1": - version: 3.0.1 - resolution: "@csstools/css-parser-algorithms@npm:3.0.1" +"@csstools/css-parser-algorithms@npm:^3.0.1, @csstools/css-parser-algorithms@npm:^3.0.2": + version: 3.0.2 + resolution: "@csstools/css-parser-algorithms@npm:3.0.2" peerDependencies: - "@csstools/css-tokenizer": ^3.0.1 - checksum: 10c0/064c6d519197b5af43bbf5efe8f4cdbd361b006113aa82160d637e925b50c643a52d33d512ca01c63042d952d723a2a10798231a714668356b76668fb11294e3 + "@csstools/css-tokenizer": ^3.0.2 + checksum: 10c0/246afbf518ee9eaa24ed7f083360eb66884f1172fd4f8c663bff8c6099de2a8abd1e2a31d5b6fe42e010277d238469d780cff62bc7fdc6a52e7a90626b8924dc languageName: node linkType: hard -"@csstools/css-tokenizer@npm:^3.0.1": - version: 3.0.1 - resolution: "@csstools/css-tokenizer@npm:3.0.1" - checksum: 10c0/c9ed4373e5731b5375ea9791590081019c04e95f08b46b272977e5e7b8c3d560affc62e82263cb8def1df1e57f0673140e7e16a14a5e7be04e6a234be088d1d3 +"@csstools/css-tokenizer@npm:^3.0.1, @csstools/css-tokenizer@npm:^3.0.2": + version: 3.0.2 + resolution: "@csstools/css-tokenizer@npm:3.0.2" + checksum: 10c0/a74e5829420ed35982fd33be272c2a19cb2380179d357abe750aa848be6d6699d0437008f47a57eb7c6ff64a34b0c8f91a97dd63dbddd08249b7cf7983767e5e languageName: node linkType: hard @@ -1605,6 +1528,16 @@ __metadata: languageName: node linkType: hard +"@csstools/media-query-list-parser@npm:^4.0.0": + version: 4.0.0 + resolution: "@csstools/media-query-list-parser@npm:4.0.0" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.2 + "@csstools/css-tokenizer": ^3.0.2 + checksum: 10c0/416417bcfd84c18a2df8dc77f31c87830e151dc20530fe7f0d8f13a0848b1a9090858abdf7792d82bf2edb41ddedb7b57b34eb78b68b5c10755ae02c019e496a + languageName: node + linkType: hard + "@csstools/postcss-cascade-layers@npm:^5.0.0": version: 5.0.0 resolution: "@csstools/postcss-cascade-layers@npm:5.0.0" @@ -1617,60 +1550,60 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-color-function@npm:4.0.2" +"@csstools/postcss-color-function@npm:^4.0.3": + version: 4.0.3 + resolution: "@csstools/postcss-color-function@npm:4.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/c987ccc7ab326668895396d3fe69c05087cf6e245be6f70e8c33da0cdeb56f8ac3d117cfad984191ec57be9691ab56d427aaa28c61c4a7446521972993dd5039 + checksum: 10c0/c994660ca0e2652755d9ad181c8cb46a07220c972086c97c843fa9bacf690be10c642770f898aeec4acc47c2b718dfc7372107285a678361f34d84d9e9c11e0c languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^3.0.2": - version: 3.0.2 - resolution: "@csstools/postcss-color-mix-function@npm:3.0.2" +"@csstools/postcss-color-mix-function@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/postcss-color-mix-function@npm:3.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/cfdc641f504f9d02b9a7b53d6bd933d4e767ecaee5f3d2df45d897f69b8a38b5b79b538d307b16fb56dcb7c19dc7e107518c356772e89771e28e04fd846d9035 + checksum: 10c0/4ba358eb9030fc485bfe2922d897eeb712725762cc399eaba60ba665c84dc3e56a4d5a52dfb320093c0b217d32fedb9b5197fa45738cade53d9afcbefdadf04f languageName: node linkType: hard -"@csstools/postcss-content-alt-text@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/postcss-content-alt-text@npm:2.0.1" +"@csstools/postcss-content-alt-text@npm:^2.0.2": + version: 2.0.2 + resolution: "@csstools/postcss-content-alt-text@npm:2.0.2" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/693e4cfa9a30a9c384120bd24846a7cd5ba1e1ebf975eb81b0e0131a21ac28a0301c7dcfa13706bc7d8b5343536fb43a46de636c3257d0fd05041c7255366e87 + checksum: 10c0/e52d40f6567b9b23b32a6c40f9b2a74d57f99a9921b4cae015f51f72453474236c760bb13120682f8815698a615e0ad7bed22314c29dca89c34b5480d83a7a6d languageName: node linkType: hard -"@csstools/postcss-exponential-functions@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/postcss-exponential-functions@npm:2.0.1" +"@csstools/postcss-exponential-functions@npm:^2.0.2": + version: 2.0.2 + resolution: "@csstools/postcss-exponential-functions@npm:2.0.2" dependencies: - "@csstools/css-calc": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-calc": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/ddcaedfa48cc0cf93611c8d2ed5a75d56c1d196a97015db644b45881adabb47f3255242acaef6ea869a1e5ba66328725d254bf6d29eb5e988cde8b040bc5f55d + checksum: 10c0/034ff89089872f63a6b00bda670c5ff11361babd221ed3e441dde969a718059e5d44ab0ed331868f137bb205331b808ecbcc4cb641d5c945238ebca28aa3ed59 languageName: node linkType: hard @@ -1686,46 +1619,46 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/postcss-gamut-mapping@npm:2.0.2" +"@csstools/postcss-gamut-mapping@npm:^2.0.3": + version: 2.0.3 + resolution: "@csstools/postcss-gamut-mapping@npm:2.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/8b6504f81c5036e3c2a9f9516c371f48a283112469b746546c8c7f6f0da2467c915d4dac6dfe8bb05d7dab3a7503911391eb9e666cb7632e09a032e801c029f5 + checksum: 10c0/21f5708f63e9c3b7603f8b72b5f288e0a021e9710a6abf4aaa713ff4d04bae057d1861e1f28d7670ea39ba463ac04f1507876d4a11178934e7cc7a1c6a780084 languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^5.0.2": - version: 5.0.2 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.2" +"@csstools/postcss-gradients-interpolation-method@npm:^5.0.3": + version: 5.0.3 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/4fa27437ad9861b1457c28228f2503c17bcc2f77dcb38da1314a4a5d38fd010e7e5d11b5f9d69e0a2cb2999bbfeca1e99ce2f59422bda5b382658dcb03f7326e + checksum: 10c0/062d27148438309c940a1973bfc7d42a06caa9397bf2382c7a61979f5be3d6f3fae1bc8ddf94d2dd8e6c807e0530a9e76179510266aaddc439677bf79447a765 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-hwb-function@npm:4.0.2" +"@csstools/postcss-hwb-function@npm:^4.0.3": + version: 4.0.3 + resolution: "@csstools/postcss-hwb-function@npm:4.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/46dc9596e37830de4c38f70764d6da9f2fc7bc339217b4291eced75daa8998c4e05fb743c271701e44818df4ac111c285019b7bb3a728e8b61d86899bbeb74eb + checksum: 10c0/faf2bfbafeec765391e37c7a5cbc7b4647d9ab1ffa51e922c7dfffa545c3d436d15604dfdfb9d7684e760042e62bb42e0243dd4ebd8c3c14694a9f7be4e57b30 languageName: node linkType: hard @@ -1763,17 +1696,17 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/postcss-light-dark-function@npm:2.0.2" +"@csstools/postcss-light-dark-function@npm:^2.0.5": + version: 2.0.5 + resolution: "@csstools/postcss-light-dark-function@npm:2.0.5" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/f8973c435868998e5d6af1fc0c35b27bbf65fa9d0c35f5055c689b8ee2807a16802044e296f7def39a7253ae544fb49559e8273ee22eb4e21845aa980a1bc82b + checksum: 10c0/80635ee312d2a8f42aa5ce6792f1dc4a71199c384c66a3270d37e998d96db55beaa6836d689cda3b7e4828227960582fae04659ba5e4e0f64fd4543cbf15c6ab languageName: node linkType: hard @@ -1815,42 +1748,42 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-logical-viewport-units@npm:^3.0.1": - version: 3.0.1 - resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.1" +"@csstools/postcss-logical-viewport-units@npm:^3.0.2": + version: 3.0.2 + resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.2" dependencies: - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/f54f91ec4d308562371576e82131c3cc1ff461a951c9a38f0b42b783c26f37a93cc846fcd025d3c4a8437b55a4fff1192ebfac8ccf84abb6478b2c515d232552 + checksum: 10c0/31f525e774bc053f545a159eb53bb21465ea2930118e87c40207ad90fa97d3151e6de83efd02f84803fb0e93ed4a4b42a3904b734423410e73ac4c6ce9666ab4 languageName: node linkType: hard -"@csstools/postcss-media-minmax@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/postcss-media-minmax@npm:2.0.1" +"@csstools/postcss-media-minmax@npm:^2.0.2": + version: 2.0.2 + resolution: "@csstools/postcss-media-minmax@npm:2.0.2" dependencies: - "@csstools/css-calc": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" - "@csstools/media-query-list-parser": "npm:^3.0.1" + "@csstools/css-calc": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/media-query-list-parser": "npm:^4.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/23c1fb0c3ed8bf82f3223f161d0d65ba62045b917bc19624581f64aaa5d678485d22c23af2591a3f634ba02030ccb419c2b30209aa22f9fd2baa1a6474af810a + checksum: 10c0/83cf10742884fca3baa7ae26e2cb34123ce5a022622390566c139b4587ea8583fab00acbb85545786b36398e2201d2a94301e0fae805e55f375f1b5c38f67ce8 languageName: node linkType: hard -"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.1": - version: 3.0.1 - resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.1" +"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.2": + version: 3.0.2 + resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.2" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" - "@csstools/media-query-list-parser": "npm:^3.0.1" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/media-query-list-parser": "npm:^4.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/e491cb149fb4fff85b2f03191511e43654ae00716e3c1ea9f1dc22ec4e7042c35f034d372082a69d3621c86cafbe46e8f419872fa36f4a534f145f584d655768 + checksum: 10c0/3ac4073d2e958bfb24ae45f673070dd805f0fcf07bc8d00a9a98f596d1096e7be282c8d8e87df3abde90f33fcbe2c7705e972b8c1a58e43ec44729f470b76096 languageName: node linkType: hard @@ -1877,18 +1810,18 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-oklab-function@npm:4.0.2" +"@csstools/postcss-oklab-function@npm:^4.0.3": + version: 4.0.3 + resolution: "@csstools/postcss-oklab-function@npm:4.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/3209a7cec6d3577544a7ef41f2d5cca25f77891d4ec0d7f39d32f9a79a6c9a9b0ee6b54b2937a2d995548ad11c39966b07d4b9f58e907ffbe1a4b454f2d277f3 + checksum: 10c0/650bcb4f664308972588a8f789f806d63c4069e2e008cfc3b5c80bf9df992c62972dce279b8f434c7f78823e97095942ee4f0e37bc549258887213e72acb7ef8 languageName: node linkType: hard @@ -1903,18 +1836,18 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^3.0.2": - version: 3.0.2 - resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.2" +"@csstools/postcss-relative-color-syntax@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/34a8c999e08c6e7833484ee2fb91e7fcc25235d6c361712fed581e44a5a29f1ceb95415b6f4260de53809ac13f5da5415d1905c2971477cf5d45e5196081c663 + checksum: 10c0/c241fe6b725d775f6d2085be1dff3868d189b176fa91ab1eb1133e30e30c8151bded4e50d17a845edd0bdd0a7adf9e8883cb2634fea3394872591fe9ad2a7e86 languageName: node linkType: hard @@ -1929,16 +1862,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-stepped-value-functions@npm:^4.0.1": - version: 4.0.1 - resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.1" +"@csstools/postcss-stepped-value-functions@npm:^4.0.2": + version: 4.0.2 + resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.2" dependencies: - "@csstools/css-calc": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-calc": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/7e65969b124fce603675ca17c2ffa2bb456677866e54bc9fbdc4da0945be1593fde2abb0730d3d03190776ad2022b394a1f9d4834c5b1f4c7ec497929fd35f8f + checksum: 10c0/444a27d725bc7a8e1554469e8ac69e248ff525b728fbe058523b0f1aefcff80ca707f543d21fead0a22d51603b1669190fb01f0f2dcd599a01768a37e0d62bc3 languageName: node linkType: hard @@ -1954,16 +1887,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-trigonometric-functions@npm:^4.0.1": - version: 4.0.1 - resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.1" +"@csstools/postcss-trigonometric-functions@npm:^4.0.2": + version: 4.0.2 + resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.2" dependencies: - "@csstools/css-calc": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-calc": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/59e017ebb9f4f8f027e134024e3322b5e202cc96073e0bb0d45733a829c8eadc7f4f7ce57ce8360a748a677595af9ea95da1779684699b48b911b73b4017ac8b + checksum: 10c0/eaecb2ea891162e4fcbbccf4f660c99e9e59f21937b70fe6aec3b51441eff2a12c1a2dc13fff426722629a7929919fd866311eaa68d74ee9d1f5387a23502fe2 languageName: node linkType: hard @@ -2010,6 +1943,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" @@ -2214,8 +2196,8 @@ __metadata: linkType: hard "@formatjs/cli@npm:^6.1.1": - version: 6.2.12 - resolution: "@formatjs/cli@npm:6.2.12" + version: 6.2.15 + resolution: "@formatjs/cli@npm:6.2.15" peerDependencies: "@glimmer/env": ^0.1.7 "@glimmer/reference": ^0.91.1 || ^0.92.0 @@ -2244,7 +2226,7 @@ __metadata: optional: true bin: formatjs: bin/formatjs - checksum: 10c0/3bd05a9fad6c837e22988e6638f426c128efa46ab80ff88cf2ad81fb3bc10cf4f228907577fc01e24c2d7d505cfabfaa69f0496d2ec8f0ab2d6b5eaccb5e475c + checksum: 10c0/e947aa7f3994251392fe15673752a8d8e3c8a30733bb49de5e617d45a327a3e1d16419e2d6b01f7ef2cbe86e2946024342d5b3301e6a8f17de3de9e2e7aedb29 languageName: node linkType: hard @@ -2258,12 +2240,34 @@ __metadata: languageName: node linkType: hard -"@formatjs/fast-memoize@npm:2.2.0": +"@formatjs/ecma402-abstract@npm:2.2.0": version: 2.2.0 - resolution: "@formatjs/fast-memoize@npm:2.2.0" + resolution: "@formatjs/ecma402-abstract@npm:2.2.0" dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/ae88c5a93b96235aba4bd9b947d0310d2ec013687a99133413361b24122b5cdea8c9bf2e04a4a2a8b61f1f4ee5419ef6416ca4796554226b5050e05a9ce6ef49 + "@formatjs/fast-memoize": "npm:2.2.1" + "@formatjs/intl-localematcher": "npm:0.5.5" + tslib: "npm:^2.7.0" + checksum: 10c0/3f8e5c1680ab3babf44a6324ae36d6355674562df61e0f0ce3bcec35c3b31d77f9c3b28596af79a9f52641aee834a11673dc4cf30093bbf27c4a96e18c8cc74b + languageName: node + linkType: hard + +"@formatjs/fast-memoize@npm:2.2.1": + version: 2.2.1 + resolution: "@formatjs/fast-memoize@npm:2.2.1" + dependencies: + tslib: "npm:^2.7.0" + checksum: 10c0/cb8cbf1aba907d395d1fe405f67a8da26686b2fc26eefde7541d49d748d2d9b939f2bc428b7d40d2c31366a6ce42cf16724c966965701186986c5882fdba3c8b + languageName: node + linkType: hard + +"@formatjs/icu-messageformat-parser@npm:2.7.10": + version: 2.7.10 + resolution: "@formatjs/icu-messageformat-parser@npm:2.7.10" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/icu-skeleton-parser": "npm:1.8.4" + tslib: "npm:^2.7.0" + checksum: 10c0/7f2b9bb31c64d2b45584a77e2e6a7c4185f247eea22c0d8e2257ac95feff36894a0936d31778d17874cd249c39058fcb894c27e13a6cadb056996e7232957655 languageName: node linkType: hard @@ -2288,25 +2292,35 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-displaynames@npm:6.6.8": - version: 6.6.8 - resolution: "@formatjs/intl-displaynames@npm:6.6.8" +"@formatjs/icu-skeleton-parser@npm:1.8.4": + version: 1.8.4 + resolution: "@formatjs/icu-skeleton-parser@npm:1.8.4" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/intl-localematcher": "npm:0.5.4" - tslib: "npm:^2.4.0" - checksum: 10c0/1a03e7644022741c1bcf10fcd07da88c434416a13603ace693a038114010463307b4130d3a3f53ad5665bd27fca9a6b19ac8e5bf58e17598b1ea84db173fdfbb + "@formatjs/ecma402-abstract": "npm:2.2.0" + tslib: "npm:^2.7.0" + checksum: 10c0/a6cd90e89b994e6fa2b66f83a80250d17fdddaeb755cd1f38be1d51a737a6f8a9b123912943d3dcad278833e3a04683a9081b187300f1a481791527954e63e82 languageName: node linkType: hard -"@formatjs/intl-listformat@npm:7.5.7": - version: 7.5.7 - resolution: "@formatjs/intl-listformat@npm:7.5.7" +"@formatjs/intl-displaynames@npm:6.6.10": + version: 6.6.10 + resolution: "@formatjs/intl-displaynames@npm:6.6.10" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/intl-localematcher": "npm:0.5.4" - tslib: "npm:^2.4.0" - checksum: 10c0/5d0478752d669d87c82aa80880df464d64a1c8974fcb6136bc854567f570a1696e5468005ffa266cfcb623adb7c7299b839c06ea33897f55d35dab6a7575cc84 + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/intl-localematcher": "npm:0.5.5" + tslib: "npm:^2.7.0" + checksum: 10c0/e4158f67fc0d6c2345d05b85183aef480fc86c68b60643abdd143ddc66a2203acfcf1b3dc4619658479e54c971c878a2548db34e08f3b035348686f088bf03c4 + languageName: node + linkType: hard + +"@formatjs/intl-listformat@npm:7.5.9": + version: 7.5.9 + resolution: "@formatjs/intl-listformat@npm:7.5.9" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/intl-localematcher": "npm:0.5.5" + tslib: "npm:^2.7.0" + checksum: 10c0/b5041de4d6e011f36ba4b54406aae9aef763f8bc8b22364bdc8447d0b8b3e553111d117b02f801c31f2ab2c0d3abc086bd90db1b83c000babb99316cd15be5e2 languageName: node linkType: hard @@ -2319,34 +2333,43 @@ __metadata: languageName: node linkType: hard +"@formatjs/intl-localematcher@npm:0.5.5": + version: 0.5.5 + resolution: "@formatjs/intl-localematcher@npm:0.5.5" + dependencies: + tslib: "npm:^2.7.0" + checksum: 10c0/a6bf466bae29ca838ab06ffa2ce2cc9d5dd98e096ec73986b45ca4354b6adc0ca9078d9fd3aa30dbf27677940cfb3fb050ca0bce3018cd6f3f4d7e4bdad91035 + languageName: node + linkType: hard + "@formatjs/intl-pluralrules@npm:^5.2.2": - version: 5.2.14 - resolution: "@formatjs/intl-pluralrules@npm:5.2.14" + version: 5.2.16 + resolution: "@formatjs/intl-pluralrules@npm:5.2.16" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/intl-localematcher": "npm:0.5.4" - tslib: "npm:^2.4.0" - checksum: 10c0/3c00109c8d4c8b221c2b9af38a38d31cd6293a0a412a1f2cdae2b8ef81bd71626c9ff4a647389682cb27ae5c223bd6f64ef54d03e3f6f19c372e0c6194b76b38 + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/intl-localematcher": "npm:0.5.5" + tslib: "npm:^2.7.0" + checksum: 10c0/2250a96a74a153a5f1e771233c366c42005efd71ac5ff665891a308ce78a68f85709f8c892d28a1e334f974252bfb3407f6a64da616c3adbeb158310ef73d71b 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.8": + version: 2.10.8 + resolution: "@formatjs/intl@npm:2.10.8" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/fast-memoize": "npm:2.2.0" - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/intl-displaynames": "npm:6.6.8" - "@formatjs/intl-listformat": "npm:7.5.7" - intl-messageformat: "npm:10.5.14" - tslib: "npm:^2.4.0" + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/fast-memoize": "npm:2.2.1" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + "@formatjs/intl-displaynames": "npm:6.6.10" + "@formatjs/intl-listformat": "npm:7.5.9" + intl-messageformat: "npm:10.7.0" + tslib: "npm:^2.7.0" peerDependencies: typescript: ^4.7 || 5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/ca7877e962f73f1fe0e358f12d73bdc3ec4006c14ee801e06d9f7aef06bcdcc12355a8f53f32b0e890f829949ded35e825c914ca5f4709eb1e08c2a18c1368c2 + checksum: 10c0/e35a4421f445ef4f7ce362144dde143ad895391b03380fbf896fe261a445fa6b5d886989e07bf9b49e52e83f0a3f9b667cfecbc2684a9ea898c6d25daf07b392 languageName: node linkType: hard @@ -2370,6 +2393,26 @@ __metadata: languageName: node linkType: hard +"@formatjs/ts-transformer@npm:3.13.16": + version: 3.13.16 + resolution: "@formatjs/ts-transformer@npm:3.13.16" + dependencies: + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + "@types/json-stable-stringify": "npm:^1.0.32" + "@types/node": "npm:14 || 16 || 17 || 18" + chalk: "npm:^4.0.0" + json-stable-stringify: "npm:^1.0.1" + tslib: "npm:^2.7.0" + typescript: "npm:5" + peerDependencies: + ts-jest: ">=27" + peerDependenciesMeta: + ts-jest: + optional: true + checksum: 10c0/de03e8bc8c730f2e122970d5843762e0c5183181ba58c9759db2f1ed45fcbfbb8046dbb3318f906574f89026481b9205f5bd6fbf3f410a5e5e1754f575baa489 + languageName: node + linkType: hard + "@gamestdio/websocket@npm:^0.3.2": version: 0.3.2 resolution: "@gamestdio/websocket@npm:0.3.2" @@ -2753,11 +2796,14 @@ __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" "@github/webauthn-json": "npm:^2.1.1" - "@rails/ujs": "npm:7.1.400" + "@rails/ujs": "npm:7.1.401" "@reduxjs/toolkit": "npm:^2.0.1" "@svgr/webpack": "npm:^5.5.0" "@testing-library/dom": "npm:^10.2.0" @@ -3059,16 +3105,16 @@ __metadata: languageName: node linkType: hard -"@rails/ujs@npm:7.1.400": - version: 7.1.400 - resolution: "@rails/ujs@npm:7.1.400" - checksum: 10c0/181329e731b925788a530dc5bc44eb4a07ae780e20b0309fd9140ebeeca30d9432ed50be0f25ae60f10beb3aa8883f6d662e4b9c6f6cd19a32c1f42ab2505c47 +"@rails/ujs@npm:7.1.401": + version: 7.1.401 + resolution: "@rails/ujs@npm:7.1.401" + checksum: 10c0/08eae084c80e837e47cc01d0be25a431495f7dea381dcaaa4ce39a3217fac46bf87d169b3dfcf304ae16e0714de7435c2b8c5eb8d5052e3ba70ef3050a72fa3c languageName: node linkType: hard "@reduxjs/toolkit@npm:^2.0.1": - version: 2.2.7 - resolution: "@reduxjs/toolkit@npm:2.2.7" + version: 2.2.8 + resolution: "@reduxjs/toolkit@npm:2.2.8" dependencies: immer: "npm:^10.0.3" redux: "npm:^5.0.1" @@ -3082,7 +3128,7 @@ __metadata: optional: true react-redux: optional: true - checksum: 10c0/7761a91adac2b5e1d50a8163ba5441480bb86a3a80b7583037c27a88463394b132dd7592862fc2be03aa7ab98a6e1710549889986dc0d3f033c169a3ba2cb02e + checksum: 10c0/bf1356d71bfb82e5a181692c79c19b7bc19355260a9966f6562604c995f0cd0ce1154177ccd14095e8b319e73f64cfe86a4e46a83d24edba7876d4ae71fd5ae0 languageName: node linkType: hard @@ -3437,7 +3483,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:*, @types/babel__core@npm:^7.1.12, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.1.7, @types/babel__core@npm:^7.20.1": +"@types/babel__core@npm:*, @types/babel__core@npm:^7.1.12, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.1, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -3459,12 +3505,12 @@ __metadata: languageName: node linkType: hard -"@types/babel__helper-plugin-utils@npm:^7.10.0": - version: 7.10.2 - resolution: "@types/babel__helper-plugin-utils@npm:7.10.2" +"@types/babel__helper-plugin-utils@npm:^7.10.3": + version: 7.10.3 + resolution: "@types/babel__helper-plugin-utils@npm:7.10.3" dependencies: "@types/babel__core": "npm:*" - checksum: 10c0/1c544e33b30ccfc02254b9fe090c52880c8bb05e5406f525bfdce71ce34e93677276f788b93e9fa5e1a16f6317b97e59a07d8a92bf4726d8f4639a0045ebb590 + checksum: 10c0/c22f68e8019c1e75e42fccc6eaca94a269fa177c4544599aa084b216b879b626f63f89755a4ac2dc9054b6e9ed4e0fab1e3460d36ce20767c99aef4a3c81fce3 languageName: node linkType: hard @@ -3478,12 +3524,12 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6, @types/babel__traverse@npm:^7.1.7": - version: 7.20.3 - resolution: "@types/babel__traverse@npm:7.20.3" +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6, @types/babel__traverse@npm:^7.20.6": + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" dependencies: "@babel/types": "npm:^7.20.7" - checksum: 10c0/295ed9b837e62e17ee43be0df45d90fff5208986bd43af593c9020d152d3b2c55328e038c2f8585926b63cc22f887f28bf3f4c805aa881e2dd0bdd5ead92ece0 + checksum: 10c0/7ba7db61a53e28cac955aa99af280d2600f15a8c056619c05b6fc911cbe02c61aa4f2823299221b23ce0cce00b294c0e5f618ec772aa3f247523c2e48cf7b888 languageName: node linkType: hard @@ -3713,9 +3759,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 @@ -3756,6 +3802,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:14 || 16 || 17 || 18": + version: 18.19.55 + resolution: "@types/node@npm:18.19.55" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10c0/19ffeca0086b45cba08d4585623cd0d80fbacb659debde82a4baa008fc0c25ba6c21cd721f3a9f0be74f70940694b00458cac61c89f8b2a1e55ca4322a9aad2b + languageName: node + linkType: hard + "@types/object-assign@npm:^4.0.30": version: 4.0.33 resolution: "@types/object-assign@npm:4.0.33" @@ -3789,9 +3844,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 @@ -3933,13 +3988,13 @@ __metadata: languageName: node 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" +"@types/react@npm:*, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7, @types/react@npm:^18.3.11": + version: 18.3.11 + resolution: "@types/react@npm:18.3.11" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10c0/548b1d3d7c2f0242fbfdbbd658731b4ce69a134be072fa83e6ab516f2840402a3f20e3e7f72e95133b23d4880ef24a6d864050dc8e1f7c68f39fa87ca8445917 + checksum: 10c0/ce80512246ca5bda69db85b9f4f1835189334acfb6b2c4f3eda8cabff1ff1a3ea9ce4f3b895bdbc18c94140aa45592331aa3fdeb557f525c1b048de7ce84fc0e languageName: node linkType: hard @@ -5194,21 +5249,21 @@ __metadata: linkType: hard "babel-plugin-formatjs@npm:^10.5.1": - version: 10.5.16 - resolution: "babel-plugin-formatjs@npm:10.5.16" + version: 10.5.18 + resolution: "babel-plugin-formatjs@npm:10.5.18" dependencies: - "@babel/core": "npm:^7.10.4" - "@babel/helper-plugin-utils": "npm:^7.10.4" - "@babel/plugin-syntax-jsx": "npm:7" - "@babel/traverse": "npm:7" - "@babel/types": "npm:^7.12.11" - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/ts-transformer": "npm:3.13.14" - "@types/babel__core": "npm:^7.1.7" - "@types/babel__helper-plugin-utils": "npm:^7.10.0" - "@types/babel__traverse": "npm:^7.1.7" - tslib: "npm:^2.4.0" - checksum: 10c0/03d9d2b0b9cdc05c011bfb417a43e5c0f557868ed84d83acbc3cb9072b7fa98f5219473d0bd61f02741c151d6f2162da363bd337522c80af14721ae37f6da86b + "@babel/core": "npm:^7.25.0" + "@babel/helper-plugin-utils": "npm:^7.25.0" + "@babel/plugin-syntax-jsx": "npm:^7.25.0" + "@babel/traverse": "npm:^7.25.0" + "@babel/types": "npm:^7.25.0" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + "@formatjs/ts-transformer": "npm:3.13.16" + "@types/babel__core": "npm:^7.20.5" + "@types/babel__helper-plugin-utils": "npm:^7.10.3" + "@types/babel__traverse": "npm:^7.20.6" + tslib: "npm:^2.7.0" + checksum: 10c0/3e7753cb1837ea300f7b0d574751758330f4fe56e4f686a1ceb7acc612c0ac1353ed2a918b5af6e4dcaf579c623d56f714159a265d64b71897471a69f15910b8 languageName: node linkType: hard @@ -5645,17 +5700,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3": - version: 4.23.3 - resolution: "browserslist@npm:4.23.3" +"browserslist@npm:^4.0.0, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3, browserslist@npm:^4.24.0": + version: 4.24.0 + resolution: "browserslist@npm:4.24.0" dependencies: - caniuse-lite: "npm:^1.0.30001646" - electron-to-chromium: "npm:^1.5.4" + caniuse-lite: "npm:^1.0.30001663" + electron-to-chromium: "npm:^1.5.28" node-releases: "npm:^2.0.18" update-browserslist-db: "npm:^1.1.0" bin: browserslist: cli.js - checksum: 10c0/3063bfdf812815346447f4796c8f04601bf5d62003374305fd323c2a463e42776475bcc5309264e39bcf9a8605851e53560695991a623be988138b3ff8c66642 + checksum: 10c0/95e76ad522753c4c470427f6e3c8a4bb5478ff448841e22b3d3e53f89ecaf17b6984666d6c7e715c370f1e7fa0cf684f42e34e554236a8b2fab38ea76b9e4c52 languageName: node linkType: hard @@ -5857,10 +5912,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001646": - version: 1.0.30001651 - resolution: "caniuse-lite@npm:1.0.30001651" - checksum: 10c0/7821278952a6dbd17358e5d08083d258f092e2a530f5bc1840657cb140fbbc5ec44293bc888258c44a18a9570cde149ed05819ac8320b9710cf22f699891e6ad +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001663": + version: 1.0.30001666 + resolution: "caniuse-lite@npm:1.0.30001666" + checksum: 10c0/2d49e9be676233c24717f12aad3d01b3e5f902b457fe1deefaa8d82e64786788a8f79381ae437c61b50e15c9aea8aeb59871b1d54cb4c28b9190d53d292e2339 languageName: node linkType: hard @@ -6356,10 +6411,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.6.0": - version: 0.6.0 - resolution: "cookie@npm:0.6.0" - checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 +"cookie@npm:0.7.1": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: 10c0/5de60c67a410e7c8dc8a46a4b72eb0fe925871d057c9a5d2c0e8145c4270a4f81076de83410c4d397179744b478e33cd80ccbcc457abf40a9409ad27dcd21dde languageName: node linkType: hard @@ -6370,7 +6425,7 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.37.1, core-js-compat@npm:^3.38.0": +"core-js-compat@npm:^3.38.0, core-js-compat@npm:^3.38.1": version: 3.38.1 resolution: "core-js-compat@npm:3.38.1" dependencies: @@ -6576,10 +6631,10 @@ __metadata: languageName: node linkType: hard -"css-functions-list@npm:^3.2.2": - version: 3.2.2 - resolution: "css-functions-list@npm:3.2.2" - checksum: 10c0/8638a63d0cf1bdc50d4a752ec1c94a57e9953c3b03eace4f5526db20bec3c061e95089f905dbb4999c44b9780ce777ba856967560f6d15119a303f6030901c10 +"css-functions-list@npm:^3.2.3": + version: 3.2.3 + resolution: "css-functions-list@npm:3.2.3" + checksum: 10c0/03f9ed34eeed310d2b1cf0e524eea02bc5f87854a4de85f8957ea432ab1036841a3fb00879590519f7bb8fda40d992ce7a72fa9b61696ca1dc53b90064858f96 languageName: node linkType: hard @@ -6687,6 +6742,16 @@ __metadata: languageName: node linkType: hard +"css-tree@npm:^3.0.0": + version: 3.0.0 + resolution: "css-tree@npm:3.0.0" + dependencies: + mdn-data: "npm:2.10.0" + source-map-js: "npm:^1.0.1" + checksum: 10c0/43d44fdf7004ae91d73d486f17894fef77efa33747a6752b9241cf0f5fb47fabc16ec34a96a993651d9014dfdeee803d7c5fcd3548214252ee19f4e5c98999b2 + languageName: node + linkType: hard + "css-tree@npm:~2.2.0": version: 2.2.1 resolution: "css-tree@npm:2.2.1" @@ -6836,12 +6901,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 @@ -6936,15 +7001,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:~4.3.6": - version: 4.3.6 - resolution: "debug@npm:4.3.6" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.3.7, debug@npm:~4.3.6": + version: 4.3.7 + resolution: "debug@npm:4.3.7" dependencies: - ms: "npm:2.1.2" + ms: "npm:^2.1.3" peerDependenciesMeta: supports-color: optional: true - checksum: 10c0/3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285 + checksum: 10c0/1471db19c3b06d485a622d62f65947a19a23fbd0dd73f7fd3eafb697eec5360cde447fb075919987899b1a2096e85d35d4eb5a4de09a57600ac9cf7e6c8e768b languageName: node linkType: hard @@ -7432,10 +7497,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.4": - version: 1.5.7 - resolution: "electron-to-chromium@npm:1.5.7" - checksum: 10c0/be4460bbe3d2186a16d53a03da67fde6fd06ad41943553ce517a45d52e03424732a982f75528e8a2d5fb042d6afde64186aa482caec0fb925daa5a74cf5ef060 +"electron-to-chromium@npm:^1.5.28": + version: 1.5.31 + resolution: "electron-to-chromium@npm:1.5.31" + checksum: 10c0/e8aecd88c4c6d50a9d459b4b222865b855bab8f1b52e82913804e18b7884f2887bd76c61b3aa08c2ccbdcda098dd8486443f75bf770f0138f21dd9e63548fca7 languageName: node linkType: hard @@ -8367,15 +8432,15 @@ __metadata: linkType: hard "express@npm:^4.17.1, express@npm:^4.18.2": - version: 4.21.0 - resolution: "express@npm:4.21.0" + version: 4.21.1 + resolution: "express@npm:4.21.1" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" body-parser: "npm:1.20.3" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.6.0" + cookie: "npm:0.7.1" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -8401,7 +8466,7 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10c0/4cf7ca328f3fdeb720f30ccb2ea7708bfa7d345f9cc460b64a82bf1b2c91e5b5852ba15a9a11b2a165d6089acf83457fc477dc904d59cd71ed34c7a91762c6cc + checksum: 10c0/0c287867e5f6129d3def1edd9b63103a53c40d4dc8628839d4b6827e35eb8f0de5a4656f9d85f4457eba584f9871ebb2ad26c750b36bd75d9bbb8bcebdc4892c languageName: node linkType: hard @@ -8545,12 +8610,12 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^9.0.0": - version: 9.0.0 - resolution: "file-entry-cache@npm:9.0.0" +"file-entry-cache@npm:^9.1.0": + version: 9.1.0 + resolution: "file-entry-cache@npm:9.1.0" dependencies: flat-cache: "npm:^5.0.0" - checksum: 10c0/07b0a4f062dc0aa258f3e1b06ac083ea25313f5e289943e146fafdaf3315dcc031635545eea7fe98fe5598b91d6c7f48dba7a251dd7ac20108a6ebf7d00b0b1c + checksum: 10c0/4b4dbc1e972f50202b1a4430d30fd99378ef6e2a64857176abdc65c5e4730a948fb37e274478520a7bacbc70f3abba455a4b9d2c1915c53f30d11dc85d3fef5e languageName: node linkType: hard @@ -8902,9 +8967,9 @@ __metadata: linkType: hard "fuzzysort@npm:^3.0.0": - version: 3.0.2 - resolution: "fuzzysort@npm:3.0.2" - checksum: 10c0/c6cdbd092a8e91ed822aeac6d4fb95559759c10602cb29f27307c1cabd01fdd384fa399f7757722435b595244efb000cd63f144104c41b8551b2faff123279cb + version: 3.1.0 + resolution: "fuzzysort@npm:3.1.0" + checksum: 10c0/da9bb32de16f2a5c2c000b99031d9f4f8a01380c12d5d3b67296443a1152c55987ce3c4ddbfe97481b0e9b6f2fb77d61dceba29a93ad36ee23ef5bab6a31afb8 languageName: node linkType: hard @@ -9624,13 +9689,20 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.3.1, ignore@npm:^5.3.2": +"ignore@npm:^5.2.0, ignore@npm:^5.3.1": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 languageName: node linkType: hard +"ignore@npm:^6.0.2": + version: 6.0.2 + resolution: "ignore@npm:6.0.2" + checksum: 10c0/9a38feac1861906a78ba0f03e8ef3cd6b0526dce2a1a84e1009324b557763afeb9c3ebcc04666b21f7bbf71adda45e76781bb9e2eaa0903d45dcaded634454f5 + languageName: node + linkType: hard + "immer@npm:^10.0.3": version: 10.0.3 resolution: "immer@npm:10.0.3" @@ -9794,15 +9866,15 @@ __metadata: languageName: node linkType: hard -"intl-messageformat@npm:10.5.14, intl-messageformat@npm:^10.3.5": - version: 10.5.14 - resolution: "intl-messageformat@npm:10.5.14" +"intl-messageformat@npm:10.7.0, intl-messageformat@npm:^10.3.5": + version: 10.7.0 + resolution: "intl-messageformat@npm:10.7.0" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/fast-memoize": "npm:2.2.0" - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - tslib: "npm:^2.4.0" - checksum: 10c0/8ec0a60539f67039356e211bcc8d81cf1bd9d62190a72ab0e94504da92f0242fe2f94ffb512b97cc6f63782b7891874d4038536ce04631e59d762c3441c60b4b + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/fast-memoize": "npm:2.2.1" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + tslib: "npm:^2.7.0" + checksum: 10c0/772469599fa8ab43dc933d03c75c6290220565c97afdc60cb67d036f2c51f1b3a825b2345933ee7616ecdf018b95ea7704f5ec80ded5a8efc2ce7f4b2962cae3 languageName: node linkType: hard @@ -11129,10 +11201,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 +11217,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,25 +11230,16 @@ __metadata: peerDependenciesMeta: canvas: optional: true - checksum: 10c0/1552bcfb816b2c69ae159ba0cd79e8964030c106cc0cb2deb20a64c1ca54e1ea41352b9802d89b7cf823e43e6d74ed7289abff4aacc95b1b2bc936570aab3594 - languageName: node - linkType: hard - -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 10c0/dbf59312e0ebf2b4405ef413ec2b25abb5f8f4d9bc5fb8d9f90381622ebca5f2af6a6aa9a8578f65903f9e33990a6dc798edd0ce5586894bf0e9e31803a1de88 + checksum: 10c0/6bda32a6dfe4e37a30568bf51136bdb3ba9c0b72aadd6356280404275a34c9e097c8c25b5eb3c742e602623741e172da977ff456684befd77c9042ed9bf8c2b4 languageName: node linkType: hard -"jsesc@npm:~0.5.0": - version: 0.5.0 - resolution: "jsesc@npm:0.5.0" +"jsesc@npm:^3.0.2, jsesc@npm:~3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" bin: jsesc: bin/jsesc - checksum: 10c0/f93792440ae1d80f091b65f8ceddf8e55c4bb7f1a09dee5dcbdb0db5612c55c0f6045625aa6b7e8edb2e0a4feabd80ee48616dbe2d37055573a84db3d24f96d9 + checksum: 10c0/ef22148f9e793180b14d8a145ee6f9f60f301abf443288117b4b6c53d0ecd58354898dc506ccbb553a5f7827965cd38bc5fb726575aae93c5e8915e2de8290e1 languageName: node linkType: hard @@ -11805,6 +11868,13 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.10.0": + version: 2.10.0 + resolution: "mdn-data@npm:2.10.0" + checksum: 10c0/f6f1a6a6eb092bab250d06f6f6c7cb1733a77a17e7119aac829ad67d4322bbf6a30df3c6d88686e71942e66bd49274b2ddfede22a1d3df0d6c49a56fbd09eb7c + languageName: node + linkType: hard + "media-typer@npm:0.3.0": version: 0.3.0 resolution: "media-typer@npm:0.3.0" @@ -12184,14 +12254,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc - languageName: node - linkType: hard - -"ms@npm:2.1.3, ms@npm:^2.1.1": +"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 @@ -13339,18 +13402,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^7.0.2": - version: 7.0.2 - resolution: "postcss-color-functional-notation@npm:7.0.2" +"postcss-color-functional-notation@npm:^7.0.3": + version: 7.0.3 + resolution: "postcss-color-functional-notation@npm:7.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/e89c0bff94558b0c978ac36f7e02f7f516291f90fd43169d39c63ad2bb0415e3b1c4b3c2469280d578727e850fdf15a557230cb28275f3f0676f0f73187f2867 + checksum: 10c0/5e04c81002512c960784043c096bc91ebc76b8fddb9259a2418b0e121eb65042944cc0f78946f6b7e5774ff1fee087849019655e4848af1f88879e3ab9ff7c17 languageName: node linkType: hard @@ -13404,46 +13467,46 @@ __metadata: languageName: node linkType: hard -"postcss-custom-media@npm:^11.0.1": - version: 11.0.1 - resolution: "postcss-custom-media@npm:11.0.1" +"postcss-custom-media@npm:^11.0.3": + version: 11.0.3 + resolution: "postcss-custom-media@npm:11.0.3" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" - "@csstools/media-query-list-parser": "npm:^3.0.1" + "@csstools/cascade-layer-name-parser": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/media-query-list-parser": "npm:^4.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/771b281a28f105370ede7c4a86f9e3dd8d9ec3bf2d2883d4f2cfe9c42b5ec1bf88f713458b356870315d0ba3a285fbeb7bb514a1203d1c4fb113bd9044369bf2 + checksum: 10c0/bd3f0cf17d7422385d26afed510dc2acebb1d8c25fce13e2bbee1c49cdc7fe95ebe7f50b89ef0a88ebdd5f6826e89d99e26b905881ceff788df655670dba93d8 languageName: node linkType: hard -"postcss-custom-properties@npm:^14.0.1": - version: 14.0.1 - resolution: "postcss-custom-properties@npm:14.0.1" +"postcss-custom-properties@npm:^14.0.2": + version: 14.0.2 + resolution: "postcss-custom-properties@npm:14.0.2" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/cascade-layer-name-parser": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/utilities": "npm:^2.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/12180a7f4a4fe2d528387346a1810b82ed870081756dcf6be226c839716ab3f6f4d6ca4c7208a07d7d84bf2c986beef6473e29964e7c2572066fca5d3b000ed5 + checksum: 10c0/ea2e0cb60c558bb1afb4e601dcc64a38e1b28e5df3e47b83b858fc12d909d0e3453013e6b368fc05a7db7098ffcdc702a30a92f1a3c0ef67dfb97bf089021f1a languageName: node linkType: hard -"postcss-custom-selectors@npm:^8.0.1": - version: 8.0.1 - resolution: "postcss-custom-selectors@npm:8.0.1" +"postcss-custom-selectors@npm:^8.0.2": + version: 8.0.2 + resolution: "postcss-custom-selectors@npm:8.0.2" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.1" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/cascade-layer-name-parser": "npm:^2.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/b867233b3d68fbab90afca8a776eb74196ebc3fac8988175d95118a47993c793138fec6cc580272bb35d9bd31086acbdd33ff86da0cab83ef2f08bfc1c23ecd6 + checksum: 10c0/81673ffb0874f63c0f5e14315a5808259ec80ae8452aaf10d28112d30a9aaabbf61d13edb02f8be2965f44b943968c7eda051a1693da436ef157e77fcff0d752 languageName: node linkType: hard @@ -13561,18 +13624,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^7.0.2": - version: 7.0.2 - resolution: "postcss-lab-function@npm:7.0.2" +"postcss-lab-function@npm:^7.0.3": + version: 7.0.3 + resolution: "postcss-lab-function@npm:7.0.3" dependencies: - "@csstools/css-color-parser": "npm:^3.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.1" - "@csstools/css-tokenizer": "npm:^3.0.1" + "@csstools/css-color-parser": "npm:^3.0.3" + "@csstools/css-parser-algorithms": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.2" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/6b2be7e762b4ccb58ea9051723d390f6732ad78bb30bfef9499139cf5e2ac160c3de31b2b005fcc30e9fced4abe1685df6cb76c99d548896bae6746105ac8520 + checksum: 10c0/c50a73a9ed54b4194998c4627599d1f42074235f572edbbcdb0e00717f3ae2121dc8378d917792b281860c5650a617d923823da6f395515f610b5760d115354d languageName: node linkType: hard @@ -13893,38 +13956,38 @@ __metadata: linkType: hard "postcss-preset-env@npm:^10.0.0": - version: 10.0.3 - resolution: "postcss-preset-env@npm:10.0.3" + version: 10.0.7 + resolution: "postcss-preset-env@npm:10.0.7" dependencies: "@csstools/postcss-cascade-layers": "npm:^5.0.0" - "@csstools/postcss-color-function": "npm:^4.0.2" - "@csstools/postcss-color-mix-function": "npm:^3.0.2" - "@csstools/postcss-content-alt-text": "npm:^2.0.1" - "@csstools/postcss-exponential-functions": "npm:^2.0.1" + "@csstools/postcss-color-function": "npm:^4.0.3" + "@csstools/postcss-color-mix-function": "npm:^3.0.3" + "@csstools/postcss-content-alt-text": "npm:^2.0.2" + "@csstools/postcss-exponential-functions": "npm:^2.0.2" "@csstools/postcss-font-format-keywords": "npm:^4.0.0" - "@csstools/postcss-gamut-mapping": "npm:^2.0.2" - "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.2" - "@csstools/postcss-hwb-function": "npm:^4.0.2" + "@csstools/postcss-gamut-mapping": "npm:^2.0.3" + "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.3" + "@csstools/postcss-hwb-function": "npm:^4.0.3" "@csstools/postcss-ic-unit": "npm:^4.0.0" "@csstools/postcss-initial": "npm:^2.0.0" "@csstools/postcss-is-pseudo-class": "npm:^5.0.0" - "@csstools/postcss-light-dark-function": "npm:^2.0.2" + "@csstools/postcss-light-dark-function": "npm:^2.0.5" "@csstools/postcss-logical-float-and-clear": "npm:^3.0.0" "@csstools/postcss-logical-overflow": "npm:^2.0.0" "@csstools/postcss-logical-overscroll-behavior": "npm:^2.0.0" "@csstools/postcss-logical-resize": "npm:^3.0.0" - "@csstools/postcss-logical-viewport-units": "npm:^3.0.1" - "@csstools/postcss-media-minmax": "npm:^2.0.1" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.1" + "@csstools/postcss-logical-viewport-units": "npm:^3.0.2" + "@csstools/postcss-media-minmax": "npm:^2.0.2" + "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.2" "@csstools/postcss-nested-calc": "npm:^4.0.0" "@csstools/postcss-normalize-display-values": "npm:^4.0.0" - "@csstools/postcss-oklab-function": "npm:^4.0.2" + "@csstools/postcss-oklab-function": "npm:^4.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" - "@csstools/postcss-relative-color-syntax": "npm:^3.0.2" + "@csstools/postcss-relative-color-syntax": "npm:^3.0.3" "@csstools/postcss-scope-pseudo-class": "npm:^4.0.0" - "@csstools/postcss-stepped-value-functions": "npm:^4.0.1" + "@csstools/postcss-stepped-value-functions": "npm:^4.0.2" "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.1" - "@csstools/postcss-trigonometric-functions": "npm:^4.0.1" + "@csstools/postcss-trigonometric-functions": "npm:^4.0.2" "@csstools/postcss-unset-value": "npm:^4.0.0" autoprefixer: "npm:^10.4.19" browserslist: "npm:^4.23.1" @@ -13934,12 +13997,12 @@ __metadata: cssdb: "npm:^8.1.1" postcss-attribute-case-insensitive: "npm:^7.0.0" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^7.0.2" + postcss-color-functional-notation: "npm:^7.0.3" postcss-color-hex-alpha: "npm:^10.0.0" postcss-color-rebeccapurple: "npm:^10.0.0" - postcss-custom-media: "npm:^11.0.1" - postcss-custom-properties: "npm:^14.0.1" - postcss-custom-selectors: "npm:^8.0.1" + postcss-custom-media: "npm:^11.0.3" + postcss-custom-properties: "npm:^14.0.2" + postcss-custom-selectors: "npm:^8.0.2" postcss-dir-pseudo-class: "npm:^9.0.0" postcss-double-position-gradients: "npm:^6.0.0" postcss-focus-visible: "npm:^10.0.0" @@ -13947,7 +14010,7 @@ __metadata: postcss-font-variant: "npm:^5.0.0" postcss-gap-properties: "npm:^6.0.0" postcss-image-set-function: "npm:^7.0.0" - postcss-lab-function: "npm:^7.0.2" + postcss-lab-function: "npm:^7.0.3" postcss-logical: "npm:^8.0.0" postcss-nesting: "npm:^13.0.0" postcss-opacity-percentage: "npm:^3.0.0" @@ -13959,7 +14022,7 @@ __metadata: postcss-selector-not: "npm:^8.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/da42caa2aab4d825fddfde00ebe2416d338c7b9a6f79a68840297888a8384f85991991c3fa10cf2d359fb230c885375f5cebd7bd63972725cd2a596d218f8b6a + checksum: 10c0/f789000e0504fd827e854bb0feb8b4c218d381314e4d863c5a36df925df412d0844c912952fe27892a320433640aeaff03ee94a3057b42011bf5d32b3963f333 languageName: node linkType: hard @@ -14013,12 +14076,12 @@ __metadata: languageName: node linkType: hard -"postcss-safe-parser@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-safe-parser@npm:7.0.0" +"postcss-safe-parser@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-safe-parser@npm:7.0.1" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/4217afd8ce2809e959dc365e4675f499303cc6b91f94db06c8164422822db2d3b3124df701ee2234db4127ad05619b016bfb9c2bccae9bf9cf898a396f1632c9 + checksum: 10c0/6957b10b818bd8d4664ec0e548af967f7549abedfb37f844d389571d36af681340f41f9477b9ccf34bcc7599bdef222d1d72e79c64373001fae77089fba6d965 languageName: node linkType: hard @@ -14082,7 +14145,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.41": +"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.47": version: 8.4.47 resolution: "postcss@npm:8.4.47" dependencies: @@ -14533,26 +14596,26 @@ __metadata: linkType: hard "react-intl@npm:^6.4.2": - version: 6.6.8 - resolution: "react-intl@npm:6.6.8" - dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/intl": "npm:2.10.4" - "@formatjs/intl-displaynames": "npm:6.6.8" - "@formatjs/intl-listformat": "npm:7.5.7" + version: 6.8.0 + resolution: "react-intl@npm:6.8.0" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.0" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + "@formatjs/intl": "npm:2.10.8" + "@formatjs/intl-displaynames": "npm:6.6.10" + "@formatjs/intl-listformat": "npm:7.5.9" "@types/hoist-non-react-statics": "npm:^3.3.1" - "@types/react": "npm:16 || 17 || 18" + "@types/react": "npm:^18.3.11" hoist-non-react-statics: "npm:^3.3.2" - intl-messageformat: "npm:10.5.14" - tslib: "npm:^2.4.0" + intl-messageformat: "npm:10.7.0" + tslib: "npm:^2.7.0" peerDependencies: react: ^16.6.0 || 17 || 18 typescript: ^4.7 || 5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/7673507eb73ad4edd1593da7173cec68f316cf77037e0959900babd32d5984a39ba7fa10aaa0a23bcddb7b98daf7dd007cb73ddfc39127ede87c18ec780a519c + checksum: 10c0/e110d8cbfc227cbed3b72b162fe8a75e824aef47eeb5a7879a5a2d9fa5dd35d2d25149ef57460fa06bca7ae106184c729e410c22bcdb349d29bb1ee35f3c5cf0 languageName: node linkType: hard @@ -14818,15 +14881,15 @@ __metadata: linkType: hard "react-textarea-autosize@npm:^8.4.1": - version: 8.5.3 - resolution: "react-textarea-autosize@npm:8.5.3" + version: 8.5.4 + resolution: "react-textarea-autosize@npm:8.5.4" dependencies: "@babel/runtime": "npm:^7.20.13" use-composed-ref: "npm:^1.3.0" use-latest: "npm:^1.2.1" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10c0/33d38a6d96cf584842695b50c341980944ece23a42155bf0bd1958f02396adb185c7720b88678dc677817fe111783059c0ebcdf7761644006892583b10e258ee + checksum: 10c0/ea92fda2128983c1a8e84c74706ffb4b8bfa1a19c803d210868ec031c1ac3b8ceee8028766ef5d91017265da2bdccf6a85e5b6e5d553005e839f0c47e5758b43 languageName: node linkType: hard @@ -15014,12 +15077,12 @@ __metadata: languageName: node linkType: hard -"regenerate-unicode-properties@npm:^10.1.0": - version: 10.1.1 - resolution: "regenerate-unicode-properties@npm:10.1.1" +"regenerate-unicode-properties@npm:^10.2.0": + version: 10.2.0 + resolution: "regenerate-unicode-properties@npm:10.2.0" dependencies: regenerate: "npm:^1.4.2" - checksum: 10c0/89adb5ee5ba081380c78f9057c02e156a8181969f6fcca72451efc45612e0c3df767b4333f8d8479c274d9c6fe52ec4854f0d8a22ef95dccbe87da8e5f2ac77d + checksum: 10c0/5510785eeaf56bbfdf4e663d6753f125c08d2a372d4107bc1b756b7bf142e2ed80c2733a8b54e68fb309ba37690e66a0362699b0e21d5c1f0255dea1b00e6460 languageName: node linkType: hard @@ -15082,28 +15145,35 @@ __metadata: languageName: node linkType: hard -"regexpu-core@npm:^5.3.1": - version: 5.3.2 - resolution: "regexpu-core@npm:5.3.2" +"regexpu-core@npm:^6.1.1": + version: 6.1.1 + resolution: "regexpu-core@npm:6.1.1" dependencies: - "@babel/regjsgen": "npm:^0.8.0" regenerate: "npm:^1.4.2" - regenerate-unicode-properties: "npm:^10.1.0" - regjsparser: "npm:^0.9.1" + regenerate-unicode-properties: "npm:^10.2.0" + regjsgen: "npm:^0.8.0" + regjsparser: "npm:^0.11.0" unicode-match-property-ecmascript: "npm:^2.0.0" unicode-match-property-value-ecmascript: "npm:^2.1.0" - checksum: 10c0/7945d5ab10c8bbed3ca383d4274687ea825aee4ab93a9c51c6e31e1365edd5ea807f6908f800ba017b66c462944ba68011164e7055207747ab651f8111ef3770 + checksum: 10c0/07d49697e20f9b65977535abba4858b7f5171c13f7c366be53ec1886d3d5f69f1b98cc6a6e63cf271adda077c3366a4c851c7473c28bbd69cf5a6b6b008efc3e languageName: node linkType: hard -"regjsparser@npm:^0.9.1": - version: 0.9.1 - resolution: "regjsparser@npm:0.9.1" +"regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "regjsgen@npm:0.8.0" + checksum: 10c0/44f526c4fdbf0b29286101a282189e4dbb303f4013cf3fea058668d96d113b9180d3d03d1e13f6d4cbde38b7728bf951aecd9dc199938c080093a9a6f0d7a6bd + languageName: node + linkType: hard + +"regjsparser@npm:^0.11.0": + version: 0.11.0 + resolution: "regjsparser@npm:0.11.0" dependencies: - jsesc: "npm:~0.5.0" + jsesc: "npm:~3.0.2" bin: regjsparser: bin/parser - checksum: 10c0/fe44fcf19a99fe4f92809b0b6179530e5ef313ff7f87df143b08ce9a2eb3c4b6189b43735d645be6e8f4033bfb015ed1ca54f0583bc7561bed53fd379feb8225 + checksum: 10c0/155143a8f2c95e3170df4fff10ddf3f16a351b5d2b8cbb257e9f4a50abb9a980a28af0936b5bf850fee767537ffa8eb77c6b211fe8be19834dbe584dfd950c62 languageName: node linkType: hard @@ -15390,13 +15460,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 +15562,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 @@ -16680,8 +16743,8 @@ __metadata: linkType: hard "stylelint@npm:^16.0.2": - version: 16.9.0 - resolution: "stylelint@npm:16.9.0" + version: 16.10.0 + resolution: "stylelint@npm:16.10.0" dependencies: "@csstools/css-parser-algorithms": "npm:^3.0.1" "@csstools/css-tokenizer": "npm:^3.0.1" @@ -16691,17 +16754,17 @@ __metadata: balanced-match: "npm:^2.0.0" colord: "npm:^2.9.3" cosmiconfig: "npm:^9.0.0" - css-functions-list: "npm:^3.2.2" - css-tree: "npm:^2.3.1" - debug: "npm:^4.3.6" + css-functions-list: "npm:^3.2.3" + css-tree: "npm:^3.0.0" + debug: "npm:^4.3.7" fast-glob: "npm:^3.3.2" fastest-levenshtein: "npm:^1.0.16" - file-entry-cache: "npm:^9.0.0" + file-entry-cache: "npm:^9.1.0" global-modules: "npm:^2.0.0" globby: "npm:^11.1.0" globjoin: "npm:^0.1.4" html-tags: "npm:^3.3.1" - ignore: "npm:^5.3.2" + ignore: "npm:^6.0.2" imurmurhash: "npm:^0.1.4" is-plain-object: "npm:^5.0.0" known-css-properties: "npm:^0.34.0" @@ -16710,21 +16773,20 @@ __metadata: micromatch: "npm:^4.0.8" normalize-path: "npm:^3.0.0" picocolors: "npm:^1.0.1" - postcss: "npm:^8.4.41" + postcss: "npm:^8.4.47" postcss-resolve-nested-selector: "npm:^0.1.6" - postcss-safe-parser: "npm:^7.0.0" + postcss-safe-parser: "npm:^7.0.1" postcss-selector-parser: "npm:^6.1.2" postcss-value-parser: "npm:^4.2.0" resolve-from: "npm:^5.0.0" string-width: "npm:^4.2.3" - strip-ansi: "npm:^7.1.0" supports-hyperlinks: "npm:^3.1.0" svg-tags: "npm:^1.0.0" table: "npm:^6.8.2" write-file-atomic: "npm:^5.0.1" bin: stylelint: bin/stylelint.mjs - checksum: 10c0/d3ff9c8945c56b04a2fa16ec33d163325496d5db94b6fcb5adf74c76f7f794ac992888273f9a3317652ba8b6195168b2ffff382ca2a667a241e2ace8c9505ae2 + checksum: 10c0/d07dd156c225d16c740995daacd78090f7fc317602e87bda2fca323a4ae427a8526d724f3089df3b2185df4520f987547668ceea9b30985988ccbc514034aa21 languageName: node linkType: hard @@ -17060,6 +17122,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 +17215,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 +17227,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 +17298,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, tslib@npm:^2.7.0": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard @@ -17342,22 +17431,22 @@ __metadata: linkType: hard "typescript@npm:5, typescript@npm:^5.0.4": - version: 5.5.4 - resolution: "typescript@npm:5.5.4" + version: 5.6.3 + resolution: "typescript@npm:5.6.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/422be60f89e661eab29ac488c974b6cc0a660fb2228003b297c3d10c32c90f3bcffc1009b43876a082515a3c376b1eefcce823d6e78982e6878408b9a923199c + checksum: 10c0/44f61d3fb15c35359bc60399cb8127c30bae554cd555b8e2b46d68fa79d680354b83320ad419ff1b81a0bdf324197b29affe6cc28988cd6a74d4ac60c94f9799 languageName: node linkType: hard "typescript@patch:typescript@npm%3A5#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.5.4 - resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin::version=5.5.4&hash=379a07" + version: 5.6.3 + resolution: "typescript@patch:typescript@npm%3A5.6.3#optional!builtin::version=5.6.3&hash=8c6c40" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/73409d7b9196a5a1217b3aaad929bf76294d3ce7d6e9766dd880ece296ee91cf7d7db6b16c6c6c630ee5096eccde726c0ef17c7dfa52b01a243e57ae1f09ef07 + checksum: 10c0/7c9d2e07c81226d60435939618c91ec2ff0b75fbfa106eec3430f0fcf93a584bc6c73176676f532d78c3594fe28a54b36eb40b3d75593071a7ec91301533ace7 languageName: node linkType: hard @@ -17596,11 +17685,11 @@ __metadata: linkType: hard "use-debounce@npm:^10.0.0": - version: 10.0.3 - resolution: "use-debounce@npm:10.0.3" + version: 10.0.4 + resolution: "use-debounce@npm:10.0.4" peerDependencies: react: "*" - checksum: 10c0/351b62c565d6dce5a21ecc21fe3e1f8db74f70c81c8f7d9dbdfc2da1cb82d883578589f6146e684d91dac534bc3c8b145ab1a36fbf4d44cbb4113827508b39aa + checksum: 10c0/73494fc44b2bd58a7ec799a528fc20077c45fe2e94fedff6dcd88d136f7a39f417d77f584d5613aac615ed32aeb2ea393797ae1f7d5b2645eab57cb497a6d0cb languageName: node linkType: hard