diff --git a/.env.production.sample b/.env.production.sample index fa75a70c57..15bf9da4e0 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/.github/ISSUE_TEMPLATE/1.web_bug_report.yml b/.github/ISSUE_TEMPLATE/1.web_bug_report.yml index 20e27d103c..f897a7d7da 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 49d5f57209..a66f5c1076 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 0000000000..eeb74b160b --- /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 2cabcf61e0..7146b4f8a3 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/test-migrations.yml b/.github/workflows/test-migrations.yml index 6a0e67c58e..5b80fef037 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 3da53c1ae8..770cd72a1b 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -124,7 +124,6 @@ jobs: fail-fast: false matrix: ruby-version: - - '3.1' - '3.2' - '.ruby-version' steps: @@ -143,7 +142,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: | @@ -226,7 +225,6 @@ jobs: fail-fast: false matrix: ruby-version: - - '3.1' - '3.2' - '.ruby-version' steps: @@ -245,7 +243,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' @@ -305,7 +303,6 @@ jobs: fail-fast: false matrix: ruby-version: - - '3.1' - '3.2' - '.ruby-version' @@ -325,7 +322,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 @@ -422,7 +419,6 @@ jobs: fail-fast: false matrix: ruby-version: - - '3.1' - '3.2' - '.ruby-version' search-image: @@ -445,7 +441,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 10fef252a9..8b84b727be 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.18 +22.11 diff --git a/.rubocop.yml b/.rubocop.yml index 965f56f3e7..ebeed6ea49 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,7 +8,7 @@ AllCops: - lib/mastodon/migration_helpers.rb ExtraDetails: true NewCops: enable - TargetRubyVersion: 3.1 # Oldest supported ruby version + TargetRubyVersion: 3.2 # Oldest supported ruby version inherit_from: - .rubocop/layout.yml diff --git a/.ruby-version b/.ruby-version index fa7adc7ac7..9c25013dbb 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.5 +3.3.6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 566c474356..0fc5291d72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,7 +67,7 @@ The following changelog entries focus on changes visible to users, administrator ```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)\ diff --git a/Dockerfile b/Dockerfile index a5e35025ae..a6c7d46b57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,10 +12,10 @@ ARG BUILDPLATFORM=${BUILDPLATFORM} # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"] # renovate: datasource=docker depName=docker.io/ruby -ARG RUBY_VERSION="3.3.5" +ARG RUBY_VERSION="3.3.6" # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # renovate: datasource=node-version depName=node -ARG NODE_MAJOR_VERSION="20" +ARG NODE_MAJOR_VERSION="22" # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] ARG DEBIAN_VERSION="bookworm" # Node image to use for base image based on combined variables (ex: 20-bookworm-slim) @@ -191,7 +191,7 @@ FROM build AS libvips # libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"] # renovate: datasource=github-releases depName=libvips packageName=libvips/libvips -ARG VIPS_VERSION=8.15.3 +ARG VIPS_VERSION=8.16.0 # libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"] ARG VIPS_URL=https://github.com/libvips/libvips/releases/download diff --git a/Gemfile b/Gemfile index bcb19421ab..47506929b0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,12 @@ # frozen_string_literal: true source 'https://rubygems.org' -ruby '>= 3.1.0' +ruby '>= 3.2.0' gem 'propshaft' gem 'puma', '~> 6.3' gem 'rack', '~> 2.2.7' -gem 'rails', '~> 7.1.1' +gem 'rails', '~> 7.2.0' gem 'thor', '~> 1.2' gem 'dotenv' @@ -16,16 +16,16 @@ gem 'pghero' gem 'aws-sdk-s3', '~> 1.123', require: false gem 'blurhash', '~> 0.1' -gem 'fog-core', '<= 2.5.0' +gem 'fog-core', '<= 2.6.0' gem 'fog-openstack', '~> 1.0', require: false +gem 'jd-paperclip-azure', '~> 3.0', require: false gem 'kt-paperclip', '~> 7.2' -gem 'md-paperclip-azure', '~> 2.2', require: false gem 'ruby-vips', '~> 2.2', require: false gem 'active_model_serializers', '~> 0.10' gem 'addressable', '~> 2.8' gem 'bootsnap', '~> 1.18.0', require: false -gem 'browser', '< 6' # https://github.com/fnando/browser/issues/543 +gem 'browser' gem 'charlock_holmes', '~> 0.7.7' gem 'chewy', '~> 7.3' gem 'devise', '~> 4.9' @@ -47,13 +47,14 @@ gem 'color_diff', '~> 0.1' gem 'csv', '~> 3.2' gem 'discard', '~> 1.2' gem 'doorkeeper', '~> 5.6' +gem 'faraday-httpclient' gem 'fast_blank', '~> 1.0' gem 'fastimage' gem 'hiredis', '~> 0.6' gem 'htmlentities', '~> 4.3' gem 'http', '~> 5.2.0' gem 'http_accept_language', '~> 2.1' -gem 'httplog', '~> 1.7.0' +gem 'httplog', '~> 1.7.0', require: false gem 'i18n' gem 'idn-ruby', require: 'idn' gem 'inline_svg' @@ -61,7 +62,8 @@ gem 'irb', '~> 1.8' gem 'kaminari', '~> 1.2' gem 'link_header', '~> 0.0' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' -gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' +gem 'mime-types', '~> 3.6.0', require: 'mime/types/columnar' +gem 'mutex_m' gem 'nokogiri', '~> 1.15' gem 'oj', '~> 3.14' gem 'ox', '~> 2.14' @@ -111,8 +113,8 @@ group :opentelemetry do gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false - gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false - gem 'opentelemetry-instrumentation-rails', '~> 0.31.0', require: false + gem 'opentelemetry-instrumentation-rack', '~> 0.25.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.32.0', require: false gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false gem 'opentelemetry-sdk', '~> 1.4', require: false @@ -220,7 +222,7 @@ gem 'concurrent-ruby', require: false gem 'connection_pool', require: false gem 'xorcist', '~> 1.1' -gem 'net-http', '~> 0.4.0' +gem 'net-http', '~> 0.5.0' gem 'rubyzip', '~> 2.3' gem 'hcaptcha', '~> 7.1' diff --git a/Gemfile.lock b/Gemfile.lock index 4c9cfe828e..1888485af0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,51 +10,46 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) + actioncable (7.2.2) + actionpack (= 7.2.2) + activesupport (= 7.2.2) 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) - 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) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (7.2.2) + actionpack (= 7.2.2) + activejob (= 7.2.2) + activerecord (= 7.2.2) + activestorage (= 7.2.2) + activesupport (= 7.2.2) + mail (>= 2.8.0) + actionmailer (7.2.2) + actionpack (= 7.2.2) + actionview (= 7.2.2) + activejob (= 7.2.2) + activesupport (= 7.2.2) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.4) - actionview (= 7.1.4) - activesupport (= 7.1.4) + actionpack (7.2.2) + actionview (= 7.2.2) + activesupport (= 7.2.2) nokogiri (>= 1.8.5) racc - rack (>= 2.2.4) + rack (>= 2.2.4, < 3.2) rack-session (>= 1.0.1) 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) + useragent (~> 0.16) + actiontext (7.2.2) + actionpack (= 7.2.2) + activerecord (= 7.2.2) + activestorage (= 7.2.2) + activesupport (= 7.2.2) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.4) - activesupport (= 7.1.4) + actionview (7.2.2) + activesupport (= 7.2.2) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) @@ -64,31 +59,33 @@ 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.2.2) + activesupport (= 7.2.2) 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.2.2) + activesupport (= 7.2.2) + activerecord (7.2.2) + activemodel (= 7.2.2) + activesupport (= 7.2.2) 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.2.2) + actionpack (= 7.2.2) + activejob (= 7.2.2) + activerecord (= 7.2.2) + activesupport (= 7.2.2) marcel (~> 1.0) - activesupport (7.1.4) + activesupport (7.2.2) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) aes_key_wrap (1.1.0) @@ -100,32 +97,27 @@ GEM attr_required (1.0.2) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.983.0) - aws-sdk-core (3.209.1) + aws-partitions (1.1001.0) + aws-sdk-core (3.212.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.94.0) - aws-sdk-core (~> 3, >= 3.207.0) + aws-sdk-kms (1.95.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.167.0) - aws-sdk-core (~> 3, >= 3.207.0) + aws-sdk-s3 (1.170.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.10.0) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) - azure-storage-blob (2.0.3) - azure-storage-common (~> 2.0) - nokogiri (~> 1, >= 1.10.8) - azure-storage-common (2.0.4) - faraday (~> 1.0) - faraday_middleware (~> 1.0, >= 1.0.0.rc1) - net-http-persistent (~> 4.0) - nokogiri (~> 1, >= 1.10.8) + azure-blob (0.5.2) + rexml base64 (0.2.0) bcp47_spec (0.2.1) bcrypt (3.1.20) + benchmark (0.3.0) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -137,9 +129,9 @@ GEM blurhash (0.1.8) bootsnap (1.18.4) msgpack (~> 1.2) - brakeman (6.2.1) + brakeman (6.2.2) racc - browser (5.3.1) + browser (6.0.0) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, < 6) @@ -179,7 +171,7 @@ GEM bigdecimal rexml crass (1.0.6) - css_parser (1.19.0) + css_parser (1.19.1) addressable csv (3.3.0) database_cleaner-active_record (2.2.0) @@ -206,8 +198,8 @@ GEM devise (>= 4.0.0) rpam2 (~> 4.0) diff-lcs (1.5.1) - discard (1.3.0) - activerecord (>= 4.2, < 8) + discard (1.4.0) + activerecord (>= 4.2, < 9.0) docile (1.4.1) domain_name (0.6.20240107) doorkeeper (5.7.1) @@ -231,38 +223,21 @@ GEM erubi (1.13.0) et-orbi (1.2.11) tzinfo - excon (0.111.0) + excon (0.112.0) fabrication (2.31.0) - faker (3.4.2) + faker (3.5.1) i18n (>= 1.8.11, < 2) - faraday (1.10.3) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0) - faraday-multipart (~> 1.0) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - faraday-retry (~> 1.0) - ruby2_keywords (>= 0.0.4) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-multipart (1.0.4) - multipart-post (~> 2) - faraday-net_http (1.0.2) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - faraday-retry (1.0.3) - faraday_middleware (1.2.0) - faraday (~> 1.0) + faraday (2.12.0) + faraday-net_http (>= 2.0, < 3.4) + json + logger + faraday-httpclient (2.0.1) + httpclient (>= 2.2) + faraday-net_http (3.3.0) + net-http fast_blank (1.0.1) fastimage (2.3.1) - ffi (1.16.3) + ffi (1.17.0) ffi-compiler (1.3.2) ffi (>= 1.15.5) rake @@ -350,8 +325,12 @@ GEM irb (1.14.1) rdoc (>= 4.0.0) reline (>= 0.4.2) + jd-paperclip-azure (3.0.0) + addressable (~> 2.5) + azure-blob (~> 0.5.2) + hashie (~> 5.0) jmespath (1.6.2) - json (2.7.2) + json (2.7.4) json-canonicalization (1.0.0) json-jwt (1.15.3.1) activesupport (>= 4.2) @@ -366,7 +345,7 @@ GEM rack (>= 2.2, < 4) rdf (~> 3.3) rexml (~> 3.2) - json-ld-preloaded (3.3.0) + json-ld-preloaded (3.3.1) json-ld (~> 3.3) rdf (~> 3.3) json-schema (5.0.1) @@ -412,7 +391,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.22.0) + loofah (2.23.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -424,26 +403,20 @@ GEM mario-redis-lock (1.2.1) redis (>= 3.0.5) matrix (0.4.2) - md-paperclip-azure (2.2.0) - addressable (~> 2.5) - azure-storage-blob (~> 2.0.1) - hashie (~> 5.0) memory_profiler (1.1.0) - mime-types (3.5.2) + mime-types (3.6.0) + logger mime-types-data (~> 3.2015) - mime-types-data (3.2024.0820) + mime-types-data (3.2024.1001) mini_mime (1.1.5) mini_portile2 (2.8.7) minitest (5.25.1) - msgpack (1.7.2) + msgpack (1.7.3) multi_json (1.15.0) - multipart-post (2.4.1) mutex_m (0.2.0) - net-http (0.4.1) + net-http (0.5.0) uri - net-http-persistent (4.0.2) - connection_pool (~> 2.2) - net-imap (0.4.15) + net-imap (0.5.0) date net-protocol net-ldap (0.19.0) @@ -457,7 +430,7 @@ GEM nokogiri (1.16.7) mini_portile2 (~> 2.8.2) racc (~> 1.4) - oj (3.16.6) + oj (3.16.7) bigdecimal (>= 3.0) ostruct (>= 0.2) omniauth (2.1.2) @@ -503,7 +476,7 @@ GEM opentelemetry-semantic_conventions opentelemetry-helpers-sql-obfuscation (0.2.0) opentelemetry-common (~> 0.21) - opentelemetry-instrumentation-action_mailer (0.1.0) + opentelemetry-instrumentation-action_mailer (0.2.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) @@ -515,13 +488,13 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.1) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_job (0.7.7) + opentelemetry-instrumentation-active_job (0.7.8) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_model_serializers (0.20.2) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_record (0.7.3) + opentelemetry-instrumentation-active_record (0.8.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-active_support (0.6.0) @@ -553,16 +526,16 @@ GEM opentelemetry-api (~> 1.0) opentelemetry-helpers-sql-obfuscation opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rack (0.24.6) + opentelemetry-instrumentation-rack (0.25.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.31.2) + opentelemetry-instrumentation-rails (0.32.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-action_mailer (~> 0.1.0) + opentelemetry-instrumentation-action_mailer (~> 0.2.0) opentelemetry-instrumentation-action_pack (~> 0.9.0) opentelemetry-instrumentation-action_view (~> 0.7.0) opentelemetry-instrumentation-active_job (~> 0.7.0) - opentelemetry-instrumentation-active_record (~> 0.7.0) + opentelemetry-instrumentation-active_record (~> 0.8.0) opentelemetry-instrumentation-active_support (~> 0.6.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-redis (0.25.7) @@ -590,8 +563,8 @@ GEM parslet (2.0.0) pastel (0.8.0) tty-color (~> 0.5) - pg (1.5.8) - pghero (3.6.0) + pg (1.5.9) + pghero (3.6.1) activerecord (>= 6.1) premailer (1.27.0) addressable @@ -638,20 +611,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.2.2) + actioncable (= 7.2.2) + actionmailbox (= 7.2.2) + actionmailer (= 7.2.2) + actionpack (= 7.2.2) + actiontext (= 7.2.2) + actionview (= 7.2.2) + activejob (= 7.2.2) + activemodel (= 7.2.2) + activerecord (= 7.2.2) + activestorage (= 7.2.2) + activesupport (= 7.2.2) bundler (>= 1.15.0) - railties (= 7.1.4) + railties (= 7.2.2) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -663,13 +636,13 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - rails-i18n (7.0.9) + rails-i18n (7.0.10) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) - irb + railties (7.2.2) + actionpack (= 7.2.2) + activesupport (= 7.2.2) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -698,9 +671,9 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.8) + rexml (3.3.9) rotp (6.3.0) - rouge (4.3.0) + rouge (4.4.0) rpam2 (4.0.2) rqrcode (2.2.0) chunky_png (~> 1.0) @@ -710,14 +683,14 @@ GEM rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.1) + rspec-core (3.13.2) rspec-support (~> 3.13.0) - rspec-expectations (3.13.2) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-github (2.4.0) rspec-core (~> 3.0) - rspec-mocks (3.13.1) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-rails (7.0.1) @@ -751,17 +724,17 @@ GEM rubocop-performance (1.22.1) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.26.2) + rubocop-rails (2.27.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.52.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.1.0) + rubocop-rspec (3.2.0) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) rubocop-rspec (~> 3, >= 3.0.1) - ruby-prof (1.7.0) + ruby-prof (1.7.1) ruby-progressbar (1.13.0) ruby-saml (1.17.0) nokogiri (>= 1.13.10) @@ -769,7 +742,6 @@ GEM ruby-vips (2.2.2) ffi (~> 1.12) logger - ruby2_keywords (0.0.5) rubyzip (2.3.2) rufus-scheduler (3.9.1) fugit (~> 1.1, >= 1.1.6) @@ -781,7 +753,8 @@ GEM scenic (1.8.0) activerecord (>= 4.0.0) railties (>= 4.0.0) - selenium-webdriver (4.25.0) + securerandom (0.3.1) + selenium-webdriver (4.26.0) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -822,7 +795,7 @@ GEM stoplight (4.1.0) redlock (~> 1.0) stringio (3.1.1) - strong_migrations (2.0.0) + strong_migrations (2.0.2) activerecord (>= 6.1) swd (1.3.0) activesupport (>= 3) @@ -864,6 +837,7 @@ GEM unf_ext (0.0.9.1) unicode-display_width (2.6.0) uri (0.13.1) + useragent (0.16.10) validate_email (0.1.6) activemodel (>= 3.0) mail (>= 2.2.5) @@ -902,7 +876,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.18) + zeitwerk (2.7.1) PLATFORMS ruby @@ -917,7 +891,7 @@ DEPENDENCIES blurhash (~> 0.1) bootsnap (~> 1.18.0) brakeman (~> 6.0) - browser (< 6) + browser bundler-audit (~> 0.9) capybara (~> 3.39) charlock_holmes (~> 0.7.7) @@ -939,10 +913,11 @@ DEPENDENCIES email_spec fabrication (~> 2.30) faker (~> 3.2) + faraday-httpclient fast_blank (~> 1.0) fastimage flatware-rspec - fog-core (<= 2.5.0) + fog-core (<= 2.6.0) fog-openstack (~> 1.0) haml-rails (~> 2.0) haml_lint @@ -957,6 +932,7 @@ DEPENDENCIES idn-ruby inline_svg irb (~> 1.8) + jd-paperclip-azure (~> 3.0) json-ld json-ld-preloaded (~> 3.2) json-schema (~> 5.0) @@ -968,10 +944,10 @@ DEPENDENCIES lograge (~> 0.12) mail (~> 2.8) mario-redis-lock (~> 1.2) - md-paperclip-azure (~> 2.2) memory_profiler - mime-types (~> 3.5.0) - net-http (~> 0.4.0) + mime-types (~> 3.6.0) + mutex_m + net-http (~> 0.5.0) net-ldap (~> 0.18) nokogiri (~> 1.15) oj (~> 3.14) @@ -991,8 +967,8 @@ DEPENDENCIES opentelemetry-instrumentation-http_client (~> 0.22.3) opentelemetry-instrumentation-net_http (~> 0.22.4) opentelemetry-instrumentation-pg (~> 0.29.0) - opentelemetry-instrumentation-rack (~> 0.24.1) - opentelemetry-instrumentation-rails (~> 0.31.0) + opentelemetry-instrumentation-rack (~> 0.25.0) + opentelemetry-instrumentation-rails (~> 0.32.0) opentelemetry-instrumentation-redis (~> 0.25.3) opentelemetry-instrumentation-sidekiq (~> 0.25.2) opentelemetry-sdk (~> 1.4) @@ -1009,7 +985,7 @@ DEPENDENCIES rack-attack (~> 6.6) rack-cors (~> 2.0) rack-test (~> 2.1) - rails (~> 7.1.1) + rails (~> 7.2.0) rails-controller-testing (~> 1.0) rails-i18n (~> 7.0) rdf-normalize (~> 0.5) @@ -1057,7 +1033,7 @@ DEPENDENCIES xorcist (~> 1.1) RUBY VERSION - ruby 3.3.4p94 + ruby 3.3.5p100 BUNDLED WITH - 2.5.18 + 2.5.22 diff --git a/README.md b/README.md index 6f61b1f9cf..b0fc720aab 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre - **PostgreSQL** 12+ - **Redis** 4+ -- **Ruby** 3.1+ +- **Ruby** 3.2+ - **Node.js** 18+ The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, and **Scalingo**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. diff --git a/Rakefile b/Rakefile index e51cf0e17e..488c551fee 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,6 @@ # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require File.expand_path('config/application', __dir__) +require_relative 'config/application' Rails.application.load_tasks diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index b8baf64e1a..0c995edbf8 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -41,11 +41,11 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController end end - def outbox_url(**kwargs) + def outbox_url(**) if params[:account_username].present? - account_outbox_url(@account, **kwargs) + account_outbox_url(@account, **) else - instance_actor_outbox_url(**kwargs) + instance_actor_outbox_url(**) end end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index faa0a061a6..fe822d8c99 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -5,7 +5,7 @@ module Admin def index authorize :email_domain_block, :index? - @email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page]) + @email_domain_blocks = EmailDomainBlock.parents.includes(:children).order(id: :desc).page(params[:page]) @form = Form::EmailDomainBlockBatch.new end diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb index dabfe97655..614e2a32d0 100644 --- a/app/controllers/admin/invites_controller.rb +++ b/app/controllers/admin/invites_controller.rb @@ -32,7 +32,7 @@ module Admin def deactivate_all authorize :invite, :deactivate_all? - Invite.available.in_batches.update_all(expires_at: Time.now.utc) + Invite.available.in_batches.touch_all(:expires_at) redirect_to admin_invites_path end diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb index 83d68eba63..65eca11c7f 100644 --- a/app/controllers/admin/trends/links_controller.rb +++ b/app/controllers/admin/trends/links_controller.rb @@ -4,7 +4,7 @@ class Admin::Trends::LinksController < Admin::BaseController def index authorize :preview_card, :review? - @locales = PreviewCardTrend.pluck('distinct language') + @locales = PreviewCardTrend.locales @preview_cards = filtered_preview_cards.page(params[:page]) @form = Trends::PreviewCardBatch.new end diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb index 3d8b53ea8a..682fe70bb5 100644 --- a/app/controllers/admin/trends/statuses_controller.rb +++ b/app/controllers/admin/trends/statuses_controller.rb @@ -4,7 +4,7 @@ class Admin::Trends::StatusesController < Admin::BaseController def index authorize [:admin, :status], :review? - @locales = StatusTrend.pluck('distinct language') + @locales = StatusTrend.locales @statuses = filtered_statuses.page(params[:page]) @form = Trends::StatusBatch.new end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 28acaeea05..f7d3de7f94 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -106,8 +106,8 @@ class Api::V1::AccountsController < Api::BaseController 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) + def relationships(**) + AccountRelationshipsPresenter.new([@account], current_user.account_id, **) end def account_ids diff --git a/app/controllers/api/v1/annual_reports_controller.rb b/app/controllers/api/v1/annual_reports_controller.rb index 9bc8e68ac2..b1aee288dd 100644 --- a/app/controllers/api/v1/annual_reports_controller.rb +++ b/app/controllers/api/v1/annual_reports_controller.rb @@ -17,6 +17,17 @@ class Api::V1::AnnualReportsController < Api::BaseController relationships: @relationships end + def show + with_read_replica do + @presenter = AnnualReportsPresenter.new([@annual_report]) + @relationships = StatusRelationshipsPresenter.new(@presenter.statuses, current_account.id) + end + + render json: @presenter, + serializer: REST::AnnualReportsSerializer, + relationships: @relationships + end + def read @annual_report.view! render_empty diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb index 29a09fceef..4b44cfe531 100644 --- a/app/controllers/api/v1/follow_requests_controller.rb +++ b/app/controllers/api/v1/follow_requests_controller.rb @@ -28,8 +28,8 @@ class Api::V1::FollowRequestsController < Api::BaseController @account ||= Account.find(params[:id]) end - def relationships(**options) - AccountRelationshipsPresenter.new([account], current_user.account_id, **options) + def relationships(**) + AccountRelationshipsPresenter.new([account], current_user.account_id, **) end def load_accounts diff --git a/app/controllers/api/v1/statuses/translations_controller.rb b/app/controllers/api/v1/statuses/translations_controller.rb index 8cf495f78a..bd5cd9bb07 100644 --- a/app/controllers/api/v1/statuses/translations_controller.rb +++ b/app/controllers/api/v1/statuses/translations_controller.rb @@ -23,6 +23,6 @@ class Api::V1::Statuses::TranslationsController < Api::V1::Statuses::BaseControl 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/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index 167d16fc4d..f515961427 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Api::Web::PushSubscriptionsController < Api::Web::BaseController - before_action :require_user! + before_action :require_user!, except: :destroy before_action :set_push_subscription, only: :update before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions? after_action :update_session_with_subscription, only: :create @@ -17,6 +17,13 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer end + def destroy + push_subscription = ::Web::PushSubscription.find_by_token_for(:unsubscribe, params[:id]) + push_subscription&.destroy + + head 200 + end + private def active_session diff --git a/app/controllers/concerns/auth/captcha_concern.rb b/app/controllers/concerns/auth/captcha_concern.rb index cfd93978ce..c01da21249 100644 --- a/app/controllers/concerns/auth/captcha_concern.rb +++ b/app/controllers/concerns/auth/captcha_concern.rb @@ -10,7 +10,7 @@ module Auth::CaptchaConcern end def captcha_available? - ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present? + Rails.configuration.x.captcha.secret_key.present? && Rails.configuration.x.captcha.site_key.present? end def captcha_enabled? diff --git a/app/controllers/oauth/userinfo_controller.rb b/app/controllers/oauth/userinfo_controller.rb new file mode 100644 index 0000000000..e268b70dcc --- /dev/null +++ b/app/controllers/oauth/userinfo_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Oauth::UserinfoController < Api::BaseController + before_action -> { doorkeeper_authorize! :profile }, only: [:show] + before_action :require_user! + + def show + @account = current_account + render json: @account, serializer: OauthUserinfoSerializer + end +end diff --git a/app/helpers/admin/settings_helper.rb b/app/helpers/admin/settings_helper.rb index 6937331e1a..9b950d5a63 100644 --- a/app/helpers/admin/settings_helper.rb +++ b/app/helpers/admin/settings_helper.rb @@ -2,7 +2,7 @@ module Admin::SettingsHelper def captcha_available? - ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present? + Rails.configuration.x.captcha.secret_key.present? && Rails.configuration.x.captcha.site_key.present? end def login_activity_title(activity) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 08c34a2c0b..73c9eb6e1f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -120,18 +120,6 @@ module ApplicationHelper inline_svg_tag 'check.svg' end - def visibility_icon(status) - if status.public_visibility? - material_symbol('globe', title: I18n.t('statuses.visibilities.public')) - elsif status.unlisted_visibility? - material_symbol('lock_open', title: I18n.t('statuses.visibilities.unlisted')) - elsif status.private_visibility? || status.limited_visibility? - material_symbol('lock', title: I18n.t('statuses.visibilities.private')) - elsif status.direct_visibility? - material_symbol('alternate_email', title: I18n.t('statuses.visibilities.direct')) - end - end - def interrelationships_icon(relationships, account_id) if relationships.following[account_id] && relationships.followed_by[account_id] material_symbol('sync_alt', title: I18n.t('relationships.mutual'), class: 'active passive') @@ -245,18 +233,23 @@ module ApplicationHelper 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'] preload_pack_asset "locales/#{current_flavour}/#{I18n.locale}-json.js" if supported_locales.include?(I18n.locale.to_s) end - def flavoured_javascript_pack_tag(pack_name, **options) - javascript_pack_tag("flavours/#{current_flavour}/#{pack_name}", **options) + def flavoured_javascript_pack_tag(pack_name, **) + javascript_pack_tag("flavours/#{current_flavour}/#{pack_name}", **) end - def flavoured_stylesheet_pack_tag(pack_name, **options) - stylesheet_pack_tag("flavours/#{current_flavour}/#{pack_name}", **options) + def flavoured_stylesheet_pack_tag(pack_name, **) + stylesheet_pack_tag("flavours/#{current_flavour}/#{pack_name}", **) end def preload_signed_in_js_packs diff --git a/app/helpers/formatting_helper.rb b/app/helpers/formatting_helper.rb index f0d583bc54..b842aa1dc7 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 @@ -19,42 +27,33 @@ module FormattingHelper module_function :extract_status_plain_text def status_content_format(status) - html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []), content_type: status.content_type) + MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span| + span.add_attributes( + 'app.formatter.content.type' => 'status', + 'app.formatter.content.origin' => status.local? ? 'local' : 'remote' + ) + + html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []), content_type: status.content_type) + end 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 def account_bio_format(account) - html_aware_format(account.note, account.local?) + MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span| + span.add_attributes( + 'app.formatter.content.type' => 'account_bio', + 'app.formatter.content.origin' => account.local? ? 'local' : 'remote' + ) + + html_aware_format(account.note, account.local?) + end end def account_field_value_format(field, with_rel_me: true) @@ -64,4 +63,47 @@ module FormattingHelper 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 394202e39a..0a8ebcde54 100644 --- a/app/helpers/languages_helper.rb +++ b/app/helpers/languages_helper.rb @@ -162,7 +162,7 @@ module LanguagesHelper th: ['Thai', 'ไทย'].freeze, ti: ['Tigrinya', 'ትግርኛ'].freeze, tk: ['Turkmen', 'Türkmen'].freeze, - tl: ['Tagalog', 'Wikang Tagalog'].freeze, + tl: ['Tagalog', 'Tagalog'].freeze, tn: ['Tswana', 'Setswana'].freeze, to: ['Tonga', 'faka Tonga'].freeze, tr: ['Turkish', 'Türkçe'].freeze, diff --git a/app/helpers/media_component_helper.rb b/app/helpers/media_component_helper.rb index 60ccdd0835..269566528a 100644 --- a/app/helpers/media_component_helper.rb +++ b/app/helpers/media_component_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module MediaComponentHelper - def render_video_component(status, **options) + def render_video_component(status, **) video = status.ordered_media_attachments.first meta = video.file.meta || {} @@ -18,14 +18,14 @@ module MediaComponentHelper media: [ serialize_media_attachment(video), ].as_json, - }.merge(**options) + }.merge(**) react_component :video, component_params do render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } end end - def render_audio_component(status, **options) + def render_audio_component(status, **) audio = status.ordered_media_attachments.first meta = audio.file.meta || {} @@ -38,19 +38,19 @@ module MediaComponentHelper foregroundColor: meta.dig('colors', 'foreground'), accentColor: meta.dig('colors', 'accent'), duration: meta.dig('original', 'duration'), - }.merge(**options) + }.merge(**) react_component :audio, component_params do render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } end end - def render_media_gallery_component(status, **options) + def render_media_gallery_component(status, **) component_params = { sensitive: sensitive_viewer?(status, current_account), autoplay: prefers_autoplay?, media: status.ordered_media_attachments.map { |a| serialize_media_attachment(a).as_json }, - }.merge(**options) + }.merge(**) react_component :media_gallery, component_params do render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments } diff --git a/app/helpers/registration_helper.rb b/app/helpers/registration_helper.rb index ef5462ac88..002d167c05 100644 --- a/app/helpers/registration_helper.rb +++ b/app/helpers/registration_helper.rb @@ -16,6 +16,6 @@ module RegistrationHelper end def ip_blocked?(remote_ip) - IpBlock.where(severity: :sign_up_block).exists?(['ip >>= ?', remote_ip.to_s]) + IpBlock.severity_sign_up_block.containing(remote_ip.to_s).exists? end end diff --git a/app/helpers/routing_helper.rb b/app/helpers/routing_helper.rb index 15d988f64d..22efc5f092 100644 --- a/app/helpers/routing_helper.rb +++ b/app/helpers/routing_helper.rb @@ -14,8 +14,8 @@ module RoutingHelper end end - def full_asset_url(source, **options) - source = ActionController::Base.helpers.asset_url(source, **options) unless use_storage? + def full_asset_url(source, **) + source = ActionController::Base.helpers.asset_url(source, **) unless use_storage? URI.join(asset_host, source).to_s end @@ -24,12 +24,12 @@ module RoutingHelper Rails.configuration.action_controller.asset_host || root_url end - def frontend_asset_path(source, **options) - asset_pack_path("media/#{source}", **options) + def frontend_asset_path(source, **) + asset_pack_path("media/#{source}", **) end - def frontend_asset_url(source, **options) - full_asset_url(frontend_asset_path(source, **options)) + def frontend_asset_url(source, **) + full_asset_url(frontend_asset_path(source, **)) end def use_storage? diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb index bba6d64a47..9bbb03fd82 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/javascript/entrypoints/public.tsx b/app/javascript/entrypoints/public.tsx index d33e00d5da..c1e8418014 100644 --- a/app/javascript/entrypoints/public.tsx +++ b/app/javascript/entrypoints/public.tsx @@ -327,31 +327,24 @@ Rails.delegate(document, '.input-copy button', 'click', ({ target }) => { if (!input) return; - const oldReadOnly = input.readOnly; - - input.readOnly = false; - input.focus(); - input.select(); - input.setSelectionRange(0, input.value.length); - - try { - if (document.execCommand('copy')) { - input.blur(); - + navigator.clipboard + .writeText(input.value) + .then(() => { const parent = target.parentElement; - if (!parent) return; - parent.classList.add('copied'); + if (parent) { + parent.classList.add('copied'); - setTimeout(() => { - parent.classList.remove('copied'); - }, 700); - } - } catch (err) { - console.error(err); - } + setTimeout(() => { + parent.classList.remove('copied'); + }, 700); + } - input.readOnly = oldReadOnly; + return true; + }) + .catch((error: unknown) => { + console.error(error); + }); }); const toggleSidebar = () => { diff --git a/app/javascript/flavours/glitch/actions/notification_groups.ts b/app/javascript/flavours/glitch/actions/notification_groups.ts index e39c9d6846..f85dfac933 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,17 +70,19 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } -const supportedGroupedNotificationTypes = ['favourite', 'reblog']; +function selectNotificationGroupedTypes(state: RootState) { + const types: NotificationType[] = ['favourite', 'reblog']; -export function shouldGroupNotificationType(type: string) { - return supportedGroupedNotificationTypes.includes(type); + if (selectSettingsNotificationsGroupFollows(state)) types.push('follow'); + + return types; } export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + grouped_types: selectNotificationGroupedTypes(getState()), exclude_types: getExcludedTypes(getState()), }), ({ notifications, accounts, statuses }, { dispatch }) => { @@ -102,7 +106,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + grouped_types: selectNotificationGroupedTypes(getState()), max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -119,7 +123,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { return apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + 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 @@ -168,7 +172,10 @@ export const processNewNotificationForGroups = createAppAsyncThunk( dispatchAssociatedRecords(dispatch, [notification]); - return notification; + return { + notification, + groupedTypes: selectNotificationGroupedTypes(state), + }; }, ); diff --git a/app/javascript/flavours/glitch/api_types/notifications.ts b/app/javascript/flavours/glitch/api_types/notifications.ts index 0175bac0d1..1f3bc4d1eb 100644 --- a/app/javascript/flavours/glitch/api_types/notifications.ts +++ b/app/javascript/flavours/glitch/api_types/notifications.ts @@ -21,6 +21,7 @@ export const allNotificationTypes = [ 'admin.report', 'moderation_warning', 'severed_relationships', + 'annual_report', ]; export type NotificationWithStatusType = @@ -39,7 +40,8 @@ export type NotificationType = | 'moderation_warning' | 'severed_relationships' | 'admin.sign_up' - | 'admin.report'; + | 'admin.report' + | 'annual_report'; export interface BaseNotificationJSON { id: string; @@ -132,6 +134,15 @@ interface AccountRelationshipSeveranceNotificationJSON event: ApiAccountRelationshipSeveranceEventJSON; } +export interface ApiAnnualReportEventJSON { + year: string; +} + +interface AnnualReportNotificationGroupJSON extends BaseNotificationGroupJSON { + type: 'annual_report'; + annual_report: ApiAnnualReportEventJSON; +} + export type ApiNotificationJSON = | SimpleNotificationJSON | ReportNotificationJSON @@ -144,7 +155,8 @@ export type ApiNotificationGroupJSON = | ReportNotificationGroupJSON | AccountRelationshipSeveranceNotificationGroupJSON | NotificationGroupWithStatusJSON - | ModerationWarningNotificationGroupJSON; + | ModerationWarningNotificationGroupJSON + | AnnualReportNotificationGroupJSON; export interface ApiNotificationGroupsResultJSON { accounts: ApiAccountJSON[]; diff --git a/app/javascript/flavours/glitch/components/button.tsx b/app/javascript/flavours/glitch/components/button.tsx index 3e720f7cee..b349a83f2b 100644 --- a/app/javascript/flavours/glitch/components/button.tsx +++ b/app/javascript/flavours/glitch/components/button.tsx @@ -1,4 +1,4 @@ -import type { PropsWithChildren } from 'react'; +import type { PropsWithChildren, JSX } from 'react'; import { useCallback } from 'react'; import classNames from 'classnames'; diff --git a/app/javascript/flavours/glitch/components/content_warning.tsx b/app/javascript/flavours/glitch/components/content_warning.tsx index 82f9ca83ed..982365b039 100644 --- a/app/javascript/flavours/glitch/components/content_warning.tsx +++ b/app/javascript/flavours/glitch/components/content_warning.tsx @@ -1,6 +1,4 @@ -/* Significantly rewritten from upstream to keep the old design for now */ - -import { FormattedMessage } from 'react-intl'; +import { StatusBanner, BannerVariant } from './status_banner'; export const ContentWarning: React.FC<{ text: string; @@ -8,20 +6,12 @@ export const ContentWarning: React.FC<{ onClick?: () => void; icons?: React.ReactNode[]; }> = ({ text, expanded, onClick, icons }) => ( -

- {' '} - -

+ + {icons} +

+ ); diff --git a/app/javascript/flavours/glitch/components/filter_warning.tsx b/app/javascript/flavours/glitch/components/filter_warning.tsx index 4305e43038..5eaaac4ba3 100644 --- a/app/javascript/flavours/glitch/components/filter_warning.tsx +++ b/app/javascript/flavours/glitch/components/filter_warning.tsx @@ -10,13 +10,16 @@ export const FilterWarning: React.FC<{

{chunks}, + }} />

diff --git a/app/javascript/flavours/glitch/components/media_gallery.jsx b/app/javascript/flavours/glitch/components/media_gallery.jsx index f2f8b21e3b..46ff875ab6 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.jsx +++ b/app/javascript/flavours/glitch/components/media_gallery.jsx @@ -98,12 +98,12 @@ class Item extends PureComponent { height = 50; } - if (attachment.get('description')?.length > 0) { - badges.push(); - } - const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); + if (description?.length > 0) { + badges.push(); + } + if (attachment.get('type') === 'unknown') { return (
diff --git a/app/javascript/flavours/glitch/components/modal_root.jsx b/app/javascript/flavours/glitch/components/modal_root.jsx index 71b875cfee..bfe9efea06 100644 --- a/app/javascript/flavours/glitch/components/modal_root.jsx +++ b/app/javascript/flavours/glitch/components/modal_root.jsx @@ -13,11 +13,14 @@ class ModalRoot extends PureComponent { static propTypes = { children: PropTypes.node, onClose: PropTypes.func.isRequired, - backgroundColor: PropTypes.shape({ - r: PropTypes.number, - g: PropTypes.number, - b: PropTypes.number, - }), + backgroundColor: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ + r: PropTypes.number, + g: PropTypes.number, + b: PropTypes.number, + }), + ]), noEsc: PropTypes.bool, ignoreFocus: PropTypes.bool, ...WithOptionalRouterPropTypes, @@ -146,14 +149,17 @@ class ModalRoot extends PureComponent { let backgroundColor = null; - if (this.props.backgroundColor) { - backgroundColor = multiply({ ...this.props.backgroundColor, a: 1 }, { r: 0, g: 0, b: 0, a: 0.7 }); + if (this.props.backgroundColor && typeof this.props.backgroundColor === 'string') { + backgroundColor = this.props.backgroundColor; + } else if (this.props.backgroundColor) { + const darkenedColor = multiply({ ...this.props.backgroundColor, a: 1 }, { r: 0, g: 0, b: 0, a: 0.7 }); + backgroundColor = `rgb(${darkenedColor.r}, ${darkenedColor.g}, ${darkenedColor.b})`; } return (
-
+
{children}
diff --git a/app/javascript/flavours/glitch/components/poll.jsx b/app/javascript/flavours/glitch/components/poll.jsx index a4fb4b62d1..76fd93f14e 100644 --- a/app/javascript/flavours/glitch/components/poll.jsx +++ b/app/javascript/flavours/glitch/components/poll.jsx @@ -41,12 +41,14 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => { class Poll extends ImmutablePureComponent { static propTypes = { identity: identityContextPropShape, - poll: ImmutablePropTypes.map, + poll: ImmutablePropTypes.map.isRequired, + status: ImmutablePropTypes.map.isRequired, lang: PropTypes.string, intl: PropTypes.object.isRequired, disabled: PropTypes.bool, refresh: PropTypes.func, onVote: PropTypes.func, + onInteractionModal: PropTypes.func, }; state = { @@ -117,7 +119,11 @@ class Poll extends ImmutablePureComponent { return; } - this.props.onVote(Object.keys(this.state.selected)); + if (this.props.identity.signedIn) { + this.props.onVote(Object.keys(this.state.selected)); + } else { + this.props.onInteractionModal('vote', this.props.status); + } }; handleRefresh = () => { @@ -232,7 +238,7 @@ class Poll extends ImmutablePureComponent {
- {!showResults && } + {!showResults && } {!showResults && <> · } {showResults && !this.props.disabled && <> · } {votesCount} diff --git a/app/javascript/flavours/glitch/components/short_number.tsx b/app/javascript/flavours/glitch/components/short_number.tsx index a0b523aaad..37201a5e1d 100644 --- a/app/javascript/flavours/glitch/components/short_number.tsx +++ b/app/javascript/flavours/glitch/components/short_number.tsx @@ -1,4 +1,5 @@ import { memo } from 'react'; +import type { JSX } from 'react'; import { FormattedMessage, FormattedNumber } from 'react-intl'; diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index a2321e02cc..692c958c66 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -590,12 +590,15 @@ class Status extends ImmutablePureComponent { let prepend, rebloggedByText; + const matchedFilters = status.get('matched_filters'); + if (hidden) { return (
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} - {status.get('content')} + {status.get('spoiler_text').length > 0 && ({status.get('spoiler_text')})} + {isExpanded && {status.get('content')}}
); @@ -604,7 +607,6 @@ class Status extends ImmutablePureComponent { const connectUp = previousId && previousId === status.get('in_reply_to_id'); const connectToRoot = rootId && rootId === status.get('in_reply_to_id'); const connectReply = nextInReplyToId && nextInReplyToId === status.get('id'); - const matchedFilters = status.get('matched_filters'); if (this.state.forceFilter === undefined ? matchedFilters : this.state.forceFilter) { const minHandlers = this.props.muted ? {} : { @@ -655,7 +657,7 @@ 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) { + } else if (['image', 'gifv', 'unknown'].includes(status.getIn(['media_attachments', 0, 'type'])) || status.get('media_attachments').size > 1) { media.push( {Component => ( @@ -749,7 +751,7 @@ class Status extends ImmutablePureComponent { if (status.get('poll')) { const language = status.getIn(['translation', 'language']) || status.get('language'); - contentMedia.push(); + contentMedia.push(); contentMediaIcons.push('tasks'); } @@ -814,7 +816,8 @@ class Status extends ImmutablePureComponent { {(connectReply || connectUp || connectToRoot) &&
} {(!muted || !isCollapsed) && ( -
+ /* eslint-disable-next-line jsx-a11y/no-static-element-interactions */ +
void; }> = ({ children, variant, expanded, onClick }) => ( -
+ ) : variant === BannerVariant.Warning ? ( + ) : ( )} -
+ ); diff --git a/app/javascript/flavours/glitch/components/status_content.jsx b/app/javascript/flavours/glitch/components/status_content.jsx index a15a4df25a..9ee2e683a5 100644 --- a/app/javascript/flavours/glitch/components/status_content.jsx +++ b/app/javascript/flavours/glitch/components/status_content.jsx @@ -378,7 +378,7 @@ class StatusContent extends PureComponent { )).reduce((aggregate, item) => [...aggregate, item, ' '], []); let spoilerIcons = []; - if (hidden && mediaIcons) { + if (mediaIcons) { const mediaComponents = { 'link': LinkIcon, 'picture-o': ImageIcon, diff --git a/app/javascript/flavours/glitch/containers/poll_container.js b/app/javascript/flavours/glitch/containers/poll_container.js index e25dd06148..710bed45c5 100644 --- a/app/javascript/flavours/glitch/containers/poll_container.js +++ b/app/javascript/flavours/glitch/containers/poll_container.js @@ -2,6 +2,7 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; +import { openModal } from 'flavours/glitch/actions/modal'; import { fetchPoll, vote } from 'flavours/glitch/actions/polls'; import Poll from 'flavours/glitch/components/poll'; @@ -17,6 +18,17 @@ const mapDispatchToProps = (dispatch, { pollId }) => ({ onVote (choices) { dispatch(vote(pollId, choices)); }, + + onInteractionModal (type, status) { + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type, + accountId: status.getIn(['account', 'id']), + url: status.get('uri'), + }, + })); + } }); const mapStateToProps = (state, { pollId }) => ({ diff --git a/app/javascript/flavours/glitch/entrypoints/public.tsx b/app/javascript/flavours/glitch/entrypoints/public.tsx index 41c0e34396..e8b9825ac9 100644 --- a/app/javascript/flavours/glitch/entrypoints/public.tsx +++ b/app/javascript/flavours/glitch/entrypoints/public.tsx @@ -327,31 +327,24 @@ Rails.delegate(document, '.input-copy button', 'click', ({ target }) => { if (!input) return; - const oldReadOnly = input.readOnly; - - input.readOnly = false; - input.focus(); - input.select(); - input.setSelectionRange(0, input.value.length); - - try { - if (document.execCommand('copy')) { - input.blur(); - + navigator.clipboard + .writeText(input.value) + .then(() => { const parent = target.parentElement; - if (!parent) return; - parent.classList.add('copied'); + if (parent) { + parent.classList.add('copied'); - setTimeout(() => { - parent.classList.remove('copied'); - }, 700); - } - } catch (err) { - console.error(err); - } + setTimeout(() => { + parent.classList.remove('copied'); + }, 700); + } - input.readOnly = oldReadOnly; + return true; + }) + .catch((error: unknown) => { + console.error(error); + }); }); const toggleSidebar = () => { diff --git a/app/javascript/flavours/glitch/features/annual_report/archetype.tsx b/app/javascript/flavours/glitch/features/annual_report/archetype.tsx new file mode 100644 index 0000000000..604f401039 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/archetype.tsx @@ -0,0 +1,69 @@ +import { FormattedMessage } from 'react-intl'; + +import booster from '@/images/archetypes/booster.png'; +import lurker from '@/images/archetypes/lurker.png'; +import oracle from '@/images/archetypes/oracle.png'; +import pollster from '@/images/archetypes/pollster.png'; +import replier from '@/images/archetypes/replier.png'; +import type { Archetype as ArchetypeData } from 'flavours/glitch/models/annual_report'; + +export const Archetype: React.FC<{ + data: ArchetypeData; +}> = ({ data }) => { + let illustration, label; + + switch (data) { + case 'booster': + illustration = booster; + label = ( + + ); + break; + case 'replier': + illustration = replier; + label = ( + + ); + break; + case 'pollster': + illustration = pollster; + label = ( + + ); + break; + case 'lurker': + illustration = lurker; + label = ( + + ); + break; + case 'oracle': + illustration = oracle; + label = ( + + ); + break; + } + + return ( +
+
{label}
+ +
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/followers.tsx b/app/javascript/flavours/glitch/features/annual_report/followers.tsx new file mode 100644 index 0000000000..e5238705d7 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/followers.tsx @@ -0,0 +1,69 @@ +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import { Sparklines, SparklinesCurve } from 'react-sparklines'; + +import { ShortNumber } from 'flavours/glitch/components/short_number'; +import type { TimeSeriesMonth } from 'flavours/glitch/models/annual_report'; + +export const Followers: React.FC<{ + data: TimeSeriesMonth[]; + total?: number; +}> = ({ data, total }) => { + const change = data.reduce((sum, item) => sum + item.followers, 0); + + const cumulativeGraph = data.reduce( + (newData, item) => [ + ...newData, + item.followers + (newData[newData.length - 1] ?? 0), + ], + [0], + ); + + return ( +
+ + + + + + + + + + + + + +
+
+ {change > -1 ? '+' : '-'} + +
+ +
+ + + +
+ }} + /> +
+
+
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/highlighted_post.tsx b/app/javascript/flavours/glitch/features/annual_report/highlighted_post.tsx new file mode 100644 index 0000000000..e66752b53e --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/highlighted_post.tsx @@ -0,0 +1,109 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return, + @typescript-eslint/no-explicit-any, + @typescript-eslint/no-unsafe-assignment */ + +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { toggleStatusSpoilers } from 'flavours/glitch/actions/statuses'; +import { DetailedStatus } from 'flavours/glitch/features/status/components/detailed_status'; +import { me } from 'flavours/glitch/initial_state'; +import type { TopStatuses } from 'flavours/glitch/models/annual_report'; +import { + makeGetStatus, + makeGetPictureInPicture, +} from 'flavours/glitch/selectors'; +import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; + +const getStatus = makeGetStatus() as unknown as (arg0: any, arg1: any) => any; +const getPictureInPicture = makeGetPictureInPicture() as unknown as ( + arg0: any, + arg1: any, +) => any; + +export const HighlightedPost: React.FC<{ + data: TopStatuses; +}> = ({ data }) => { + let statusId, label; + + if (data.by_reblogs) { + statusId = data.by_reblogs; + label = ( + + ); + } else if (data.by_favourites) { + statusId = data.by_favourites; + label = ( + + ); + } else { + statusId = data.by_replies; + label = ( + + ); + } + + const dispatch = useAppDispatch(); + const domain = useAppSelector((state) => state.meta.get('domain')); + const status = useAppSelector((state) => + statusId ? getStatus(state, { id: statusId }) : undefined, + ); + const pictureInPicture = useAppSelector((state) => + statusId ? getPictureInPicture(state, { id: statusId }) : undefined, + ); + const account = useAppSelector((state) => + me ? state.accounts.get(me) : undefined, + ); + + const handleToggleHidden = useCallback(() => { + dispatch(toggleStatusSpoilers(statusId)); + }, [dispatch, statusId]); + + if (!status) { + return ( +
+ ); + } + + const displayName = ( + + + + ), + }} + /> + + {label} + + ); + + return ( +
+ +
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/index.tsx b/app/javascript/flavours/glitch/features/annual_report/index.tsx new file mode 100644 index 0000000000..0c737934b4 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/index.tsx @@ -0,0 +1,99 @@ +import { useState, useEffect } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { + importFetchedStatuses, + importFetchedAccounts, +} from 'flavours/glitch/actions/importer'; +import { apiRequestGet, apiRequestPost } from 'flavours/glitch/api'; +import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator'; +import { me } from 'flavours/glitch/initial_state'; +import type { Account } from 'flavours/glitch/models/account'; +import type { AnnualReport as AnnualReportData } from 'flavours/glitch/models/annual_report'; +import type { Status } from 'flavours/glitch/models/status'; +import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; + +import { Archetype } from './archetype'; +import { Followers } from './followers'; +import { HighlightedPost } from './highlighted_post'; +import { MostUsedHashtag } from './most_used_hashtag'; +import { NewPosts } from './new_posts'; +import { Percentile } from './percentile'; + +interface AnnualReportResponse { + annual_reports: AnnualReportData[]; + accounts: Account[]; + statuses: Status[]; +} + +export const AnnualReport: React.FC<{ + year: string; +}> = ({ year }) => { + const [response, setResponse] = useState(null); + const [loading, setLoading] = useState(false); + const currentAccount = useAppSelector((state) => + me ? state.accounts.get(me) : undefined, + ); + const dispatch = useAppDispatch(); + + useEffect(() => { + setLoading(true); + + apiRequestGet(`v1/annual_reports/${year}`) + .then((data) => { + dispatch(importFetchedStatuses(data.statuses)); + dispatch(importFetchedAccounts(data.accounts)); + + setResponse(data); + setLoading(false); + + return apiRequestPost(`v1/annual_reports/${year}/read`); + }) + .catch(() => { + setLoading(false); + }); + }, [dispatch, year, setResponse, setLoading]); + + if (loading) { + return ; + } + + const report = response?.annual_reports[0]; + + if (!report) { + return null; + } + + return ( +
+
+

+ +

+

+ +

+
+ +
+ + + + + + +
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/most_used_app.tsx b/app/javascript/flavours/glitch/features/annual_report/most_used_app.tsx new file mode 100644 index 0000000000..f78a02b296 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/most_used_app.tsx @@ -0,0 +1,29 @@ +import { FormattedMessage } from 'react-intl'; + +import type { NameAndCount } from 'flavours/glitch/models/annual_report'; + +export const MostUsedApp: React.FC<{ + data: NameAndCount[]; +}> = ({ data }) => { + const app = data[0]; + + if (!app) { + return ( +
+ ); + } + + return ( +
+
+ {app.name} +
+
+ +
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/most_used_hashtag.tsx b/app/javascript/flavours/glitch/features/annual_report/most_used_hashtag.tsx new file mode 100644 index 0000000000..a6d5e08fe1 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/most_used_hashtag.tsx @@ -0,0 +1,29 @@ +import { FormattedMessage } from 'react-intl'; + +import type { NameAndCount } from 'flavours/glitch/models/annual_report'; + +export const MostUsedHashtag: React.FC<{ + data: NameAndCount[]; +}> = ({ data }) => { + const hashtag = data[0]; + + if (!hashtag) { + return ( +
+ ); + } + + return ( +
+
+ #{hashtag.name} +
+
+ +
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/new_posts.tsx b/app/javascript/flavours/glitch/features/annual_report/new_posts.tsx new file mode 100644 index 0000000000..4ca286debb --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/new_posts.tsx @@ -0,0 +1,53 @@ +import { FormattedNumber, FormattedMessage } from 'react-intl'; + +import ChatBubbleIcon from '@/material-icons/400-24px/chat_bubble.svg?react'; +import type { TimeSeriesMonth } from 'flavours/glitch/models/annual_report'; + +export const NewPosts: React.FC<{ + data: TimeSeriesMonth[]; +}> = ({ data }) => { + const posts = data.reduce((sum, item) => sum + item.statuses, 0); + + return ( +
+ + + + + + + + + + + +
+ +
+
+ +
+
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/annual_report/percentile.tsx b/app/javascript/flavours/glitch/features/annual_report/percentile.tsx new file mode 100644 index 0000000000..322171ba21 --- /dev/null +++ b/app/javascript/flavours/glitch/features/annual_report/percentile.tsx @@ -0,0 +1,53 @@ +/* eslint-disable react/jsx-no-useless-fragment */ +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import type { Percentiles } from 'flavours/glitch/models/annual_report'; + +export const Percentile: React.FC<{ + data: Percentiles; +}> = ({ data }) => { + const percentile = data.statuses; + + return ( +
+ ( +
+ {str} +
+ ), + percentage: () => ( +
+ +
+ ), + bottomLabel: (str) => ( +
+
+ {str} +
+ + {percentile < 6 && ( +
+ +
+ )} +
+ ), + }} + > + {(message) => <>{message}} +
+
+ ); +}; 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 a13081e82b..b6200106dd 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 361522d7b4..49d66dfbb4 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/follow_requests/index.jsx b/app/javascript/flavours/glitch/features/follow_requests/index.jsx index a8f40a31d0..7d651f2ca6 100644 --- a/app/javascript/flavours/glitch/features/follow_requests/index.jsx +++ b/app/javascript/flavours/glitch/features/follow_requests/index.jsx @@ -68,7 +68,7 @@ class FollowRequests extends ImmutablePureComponent { ); return ( - +
+ +
+ +
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 3c4c4b30ca..3e0da03e33 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_annual_report.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_annual_report.tsx new file mode 100644 index 0000000000..42754d1490 --- /dev/null +++ b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_annual_report.tsx @@ -0,0 +1,59 @@ +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import classNames from 'classnames'; + +import CelebrationIcon from '@/material-icons/400-24px/celebration.svg?react'; +import { openModal } from 'flavours/glitch/actions/modal'; +import { Icon } from 'flavours/glitch/components/icon'; +import type { NotificationGroupAnnualReport } from 'flavours/glitch/models/notification_group'; +import { useAppDispatch } from 'flavours/glitch/store'; + +export const NotificationAnnualReport: React.FC<{ + notification: NotificationGroupAnnualReport; + unread: boolean; +}> = ({ notification: { annualReport }, unread }) => { + const dispatch = useAppDispatch(); + const year = annualReport.year; + + const handleClick = useCallback(() => { + dispatch( + openModal({ + modalType: 'ANNUAL_REPORT', + modalProps: { year }, + }), + ); + }, [dispatch, year]); + + return ( +
+
+ +
+ +
+

+ +

+ +
+
+ ); +}; 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 f154e801fb..068f56cd18 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,21 @@ +import type { JSX } from 'react'; + 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 +53,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 +79,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_group.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group.tsx index d43320f394..800df28ced 100644 --- a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group.tsx +++ b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group.tsx @@ -9,6 +9,7 @@ import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; import { NotificationAdminReport } from './notification_admin_report'; import { NotificationAdminSignUp } from './notification_admin_sign_up'; +import { NotificationAnnualReport } from './notification_annual_report'; import { NotificationFavourite } from './notification_favourite'; import { NotificationFollow } from './notification_follow'; import { NotificationFollowRequest } from './notification_follow_request'; @@ -152,6 +153,14 @@ export const NotificationGroup: React.FC<{ /> ); break; + case 'annual_report': + content = ( + + ); + break; default: return null; } diff --git a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group_with_status.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group_with_status.tsx index 99045fa53b..5be3791161 100644 --- a/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group_with_status.tsx +++ b/app/javascript/flavours/glitch/features/notifications_v2/components/notification_group_with_status.tsx @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import type { JSX } from 'react'; import classNames from 'classnames'; 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 b57f882a74..2ddbed77ff 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 e1edd9a9a2..3028106c96 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.tsx @@ -54,6 +54,7 @@ export const DetailedStatus: React.FC<{ domain: string; showMedia?: boolean; withLogo?: boolean; + overrideDisplayName?: React.ReactNode; pictureInPicture: any; onToggleHidden?: (status: any) => void; onToggleMediaVisibility?: () => void; @@ -70,6 +71,7 @@ export const DetailedStatus: React.FC<{ domain, showMedia, withLogo, + overrideDisplayName, pictureInPicture, onToggleMediaVisibility, onToggleHidden, @@ -204,7 +206,7 @@ export const DetailedStatus: React.FC<{ ) { media.push(); } else if ( - ['image', 'gifv'].includes( + ['image', 'gifv', 'unknown'].includes( status.getIn(['media_attachments', 0, 'type']) as string, ) || status.get('media_attachments').size > 1 @@ -297,6 +299,7 @@ export const DetailedStatus: React.FC<{ , ); @@ -385,7 +388,11 @@ export const DetailedStatus: React.FC<{
- + + {overrideDisplayName ?? ( + + )} + {withLogo && ( <>
diff --git a/app/javascript/flavours/glitch/features/ui/components/annual_report_modal.tsx b/app/javascript/flavours/glitch/features/ui/components/annual_report_modal.tsx new file mode 100644 index 0000000000..b7f5db04ac --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/components/annual_report_modal.tsx @@ -0,0 +1,21 @@ +import { useEffect } from 'react'; + +import { AnnualReport } from 'flavours/glitch/features/annual_report'; + +const AnnualReportModal: React.FC<{ + year: string; + onChangeBackgroundColor: (arg0: string) => void; +}> = ({ year, onChangeBackgroundColor }) => { + useEffect(() => { + onChangeBackgroundColor('var(--indigo-1)'); + }, [onChangeBackgroundColor]); + + return ( +
+ +
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default AnnualReportModal; diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx index 83345905be..506cccfbb2 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx @@ -20,6 +20,7 @@ import { SubscribedLanguagesModal, ClosedRegistrationsModal, IgnoreNotificationsModal, + AnnualReportModal, } from 'flavours/glitch/features/ui/util/async-components'; import { getScrollbarWidth } from 'flavours/glitch/utils/scrollbar'; @@ -82,6 +83,7 @@ export const MODAL_COMPONENTS = { 'INTERACTION': InteractionModal, 'CLOSED_REGISTRATIONS': ClosedRegistrationsModal, 'IGNORE_NOTIFICATIONS': IgnoreNotificationsModal, + 'ANNUAL_REPORT': AnnualReportModal, }; export default class ModalRoot extends PureComponent { 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 e208f12173..2e944151bf 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/util/async-components.js b/app/javascript/flavours/glitch/features/ui/util/async-components.js index c7f2e6cff9..1354c21f09 100644 --- a/app/javascript/flavours/glitch/features/ui/util/async-components.js +++ b/app/javascript/flavours/glitch/features/ui/util/async-components.js @@ -229,3 +229,7 @@ export function NotificationRequest () { export function LinkTimeline () { return import(/*webpackChunkName: "features/glitch/link_timeline" */'../../link_timeline'); } + +export function AnnualReportModal () { + return import(/*webpackChunkName: "flavours/glitch/async/modals/annual_report_modal" */'../components/annual_report_modal'); +} diff --git a/app/javascript/flavours/glitch/locales/de.json b/app/javascript/flavours/glitch/locales/de.json index 62a68fd47c..14d9be9615 100644 --- a/app/javascript/flavours/glitch/locales/de.json +++ b/app/javascript/flavours/glitch/locales/de.json @@ -154,7 +154,5 @@ "status.is_poll": "Dieser Toot ist eine Umfrage", "status.local_only": "Nur auf deiner Instanz sichtbar", "status.show_filter_reason": "Trotzdem anzeigen", - "status.show_less": "Weniger anzeigen", - "status.show_more": "Mehr anzeigen", "status.uncollapse": "Ausklappen" } diff --git a/app/javascript/flavours/glitch/locales/en.json b/app/javascript/flavours/glitch/locales/en.json index 937c3fdeb7..9a0e49cdd0 100644 --- a/app/javascript/flavours/glitch/locales/en.json +++ b/app/javascript/flavours/glitch/locales/en.json @@ -161,7 +161,5 @@ "status.local_only": "Only visible from your instance", "status.react": "React", "status.show_filter_reason": "Show anyway", - "status.show_less": "Show less", - "status.show_more": "Show more", "status.uncollapse": "Uncollapse" } diff --git a/app/javascript/flavours/glitch/locales/es-AR.json b/app/javascript/flavours/glitch/locales/es-AR.json index 8153c773ce..de7617a31d 100644 --- a/app/javascript/flavours/glitch/locales/es-AR.json +++ b/app/javascript/flavours/glitch/locales/es-AR.json @@ -154,7 +154,5 @@ "status.is_poll": "Esta publicación es una encuesta", "status.local_only": "Sólo visible para tu instancia", "status.show_filter_reason": "Mostrar de todos modos", - "status.show_less": "Mostrar menos", - "status.show_more": "Mostrar más", "status.uncollapse": "Descolapsar" } diff --git a/app/javascript/flavours/glitch/locales/ko.json b/app/javascript/flavours/glitch/locales/ko.json index e75aec85c3..31539ae1f5 100644 --- a/app/javascript/flavours/glitch/locales/ko.json +++ b/app/javascript/flavours/glitch/locales/ko.json @@ -154,7 +154,5 @@ "status.is_poll": "이 글은 설문입니다", "status.local_only": "당신의 서버에서만 보입니다", "status.show_filter_reason": "그냥 표시하기", - "status.show_less": "접기", - "status.show_more": "더보기", "status.uncollapse": "펼치기" } diff --git a/app/javascript/flavours/glitch/locales/ru.json b/app/javascript/flavours/glitch/locales/ru.json index 6c9355ae11..7ac02de1e3 100644 --- a/app/javascript/flavours/glitch/locales/ru.json +++ b/app/javascript/flavours/glitch/locales/ru.json @@ -1,5 +1,88 @@ { - "about.fork_disclaimer": "Glitch-soc - это бесплатное программное обеспечение с открытым исходным кодом, обращенное от Mastodon.", + "about.fork_disclaimer": "Glitch-soc — это свободное программное обеспечение с открытым исходным кодом, ответвлённое от Mastodon.", + "account.follows": "Подписки", + "account.follows_you": "Подписан(а) на вас", + "account.suspended_disclaimer_full": "Этот пользователь был заблокирован модератором.", + "boost_modal.missing_description": "Этот пост содержит медиафайлы без описания", + "column.favourited_by": "Добавили в избранное", + "column.reblogged_by": "Продвинули", + "column_header.profile": "Профиль", + "column_subheading.lists": "Списки", + "column_subheading.navigation": "Навигация", + "compose.attach.doodle": "Нарисовать что-нибудь", + "compose.change_federation": "Изменить настройки федерации", + "compose.content-type.html": "HTML", + "compose.content-type.markdown": "Markdown", + "compose.content-type.plain": "Простой текст", + "compose.disable_threaded_mode": "Отключить режим треда", + "compose.enable_threaded_mode": "Включить режим треда", + "confirmation_modal.do_not_ask_again": "Больше не спрашивать подтверждение", + "confirmations.deprecated_settings.confirm": "Использовать настройки Mastodon", + "confirmations.missing_media_description.confirm": "Всё равно опубликовать", + "direct.group_by_conversations": "Группировать по перепискам", + "endorsed_accounts_editor.endorsed_accounts": "Рекомендованные аккаунты", + "favourite_modal.favourite": "Добавить пост в избранное?", + "federation.federated.long": "Разрешить делиться этим постом с другими серверами", + "federation.local_only.long": "Запретить делиться этим постом с другими серверами", + "home.column_settings.advanced": "Продвинутые настройки", + "home.column_settings.filter_regex": "Фильтр по регулярным выражениям", + "keyboard_shortcuts.bookmark": "добавить закладку", + "keyboard_shortcuts.toggle_collapse": "свернуть/развернуть пост", + "moved_to_warning": "Этот аккаунт переехал на {moved_to_link}, и скорее всего не принимает новых подписчиков.", + "navigation_bar.app_settings": "Настройки приложения", + "navigation_bar.keyboard_shortcuts": "Сочетания клавиш", + "notification.markForDeletion": "Отметить для удаления", + "notification_purge.btn_all": "Выбрать все", + "notification_purge.btn_apply": "Удалить выбранное", + "notification_purge.btn_invert": "Инвертировать выбор", + "notification_purge.btn_none": "Отменить выбор", + "notification_purge.start": "Войти в режим очистки уведомлений", + "notifications.column_settings.filter_bar.show_bar": "Показать панель фильтров", + "notifications.marked_clear": "Удалить выбранные уведомления", + "notifications.marked_clear_confirmation": "Вы уверены, что хотите безвозвратно удалить все выбранные уведомления?", + "settings.auto_collapse": "Сворачивать автоматически", + "settings.auto_collapse_all": "Всё", + "settings.auto_collapse_height": "Высота (в пикселях) для того, чтобы пост считался длинным", + "settings.auto_collapse_lengthy": "Длинные посты", + "settings.auto_collapse_media": "Посты с медиафайлами", + "settings.auto_collapse_notifications": "Уведомления", + "settings.auto_collapse_reblogs": "Продвижения", + "settings.auto_collapse_replies": "Ответы", + "settings.close": "Закрыть", + "settings.collapsed_statuses": "Сворачивание постов", + "settings.compose_box_opts": "Форма постинга", "settings.content_warnings": "Content warnings", - "settings.preferences": "Preferences" + "settings.content_warnings.regexp": "Регулярное выражение", + "settings.content_warnings_unfold_opts": "Автоматическое раскрытие", + "settings.deprecated_setting": "Эта опция теперь может быть включена в {settings_page_link} Mastodon", + "settings.enable_collapsed": "Включить сворачивание постов", + "settings.general": "Общие", + "settings.hicolor_privacy_icons": "Цветные значки публичности поста", + "settings.hicolor_privacy_icons.hint": "Отображать значки публичности поста в ярких и различимых цветах", + "settings.media": "Медиафайлы", + "settings.notifications.favicon_badge": "Индикатор уведомлений на иконке сайта", + "settings.notifications_opts": "Опции уведомлений", + "settings.pop_in_left": "Слева", + "settings.pop_in_player": "Включить плавающий плеер", + "settings.pop_in_position": "Расположение плавающего плеера:", + "settings.pop_in_right": "Справа", + "settings.preferences": "Preferences", + "settings.shared_settings_link": "настройках пользователя", + "settings.show_reply_counter": "Показывать приблизительное число ответов", + "settings.side_arm": "Дополнительная кнопка постинга:", + "settings.side_arm.none": "Нет", + "settings.side_arm_reply_mode": "При ответе на пост дополнительная кнопка постинга должна:", + "settings.status_icons": "Значки постов", + "settings.status_icons_language": "Индикатор языка", + "settings.status_icons_local_only": "Индикатор нефедерируемого поста", + "settings.status_icons_media": "Индикаторы медиафайлов и опросов", + "settings.status_icons_reply": "Индикатор ответа", + "settings.status_icons_visibility": "Индикатор публичности поста", + "settings.tag_misleading_links": "Помечать обманчивые ссылки", + "status.collapse": "Свернуть", + "status.hide": "Скрыть пост", + "status.in_reply_to": "Этот пост является ответом", + "status.is_poll": "Этот пост содержит опрос", + "status.show_filter_reason": "Всё равно показать", + "status.uncollapse": "Развернуть" } diff --git a/app/javascript/flavours/glitch/locales/zh-CN.json b/app/javascript/flavours/glitch/locales/zh-CN.json index 8cdb2c89a4..50bcdc0161 100644 --- a/app/javascript/flavours/glitch/locales/zh-CN.json +++ b/app/javascript/flavours/glitch/locales/zh-CN.json @@ -153,7 +153,5 @@ "status.is_poll": "此嘟文是投票", "status.local_only": "此嘟文仅本站可见", "status.show_filter_reason": "仍然显示", - "status.show_less": "部分显示", - "status.show_more": "完全显示", "status.uncollapse": "展开" } diff --git a/app/javascript/flavours/glitch/models/annual_report.ts b/app/javascript/flavours/glitch/models/annual_report.ts new file mode 100644 index 0000000000..c0a101e6c8 --- /dev/null +++ b/app/javascript/flavours/glitch/models/annual_report.ts @@ -0,0 +1,44 @@ +export interface Percentiles { + followers: number; + statuses: number; +} + +export interface NameAndCount { + name: string; + count: number; +} + +export interface TimeSeriesMonth { + month: number; + statuses: number; + following: number; + followers: number; +} + +export interface TopStatuses { + by_reblogs: number; + by_favourites: number; + by_replies: number; +} + +export type Archetype = + | 'lurker' + | 'booster' + | 'pollster' + | 'replier' + | 'oracle'; + +interface AnnualReportV1 { + most_used_apps: NameAndCount[]; + percentiles: Percentiles; + top_hashtags: NameAndCount[]; + top_statuses: TopStatuses; + time_series: TimeSeriesMonth[]; + archetype: Archetype; +} + +export interface AnnualReport { + year: number; + schema_version: number; + data: AnnualReportV1; +} diff --git a/app/javascript/flavours/glitch/models/notification_group.ts b/app/javascript/flavours/glitch/models/notification_group.ts index 13681f88df..2b8a188df9 100644 --- a/app/javascript/flavours/glitch/models/notification_group.ts +++ b/app/javascript/flavours/glitch/models/notification_group.ts @@ -1,6 +1,7 @@ import type { ApiAccountRelationshipSeveranceEventJSON, ApiAccountWarningJSON, + ApiAnnualReportEventJSON, BaseNotificationGroupJSON, ApiNotificationGroupJSON, ApiNotificationJSON, @@ -66,6 +67,12 @@ export interface NotificationGroupSeveredRelationships event: AccountRelationshipSeveranceEvent; } +type AnnualReportEvent = ApiAnnualReportEventJSON; +export interface NotificationGroupAnnualReport + extends BaseNotification<'annual_report'> { + annualReport: AnnualReportEvent; +} + interface Report extends Omit { targetAccountId: string; } @@ -88,7 +95,8 @@ export type NotificationGroup = | NotificationGroupModerationWarning | NotificationGroupSeveredRelationships | NotificationGroupAdminSignUp - | NotificationGroupAdminReport; + | NotificationGroupAdminReport + | NotificationGroupAnnualReport; function createReportFromJSON(reportJSON: ApiReportJSON): Report { const { target_account, ...report } = reportJSON; @@ -114,6 +122,12 @@ function createAccountRelationshipSeveranceEventFromJSON( return eventJson; } +function createAnnualReportEventFromJSON( + eventJson: ApiAnnualReportEventJSON, +): AnnualReportEvent { + return eventJson; +} + export function createNotificationGroupFromJSON( groupJson: ApiNotificationGroupJSON, ): NotificationGroup { @@ -148,7 +162,6 @@ export function createNotificationGroupFromJSON( event: createAccountRelationshipSeveranceEventFromJSON(group.event), sampleAccountIds, }; - case 'moderation_warning': { const { moderation_warning, ...groupWithoutModerationWarning } = group; return { @@ -157,6 +170,14 @@ export function createNotificationGroupFromJSON( sampleAccountIds, }; } + case 'annual_report': { + const { annual_report, ...groupWithoutAnnualReport } = group; + return { + ...groupWithoutAnnualReport, + annualReport: createAnnualReportEventFromJSON(annual_report), + sampleAccountIds, + }; + } default: return { sampleAccountIds, diff --git a/app/javascript/flavours/glitch/reducers/accounts.ts b/app/javascript/flavours/glitch/reducers/accounts.ts index c9d7b5fe12..cbdfbcd832 100644 --- a/app/javascript/flavours/glitch/reducers/accounts.ts +++ b/app/javascript/flavours/glitch/reducers/accounts.ts @@ -57,7 +57,10 @@ export const accountsReducer: Reducer = ( return state.setIn([action.payload.id, 'hidden'], false); else if (importAccounts.match(action)) return normalizeAccounts(state, action.payload.accounts); - else if (followAccountSuccess.match(action)) { + else if ( + followAccountSuccess.match(action) && + !action.payload.alreadyFollowing + ) { return state .update(action.payload.relationship.id, (account) => account?.update('followers_count', (n) => n + 1), diff --git a/app/javascript/flavours/glitch/reducers/notification_groups.ts b/app/javascript/flavours/glitch/reducers/notification_groups.ts index d1dacc7964..09c0c5c3ee 100644 --- a/app/javascript/flavours/glitch/reducers/notification_groups.ts +++ b/app/javascript/flavours/glitch/reducers/notification_groups.ts @@ -21,7 +21,6 @@ import { unmountNotifications, refreshStaleNotificationGroups, pollRecentNotifications, - shouldGroupNotificationType, } from 'flavours/glitch/actions/notification_groups'; import { disconnectTimeline, @@ -30,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'; @@ -205,8 +205,9 @@ function mergeGapsAround( function processNewNotification( groups: NotificationGroupsState['groups'], notification: ApiNotificationJSON, + groupedTypes: NotificationType[], ) { - if (!shouldGroupNotificationType(notification.type)) { + if (!groupedTypes.includes(notification.type)) { notification = { ...notification, group_key: `ungrouped-${notification.id}`, @@ -476,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); diff --git a/app/javascript/flavours/glitch/reducers/settings.js b/app/javascript/flavours/glitch/reducers/settings.js index 46ddb32df1..fe87f4d2bf 100644 --- a/app/javascript/flavours/glitch/reducers/settings.js +++ b/app/javascript/flavours/glitch/reducers/settings.js @@ -84,6 +84,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/settings.ts b/app/javascript/flavours/glitch/selectors/settings.ts index d66f00f0e1..5229b15cf0 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/annual_reports.scss b/app/javascript/flavours/glitch/styles/annual_reports.scss new file mode 100644 index 0000000000..39784e3b5e --- /dev/null +++ b/app/javascript/flavours/glitch/styles/annual_reports.scss @@ -0,0 +1,335 @@ +:root { + --indigo-1: #17063b; + --indigo-2: #2f0c7a; + --indigo-3: #562cfc; + --indigo-5: #858afa; + --indigo-6: #cccfff; + --lime: #baff3b; + --goldenrod-2: #ffc954; +} + +.annual-report { + flex: 0 0 auto; + background: var(--indigo-1); + padding: 24px; + + &__header { + margin-bottom: 16px; + + h1 { + font-size: 25px; + font-weight: 600; + line-height: 30px; + color: var(--lime); + margin-bottom: 8px; + } + + p { + font-size: 16px; + font-weight: 600; + line-height: 20px; + color: var(--indigo-6); + } + } + + &__bento { + display: grid; + gap: 8px; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); + grid-template-rows: minmax(0, auto) minmax(0, 1fr) minmax(0, auto) minmax( + 0, + auto + ); + + &__box { + padding: 16px; + border-radius: 8px; + background: var(--indigo-2); + color: var(--indigo-5); + } + } + + &__summary { + &__most-boosted-post { + grid-column: span 2; + grid-row: span 2; + padding: 0; + + .status__content, + .content-warning { + color: var(--indigo-6); + } + + .detailed-status { + border: 0; + } + + .content-warning { + border: 0; + background: var(--indigo-1); + + .link-button { + color: var(--indigo-5); + } + } + + .detailed-status__meta__line { + border-bottom-color: var(--indigo-3); + } + + .detailed-status__meta { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .detailed-status__meta, + .poll__footer, + .poll__link, + .detailed-status .logo, + .detailed-status__display-name { + color: var(--indigo-5); + } + + .detailed-status__meta .animated-number, + .detailed-status__display-name strong { + color: var(--indigo-6); + } + + .poll__chart { + background-color: var(--indigo-3); + + &.leading { + background-color: var(--goldenrod-2); + } + } + } + + &__followers { + grid-column: span 1; + text-align: center; + position: relative; + overflow: hidden; + padding-block-start: 24px; + padding-block-end: 24px; + + --sparkline-gradient-top: rgba(86, 44, 252, 50%); + --sparkline-gradient-bottom: rgba(86, 44, 252, 0%); + + &__foreground { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + position: relative; + z-index: 1; + } + + &__number { + font-size: 31px; + font-weight: 600; + line-height: 37px; + color: var(--lime); + } + + &__label { + font-size: 14px; + font-weight: 600; + line-height: 17px; + color: var(--indigo-6); + } + + &__footnote { + display: block; + font-weight: 400; + opacity: 0.5; + } + + svg { + position: absolute; + bottom: 0; + inset-inline-end: 0; + pointer-events: none; + z-index: 0; + height: 70%; + width: auto; + + path:first-child { + fill: url('#gradient') !important; + fill-opacity: 1 !important; + } + + path:last-child { + stroke: var(--indigo-3) !important; + fill: none !important; + } + } + } + + &__archetype { + grid-column: span 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 8px; + padding: 0; + + img { + display: block; + width: 100%; + height: auto; + border-radius: 8px; + } + + &__label { + padding: 16px; + padding-bottom: 8px; + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--lime); + } + } + + &__most-used-app { + grid-column: span 1; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + box-sizing: border-box; + + &__label { + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--indigo-6); + } + + &__icon { + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--goldenrod-2); + } + } + + &__percentile { + grid-row: span 2; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + text-align: center; + text-wrap: balance; + padding: 16px 8px; + + &__label { + font-size: 14px; + line-height: 17px; + } + + &__number { + font-size: 61px; + font-weight: 600; + line-height: 73px; + color: var(--goldenrod-2); + } + + &__footnote { + font-size: 11px; + line-height: 14px; + opacity: 0.5; + } + } + + &__new-posts { + grid-column: span 2; + text-align: center; + position: relative; + overflow: hidden; + + &__label { + font-size: 20px; + font-weight: 600; + line-height: 24px; + color: var(--indigo-6); + z-index: 1; + position: relative; + } + + &__number { + font-size: 76px; + font-weight: 600; + line-height: 91px; + color: var(--goldenrod-2); + z-index: 1; + position: relative; + } + + svg { + position: absolute; + inset-inline-start: -7px; + top: -4px; + z-index: 0; + } + } + + &__most-used-hashtag { + grid-column: span 2; + text-align: center; + overflow: hidden; + + &__hashtag { + font-size: 42px; + font-weight: 600; + line-height: 58px; + color: var(--indigo-6); + margin-inline-start: -100%; + margin-inline-end: -100%; + } + + &__label { + font-size: 14px; + font-weight: 600; + line-height: 17px; + } + } + } +} + +.annual-report-modal { + max-width: 480px; + background: var(--indigo-1); + border-radius: 16px; + display: flex; + flex-direction: column; + overflow-y: auto; + + .loading-indicator .circular-progress { + color: var(--lime); + } + + @media screen and (max-width: $no-columns-breakpoint) { + border-bottom: 0; + border-radius: 16px 16px 0 0; + } +} + +.notification-group--annual-report { + .notification-group__icon { + color: var(--lime); + } + + .notification-group__main .link-button { + font-weight: 500; + color: var(--lime); + } +} diff --git a/app/javascript/flavours/glitch/styles/application.scss b/app/javascript/flavours/glitch/styles/application.scss index fd55960311..ac58cca66a 100644 --- a/app/javascript/flavours/glitch/styles/application.scss +++ b/app/javascript/flavours/glitch/styles/application.scss @@ -15,6 +15,7 @@ @import 'polls'; @import 'modal'; @import 'emoji_picker'; +@import 'annual_reports'; @import 'about'; @import 'tables'; @import 'admin'; diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 9e943617ac..0f52af2986 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -1399,9 +1399,9 @@ body > [data-popper-placement] { } .status__content__spoiler-link { - display: inline-flex; // glitch: media icon in spoiler button + display: inline-block; border-radius: 2px; - background: $action-button-color; // glitch: design used in more places + background: transparent; border: 0; color: $inverted-text-color; font-weight: 700; @@ -1411,23 +1411,6 @@ body > [data-popper-placement] { line-height: 20px; cursor: pointer; vertical-align: top; - align-items: center; // glitch: content indicator - - &:hover { - // glitch: design used in more places - background: lighten($action-button-color, 7%); - text-decoration: none; - } - - .status__content__spoiler-icon { - display: inline-block; - margin-inline-start: 5px; - border-inline-start: 1px solid currentColor; - padding: 0; - padding-inline-start: 4px; - width: 16px; - height: 16px; - } } .status__wrapper--filtered { @@ -1878,7 +1861,8 @@ body > [data-popper-placement] { .status__wrapper-direct, .notification-ungrouped--direct, -.notification-group--direct { +.notification-group--direct, +.notification-group--annual-report { background: rgba($ui-highlight-color, 0.05); &:focus { @@ -1952,6 +1936,14 @@ body > [data-popper-placement] { margin-bottom: 16px; } + .content-warning { + margin-bottom: 16px; + + &:last-child { + margin-bottom: 0; + } + } + .logo { width: 40px; height: 40px; @@ -2954,6 +2946,7 @@ a.account__display-name { flex: 0 1 auto; display: flex; flex-direction: column; + contain: inline-size layout paint style; @media screen and (min-width: $no-gap-breakpoint) { max-width: 600px; @@ -4250,6 +4243,7 @@ input.glitch-setting-text { overflow: hidden; border: 1px solid var(--background-border-color); border-radius: 8px; + contain: inline-size layout paint style; &.bottomless { border-radius: 8px 8px 0 0; @@ -6265,7 +6259,8 @@ a.status-card { inset-inline-start: 0; inset-inline-end: 0; bottom: 0; - background: rgba($base-overlay-background, 0.7); + opacity: 0.9; + background: $base-overlay-background; transition: background 0.5s; } @@ -6292,6 +6287,7 @@ a.status-card { pointer-events: auto; user-select: text; display: flex; + max-width: 100vw; @media screen and (width <= $mobile-breakpoint) { margin-top: auto; @@ -11377,21 +11373,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 { @@ -11676,19 +11668,21 @@ noscript { } .content-warning { + display: block; box-sizing: border-box; background: rgba($ui-highlight-color, 0.05); color: $secondary-text-color; - border-top: 1px solid; - border-bottom: 1px solid; - border-color: rgba($ui-highlight-color, 0.15); + border: 1px solid rgba($ui-highlight-color, 0.15); + border-radius: 8px; padding: 8px (5px + 8px); position: relative; font-size: 15px; line-height: 22px; + cursor: pointer; p { margin-bottom: 8px; + font-weight: 500; } .link-button { @@ -11697,31 +11691,22 @@ noscript { font-weight: 500; } - &::before, - &::after { - content: ''; - display: block; - position: absolute; - height: 100%; - background: url('~images/warning-stripes.svg') repeat-y; - width: 5px; - top: 0; + &--filter { + color: $darker-text-color; + + p { + font-weight: normal; + } + + .filter-name { + font-weight: 500; + color: $secondary-text-color; + } } - &::before { - border-start-start-radius: 4px; - border-end-start-radius: 4px; - inset-inline-start: 0; - } - - &::after { - border-start-end-radius: 4px; - border-end-end-radius: 4px; - inset-inline-end: 0; - } - - &--filter::before, - &--filter::after { - background-image: url('~images/filter-stripes.svg'); + .status__content__spoiler-icon { + float: inline-end; + width: 20px; + height: 20px; } } diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 63346bb5ca..352567d093 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -23,6 +23,8 @@ code { position: relative; overflow: hidden; height: 160px; + max-width: 566px; + margin-inline: auto; &::after { content: ''; diff --git a/app/javascript/flavours/glitch/styles/mastodon-light/variables.scss b/app/javascript/flavours/glitch/styles/mastodon-light/variables.scss index 76bdc4022e..777c622ace 100644 --- a/app/javascript/flavours/glitch/styles/mastodon-light/variables.scss +++ b/app/javascript/flavours/glitch/styles/mastodon-light/variables.scss @@ -76,4 +76,7 @@ body { --background-color-tint: rgba(255, 255, 255, 80%); --background-filter: blur(10px); --on-surface-color: #{transparentize($ui-base-color, 0.65)}; + --rich-text-container-color: rgba(255, 216, 231, 100%); + --rich-text-text-color: rgba(114, 47, 83, 100%); + --rich-text-decorations-color: rgba(255, 175, 212, 100%); } diff --git a/app/javascript/flavours/glitch/styles/rich_text.scss b/app/javascript/flavours/glitch/styles/rich_text.scss index 266a09eb8e..30f89a5710 100644 --- a/app/javascript/flavours/glitch/styles/rich_text.scss +++ b/app/javascript/flavours/glitch/styles/rich_text.scss @@ -2,9 +2,29 @@ .e-content, .edit-indicator__content, .reply-indicator__content { + code { + background: var(--rich-text-container-color); + padding: 4px; + border-radius: 4px; + color: var(--rich-text-text-color); + font-size: 0.85em; + } + + pre { + background: var(--rich-text-container-color); + padding: 8px; + border-radius: 4px; + color: var(--rich-text-text-color); + + code { + padding: 0; + background: transparent; + } + } + pre, blockquote { - margin-bottom: 20px; + margin-bottom: 22px; white-space: pre-wrap; unicode-bidi: plaintext; @@ -14,19 +34,45 @@ } blockquote { - padding-inline-start: 10px; - border-inline-start: 3px solid $darker-text-color; - color: $darker-text-color; + padding-inline-start: 32px; + color: var(--rich-text-text-color); white-space: normal; + position: relative; - p:last-child { + &::before { + display: block; + content: ''; + width: 24px; + height: 20px; + mask-image: url('~images/quote.svg'); + background-color: var(--rich-text-decorations-color); + position: absolute; + inset-inline-start: 0; + top: 0; + } + + blockquote { + margin-top: 4px; + border-inline-start: 3px solid var(--rich-text-decorations-color); + padding-inline-start: 16px; + + &::before { + display: none; + } + } + + p:last-of-type { margin-bottom: 0; } } & > ul, & > ol { - margin-bottom: 20px; + margin-bottom: 22px; + + &:last-child { + margin-bottom: 0; + } } h1, @@ -76,7 +122,15 @@ ul, ol { - margin-inline-start: 2em; + padding-inline-start: 24px; + + li { + padding-inline-start: 8px; + + &::marker { + text-align: end; + } + } p { margin: 0; @@ -84,7 +138,11 @@ } ul { - list-style-type: disc; + list-style-type: '•'; + + li::marker { + text-align: start; + } } ol { diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index f6140b87e2..ba60983436 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/variables.scss b/app/javascript/flavours/glitch/styles/variables.scss index b3e87681f5..a25fdad141 100644 --- a/app/javascript/flavours/glitch/styles/variables.scss +++ b/app/javascript/flavours/glitch/styles/variables.scss @@ -122,4 +122,7 @@ $dismiss-overlay-width: 4rem; --error-background-color: #{darken($error-red, 16%)}; --error-active-background-color: #{darken($error-red, 12%)}; --on-error-color: #fff; + --rich-text-container-color: rgba(87, 24, 60, 100%); + --rich-text-text-color: rgba(255, 175, 212, 100%); + --rich-text-decorations-color: rgba(128, 58, 95, 100%); } diff --git a/app/javascript/images/archetypes/booster.png b/app/javascript/images/archetypes/booster.png new file mode 100755 index 0000000000..18c92dfb7d Binary files /dev/null and b/app/javascript/images/archetypes/booster.png differ diff --git a/app/javascript/images/archetypes/lurker.png b/app/javascript/images/archetypes/lurker.png new file mode 100755 index 0000000000..8e1d6451b0 Binary files /dev/null and b/app/javascript/images/archetypes/lurker.png differ diff --git a/app/javascript/images/archetypes/oracle.png b/app/javascript/images/archetypes/oracle.png new file mode 100755 index 0000000000..2afd3c72e1 Binary files /dev/null and b/app/javascript/images/archetypes/oracle.png differ diff --git a/app/javascript/images/archetypes/pollster.png b/app/javascript/images/archetypes/pollster.png new file mode 100755 index 0000000000..b838fccdd6 Binary files /dev/null and b/app/javascript/images/archetypes/pollster.png differ diff --git a/app/javascript/images/archetypes/replier.png b/app/javascript/images/archetypes/replier.png new file mode 100755 index 0000000000..b298d4221c Binary files /dev/null and b/app/javascript/images/archetypes/replier.png differ diff --git a/app/javascript/images/logo_full.svg b/app/javascript/images/logo_full.svg deleted file mode 100644 index 03bcf93e39..0000000000 --- a/app/javascript/images/logo_full.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/javascript/images/logo_transparent.svg b/app/javascript/images/logo_transparent.svg deleted file mode 100644 index a1e7b403e0..0000000000 --- a/app/javascript/images/logo_transparent.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/javascript/images/quote.svg b/app/javascript/images/quote.svg new file mode 100644 index 0000000000..ae6fbbe04a --- /dev/null +++ b/app/javascript/images/quote.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/javascript/mastodon/actions/notification_groups.ts b/app/javascript/mastodon/actions/notification_groups.ts index a359913e61..a3c8095ac4 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,17 +70,19 @@ function dispatchAssociatedRecords( dispatch(importFetchedStatuses(fetchedStatuses)); } -const supportedGroupedNotificationTypes = ['favourite', 'reblog']; +function selectNotificationGroupedTypes(state: RootState) { + const types: NotificationType[] = ['favourite', 'reblog']; -export function shouldGroupNotificationType(type: string) { - return supportedGroupedNotificationTypes.includes(type); + if (selectSettingsNotificationsGroupFollows(state)) types.push('follow'); + + return types; } export const fetchNotifications = createDataLoadingThunk( 'notificationGroups/fetch', async (_params, { getState }) => apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + grouped_types: selectNotificationGroupedTypes(getState()), exclude_types: getExcludedTypes(getState()), }), ({ notifications, accounts, statuses }, { dispatch }) => { @@ -102,7 +106,7 @@ export const fetchNotificationsGap = createDataLoadingThunk( 'notificationGroups/fetchGap', async (params: { gap: NotificationGap }, { getState }) => apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + grouped_types: selectNotificationGroupedTypes(getState()), max_id: params.gap.maxId, exclude_types: getExcludedTypes(getState()), }), @@ -119,7 +123,7 @@ export const pollRecentNotifications = createDataLoadingThunk( 'notificationGroups/pollRecentNotifications', async (_params, { getState }) => { return apiFetchNotificationGroups({ - grouped_types: supportedGroupedNotificationTypes, + 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 @@ -168,7 +172,10 @@ export const processNewNotificationForGroups = createAppAsyncThunk( dispatchAssociatedRecords(dispatch, [notification]); - return notification; + return { + notification, + groupedTypes: selectNotificationGroupedTypes(state), + }; }, ); diff --git a/app/javascript/mastodon/api_types/notifications.ts b/app/javascript/mastodon/api_types/notifications.ts index 28ba7eb5c2..190d8c8396 100644 --- a/app/javascript/mastodon/api_types/notifications.ts +++ b/app/javascript/mastodon/api_types/notifications.ts @@ -20,6 +20,7 @@ export const allNotificationTypes = [ 'admin.report', 'moderation_warning', 'severed_relationships', + 'annual_report', ]; export type NotificationWithStatusType = @@ -37,7 +38,8 @@ export type NotificationType = | 'moderation_warning' | 'severed_relationships' | 'admin.sign_up' - | 'admin.report'; + | 'admin.report' + | 'annual_report'; export interface BaseNotificationJSON { id: string; @@ -130,6 +132,15 @@ interface AccountRelationshipSeveranceNotificationJSON event: ApiAccountRelationshipSeveranceEventJSON; } +export interface ApiAnnualReportEventJSON { + year: string; +} + +interface AnnualReportNotificationGroupJSON extends BaseNotificationGroupJSON { + type: 'annual_report'; + annual_report: ApiAnnualReportEventJSON; +} + export type ApiNotificationJSON = | SimpleNotificationJSON | ReportNotificationJSON @@ -142,7 +153,8 @@ export type ApiNotificationGroupJSON = | ReportNotificationGroupJSON | AccountRelationshipSeveranceNotificationGroupJSON | NotificationGroupWithStatusJSON - | ModerationWarningNotificationGroupJSON; + | ModerationWarningNotificationGroupJSON + | AnnualReportNotificationGroupJSON; export interface ApiNotificationGroupsResultJSON { accounts: ApiAccountJSON[]; diff --git a/app/javascript/mastodon/components/button.tsx b/app/javascript/mastodon/components/button.tsx index 3e720f7cee..b349a83f2b 100644 --- a/app/javascript/mastodon/components/button.tsx +++ b/app/javascript/mastodon/components/button.tsx @@ -1,4 +1,4 @@ -import type { PropsWithChildren } from 'react'; +import type { PropsWithChildren, JSX } from 'react'; import { useCallback } from 'react'; import classNames from 'classnames'; diff --git a/app/javascript/mastodon/components/content_warning.tsx b/app/javascript/mastodon/components/content_warning.tsx index df8afca74d..c1c879b55d 100644 --- a/app/javascript/mastodon/components/content_warning.tsx +++ b/app/javascript/mastodon/components/content_warning.tsx @@ -8,7 +8,7 @@ export const ContentWarning: React.FC<{

diff --git a/app/javascript/mastodon/components/filter_warning.tsx b/app/javascript/mastodon/components/filter_warning.tsx index 4305e43038..5eaaac4ba3 100644 --- a/app/javascript/mastodon/components/filter_warning.tsx +++ b/app/javascript/mastodon/components/filter_warning.tsx @@ -10,13 +10,16 @@ export const FilterWarning: React.FC<{

{chunks}, + }} />

diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index e059978442..59963a0a9f 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -97,12 +97,12 @@ class Item extends PureComponent { height = 50; } - if (attachment.get('description')?.length > 0) { - badges.push(); - } - const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); + if (description?.length > 0) { + badges.push(); + } + if (attachment.get('type') === 'unknown') { return (
diff --git a/app/javascript/mastodon/components/modal_root.jsx b/app/javascript/mastodon/components/modal_root.jsx index e7fa5e6f9a..b0d88fe8f9 100644 --- a/app/javascript/mastodon/components/modal_root.jsx +++ b/app/javascript/mastodon/components/modal_root.jsx @@ -13,11 +13,14 @@ class ModalRoot extends PureComponent { static propTypes = { children: PropTypes.node, onClose: PropTypes.func.isRequired, - backgroundColor: PropTypes.shape({ - r: PropTypes.number, - g: PropTypes.number, - b: PropTypes.number, - }), + backgroundColor: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ + r: PropTypes.number, + g: PropTypes.number, + b: PropTypes.number, + }), + ]), ignoreFocus: PropTypes.bool, ...WithOptionalRouterPropTypes, }; @@ -141,14 +144,17 @@ class ModalRoot extends PureComponent { let backgroundColor = null; - if (this.props.backgroundColor) { - backgroundColor = multiply({ ...this.props.backgroundColor, a: 1 }, { r: 0, g: 0, b: 0, a: 0.7 }); + if (this.props.backgroundColor && typeof this.props.backgroundColor === 'string') { + backgroundColor = this.props.backgroundColor; + } else if (this.props.backgroundColor) { + const darkenedColor = multiply({ ...this.props.backgroundColor, a: 1 }, { r: 0, g: 0, b: 0, a: 0.7 }); + backgroundColor = `rgb(${darkenedColor.r}, ${darkenedColor.g}, ${darkenedColor.b})`; } return (
-
+
{children}
diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx index 7b836f00b1..06b09f5b35 100644 --- a/app/javascript/mastodon/components/poll.jsx +++ b/app/javascript/mastodon/components/poll.jsx @@ -41,12 +41,14 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => { class Poll extends ImmutablePureComponent { static propTypes = { identity: identityContextPropShape, - poll: ImmutablePropTypes.map, + poll: ImmutablePropTypes.map.isRequired, + status: ImmutablePropTypes.map.isRequired, lang: PropTypes.string, intl: PropTypes.object.isRequired, disabled: PropTypes.bool, refresh: PropTypes.func, onVote: PropTypes.func, + onInteractionModal: PropTypes.func, }; state = { @@ -117,7 +119,11 @@ class Poll extends ImmutablePureComponent { return; } - this.props.onVote(Object.keys(this.state.selected)); + if (this.props.identity.signedIn) { + this.props.onVote(Object.keys(this.state.selected)); + } else { + this.props.onInteractionModal('vote', this.props.status); + } }; handleRefresh = () => { @@ -232,7 +238,7 @@ class Poll extends ImmutablePureComponent {
- {!showResults && } + {!showResults && } {!showResults && <> · } {showResults && !this.props.disabled && <> · } {votesCount} diff --git a/app/javascript/mastodon/components/short_number.tsx b/app/javascript/mastodon/components/short_number.tsx index a0b523aaad..37201a5e1d 100644 --- a/app/javascript/mastodon/components/short_number.tsx +++ b/app/javascript/mastodon/components/short_number.tsx @@ -1,4 +1,5 @@ import { memo } from 'react'; +import type { JSX } from 'react'; import { FormattedMessage, FormattedNumber } from 'react-intl'; diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index b6a6ee9360..472c517813 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -395,13 +395,16 @@ class Status extends ImmutablePureComponent { }; let media, statusAvatar, prepend, rebloggedByText; + const matchedFilters = status.get('matched_filters'); + const expanded = (!matchedFilters || this.state.showDespiteFilter) && (!status.get('hidden') || status.get('spoiler_text').length === 0); if (hidden) { return (
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])} - {status.get('content')} + {status.get('spoiler_text').length > 0 && ({status.get('spoiler_text')})} + {expanded && {status.get('content')}}
); @@ -410,7 +413,6 @@ class Status extends ImmutablePureComponent { const connectUp = previousId && previousId === status.get('in_reply_to_id'); const connectToRoot = rootId && rootId === status.get('in_reply_to_id'); const connectReply = nextInReplyToId && nextInReplyToId === status.get('id'); - const matchedFilters = status.get('matched_filters'); if (featured) { prepend = ( @@ -451,7 +453,7 @@ class Status extends ImmutablePureComponent { } else if (status.get('media_attachments').size > 0) { const language = status.getIn(['translation', 'language']) || status.get('language'); - if (['image', 'gifv'].includes(status.getIn(['media_attachments', 0, 'type'])) || status.get('media_attachments').size > 1) { + if (['image', 'gifv', 'unknown'].includes(status.getIn(['media_attachments', 0, 'type'])) || status.get('media_attachments').size > 1) { media = ( {Component => ( @@ -540,7 +542,6 @@ class Status extends ImmutablePureComponent { } const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status); - const expanded = (!matchedFilters || this.state.showDespiteFilter) && (!status.get('hidden') || status.get('spoiler_text').length === 0); return ( diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx index feb79573a5..9035c3b73f 100644 --- a/app/javascript/mastodon/components/status_action_bar.jsx +++ b/app/javascript/mastodon/components/status_action_bar.jsx @@ -271,7 +271,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 }); } diff --git a/app/javascript/mastodon/components/status_banner.tsx b/app/javascript/mastodon/components/status_banner.tsx index 8ff17a9b2e..d25c05d6db 100644 --- a/app/javascript/mastodon/components/status_banner.tsx +++ b/app/javascript/mastodon/components/status_banner.tsx @@ -1,8 +1,8 @@ import { FormattedMessage } from 'react-intl'; export enum BannerVariant { - Yellow = 'yellow', - Blue = 'blue', + Warning = 'warning', + Filter = 'filter', } export const StatusBanner: React.FC<{ @@ -11,9 +11,9 @@ export const StatusBanner: React.FC<{ expanded?: boolean; onClick?: () => void; }> = ({ children, variant, expanded, onClick }) => ( -
+ ) : variant === BannerVariant.Warning ? ( + ) : ( )} -
+ ); diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 3316be8350..4950c896f9 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -245,7 +245,7 @@ class StatusContent extends PureComponent { ); const poll = !!status.get('poll') && ( - + ); if (this.props.onClick) { diff --git a/app/javascript/mastodon/containers/poll_container.js b/app/javascript/mastodon/containers/poll_container.js index 8482345431..db378cba7c 100644 --- a/app/javascript/mastodon/containers/poll_container.js +++ b/app/javascript/mastodon/containers/poll_container.js @@ -2,6 +2,7 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; +import { openModal } from 'mastodon/actions/modal'; import { fetchPoll, vote } from 'mastodon/actions/polls'; import Poll from 'mastodon/components/poll'; @@ -17,6 +18,17 @@ const mapDispatchToProps = (dispatch, { pollId }) => ({ onVote (choices) { dispatch(vote(pollId, choices)); }, + + onInteractionModal (type, status) { + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type, + accountId: status.getIn(['account', 'id']), + url: status.get('uri'), + }, + })); + } }); const mapStateToProps = (state, { pollId }) => ({ diff --git a/app/javascript/mastodon/features/annual_report/archetype.tsx b/app/javascript/mastodon/features/annual_report/archetype.tsx new file mode 100644 index 0000000000..fffbc1803e --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/archetype.tsx @@ -0,0 +1,69 @@ +import { FormattedMessage } from 'react-intl'; + +import booster from '@/images/archetypes/booster.png'; +import lurker from '@/images/archetypes/lurker.png'; +import oracle from '@/images/archetypes/oracle.png'; +import pollster from '@/images/archetypes/pollster.png'; +import replier from '@/images/archetypes/replier.png'; +import type { Archetype as ArchetypeData } from 'mastodon/models/annual_report'; + +export const Archetype: React.FC<{ + data: ArchetypeData; +}> = ({ data }) => { + let illustration, label; + + switch (data) { + case 'booster': + illustration = booster; + label = ( + + ); + break; + case 'replier': + illustration = replier; + label = ( + + ); + break; + case 'pollster': + illustration = pollster; + label = ( + + ); + break; + case 'lurker': + illustration = lurker; + label = ( + + ); + break; + case 'oracle': + illustration = oracle; + label = ( + + ); + break; + } + + return ( +
+
{label}
+ +
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/followers.tsx b/app/javascript/mastodon/features/annual_report/followers.tsx new file mode 100644 index 0000000000..196013ae9d --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/followers.tsx @@ -0,0 +1,69 @@ +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import { Sparklines, SparklinesCurve } from 'react-sparklines'; + +import { ShortNumber } from 'mastodon/components/short_number'; +import type { TimeSeriesMonth } from 'mastodon/models/annual_report'; + +export const Followers: React.FC<{ + data: TimeSeriesMonth[]; + total?: number; +}> = ({ data, total }) => { + const change = data.reduce((sum, item) => sum + item.followers, 0); + + const cumulativeGraph = data.reduce( + (newData, item) => [ + ...newData, + item.followers + (newData[newData.length - 1] ?? 0), + ], + [0], + ); + + return ( +
+ + + + + + + + + + + + + +
+
+ {change > -1 ? '+' : '-'} + +
+ +
+ + + +
+ }} + /> +
+
+
+
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/highlighted_post.tsx b/app/javascript/mastodon/features/annual_report/highlighted_post.tsx new file mode 100644 index 0000000000..3a2a70713d --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/highlighted_post.tsx @@ -0,0 +1,105 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return, + @typescript-eslint/no-explicit-any, + @typescript-eslint/no-unsafe-assignment */ + +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { toggleStatusSpoilers } from 'mastodon/actions/statuses'; +import { DetailedStatus } from 'mastodon/features/status/components/detailed_status'; +import { me } from 'mastodon/initial_state'; +import type { TopStatuses } from 'mastodon/models/annual_report'; +import { makeGetStatus, makeGetPictureInPicture } from 'mastodon/selectors'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; + +const getStatus = makeGetStatus() as unknown as (arg0: any, arg1: any) => any; +const getPictureInPicture = makeGetPictureInPicture() as unknown as ( + arg0: any, + arg1: any, +) => any; + +export const HighlightedPost: React.FC<{ + data: TopStatuses; +}> = ({ data }) => { + let statusId, label; + + if (data.by_reblogs) { + statusId = data.by_reblogs; + label = ( + + ); + } else if (data.by_favourites) { + statusId = data.by_favourites; + label = ( + + ); + } else { + statusId = data.by_replies; + label = ( + + ); + } + + const dispatch = useAppDispatch(); + const domain = useAppSelector((state) => state.meta.get('domain')); + const status = useAppSelector((state) => + statusId ? getStatus(state, { id: statusId }) : undefined, + ); + const pictureInPicture = useAppSelector((state) => + statusId ? getPictureInPicture(state, { id: statusId }) : undefined, + ); + const account = useAppSelector((state) => + me ? state.accounts.get(me) : undefined, + ); + + const handleToggleHidden = useCallback(() => { + dispatch(toggleStatusSpoilers(statusId)); + }, [dispatch, statusId]); + + if (!status) { + return ( +
+ ); + } + + const displayName = ( + + + + ), + }} + /> + + {label} + + ); + + return ( +
+ +
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/index.tsx b/app/javascript/mastodon/features/annual_report/index.tsx new file mode 100644 index 0000000000..91f03330c0 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/index.tsx @@ -0,0 +1,99 @@ +import { useState, useEffect } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { + importFetchedStatuses, + importFetchedAccounts, +} from 'mastodon/actions/importer'; +import { apiRequestGet, apiRequestPost } from 'mastodon/api'; +import { LoadingIndicator } from 'mastodon/components/loading_indicator'; +import { me } from 'mastodon/initial_state'; +import type { Account } from 'mastodon/models/account'; +import type { AnnualReport as AnnualReportData } from 'mastodon/models/annual_report'; +import type { Status } from 'mastodon/models/status'; +import { useAppSelector, useAppDispatch } from 'mastodon/store'; + +import { Archetype } from './archetype'; +import { Followers } from './followers'; +import { HighlightedPost } from './highlighted_post'; +import { MostUsedHashtag } from './most_used_hashtag'; +import { NewPosts } from './new_posts'; +import { Percentile } from './percentile'; + +interface AnnualReportResponse { + annual_reports: AnnualReportData[]; + accounts: Account[]; + statuses: Status[]; +} + +export const AnnualReport: React.FC<{ + year: string; +}> = ({ year }) => { + const [response, setResponse] = useState(null); + const [loading, setLoading] = useState(false); + const currentAccount = useAppSelector((state) => + me ? state.accounts.get(me) : undefined, + ); + const dispatch = useAppDispatch(); + + useEffect(() => { + setLoading(true); + + apiRequestGet(`v1/annual_reports/${year}`) + .then((data) => { + dispatch(importFetchedStatuses(data.statuses)); + dispatch(importFetchedAccounts(data.accounts)); + + setResponse(data); + setLoading(false); + + return apiRequestPost(`v1/annual_reports/${year}/read`); + }) + .catch(() => { + setLoading(false); + }); + }, [dispatch, year, setResponse, setLoading]); + + if (loading) { + return ; + } + + const report = response?.annual_reports[0]; + + if (!report) { + return null; + } + + return ( +
+
+

+ +

+

+ +

+
+ +
+ + + + + + +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/most_used_app.tsx b/app/javascript/mastodon/features/annual_report/most_used_app.tsx new file mode 100644 index 0000000000..2d8c8aa582 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/most_used_app.tsx @@ -0,0 +1,29 @@ +import { FormattedMessage } from 'react-intl'; + +import type { NameAndCount } from 'mastodon/models/annual_report'; + +export const MostUsedApp: React.FC<{ + data: NameAndCount[]; +}> = ({ data }) => { + const app = data[0]; + + if (!app) { + return ( +
+ ); + } + + return ( +
+
+ {app.name} +
+
+ +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/most_used_hashtag.tsx b/app/javascript/mastodon/features/annual_report/most_used_hashtag.tsx new file mode 100644 index 0000000000..0e4c78f639 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/most_used_hashtag.tsx @@ -0,0 +1,29 @@ +import { FormattedMessage } from 'react-intl'; + +import type { NameAndCount } from 'mastodon/models/annual_report'; + +export const MostUsedHashtag: React.FC<{ + data: NameAndCount[]; +}> = ({ data }) => { + const hashtag = data[0]; + + if (!hashtag) { + return ( +
+ ); + } + + return ( +
+
+ #{hashtag.name} +
+
+ +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/new_posts.tsx b/app/javascript/mastodon/features/annual_report/new_posts.tsx new file mode 100644 index 0000000000..9ead0176b2 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/new_posts.tsx @@ -0,0 +1,53 @@ +import { FormattedNumber, FormattedMessage } from 'react-intl'; + +import ChatBubbleIcon from '@/material-icons/400-24px/chat_bubble.svg?react'; +import type { TimeSeriesMonth } from 'mastodon/models/annual_report'; + +export const NewPosts: React.FC<{ + data: TimeSeriesMonth[]; +}> = ({ data }) => { + const posts = data.reduce((sum, item) => sum + item.statuses, 0); + + return ( +
+ + + + + + + + + + + +
+ +
+
+ +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/annual_report/percentile.tsx b/app/javascript/mastodon/features/annual_report/percentile.tsx new file mode 100644 index 0000000000..a758db72c1 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/percentile.tsx @@ -0,0 +1,53 @@ +/* eslint-disable react/jsx-no-useless-fragment */ +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import type { Percentiles } from 'mastodon/models/annual_report'; + +export const Percentile: React.FC<{ + data: Percentiles; +}> = ({ data }) => { + const percentile = data.statuses; + + return ( +
+ ( +
+ {str} +
+ ), + percentage: () => ( +
+ +
+ ), + bottomLabel: (str) => ( +
+
+ {str} +
+ + {percentile < 6 && ( +
+ +
+ )} +
+ ), + }} + > + {(message) => <>{message}} +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx index 15381b589d..73927b612d 100644 --- a/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx +++ b/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx @@ -21,9 +21,11 @@ class ColumnSettings extends PureComponent { return (
-
- } /> -
+
+
+ } /> +
+
); } diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx index 9079cfd87b..d59603fe79 100644 --- a/app/javascript/mastodon/features/compose/components/poll_form.jsx +++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx @@ -25,7 +25,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/mastodon/features/follow_requests/index.jsx b/app/javascript/mastodon/features/follow_requests/index.jsx index a8f40a31d0..7d651f2ca6 100644 --- a/app/javascript/mastodon/features/follow_requests/index.jsx +++ b/app/javascript/mastodon/features/follow_requests/index.jsx @@ -68,7 +68,7 @@ class FollowRequests extends ImmutablePureComponent { ); return ( - +
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 8bcc7ab4ef..4ac6cfa629 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_annual_report.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_annual_report.tsx new file mode 100644 index 0000000000..8b92f31add --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_annual_report.tsx @@ -0,0 +1,59 @@ +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import classNames from 'classnames'; + +import CelebrationIcon from '@/material-icons/400-24px/celebration.svg?react'; +import { openModal } from 'mastodon/actions/modal'; +import { Icon } from 'mastodon/components/icon'; +import type { NotificationGroupAnnualReport } from 'mastodon/models/notification_group'; +import { useAppDispatch } from 'mastodon/store'; + +export const NotificationAnnualReport: React.FC<{ + notification: NotificationGroupAnnualReport; + unread: boolean; +}> = ({ notification: { annualReport }, unread }) => { + const dispatch = useAppDispatch(); + const year = annualReport.year; + + const handleClick = useCallback(() => { + dispatch( + openModal({ + modalType: 'ANNUAL_REPORT', + modalProps: { year }, + }), + ); + }, [dispatch, year]); + + return ( +
+
+ +
+ +
+

+ +

+ +
+
+ ); +}; 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 6a9a45d242..78ba260fa9 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,21 @@ +import type { JSX } from 'react'; + 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 +53,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 +79,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_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx index 36f033261a..d5eb851985 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx @@ -9,6 +9,7 @@ import { useAppSelector, useAppDispatch } from 'mastodon/store'; import { NotificationAdminReport } from './notification_admin_report'; import { NotificationAdminSignUp } from './notification_admin_sign_up'; +import { NotificationAnnualReport } from './notification_annual_report'; import { NotificationFavourite } from './notification_favourite'; import { NotificationFollow } from './notification_follow'; import { NotificationFollowRequest } from './notification_follow_request'; @@ -143,6 +144,14 @@ export const NotificationGroup: React.FC<{ /> ); break; + case 'annual_report': + content = ( + + ); + break; default: return null; } diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx index 91f8ae2d40..861556620f 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx @@ -1,4 +1,5 @@ import { useMemo } from 'react'; +import type { JSX } from 'react'; import classNames from 'classnames'; 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 300c8dd5b3..5c83f99b54 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 0bf1bfda8b..deb330b9a0 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.tsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx @@ -49,6 +49,7 @@ export const DetailedStatus: React.FC<{ domain: string; showMedia?: boolean; withLogo?: boolean; + overrideDisplayName?: React.ReactNode; pictureInPicture: any; onToggleHidden?: (status: any) => void; onToggleMediaVisibility?: () => void; @@ -62,6 +63,7 @@ export const DetailedStatus: React.FC<{ domain, showMedia, withLogo, + overrideDisplayName, pictureInPicture, onToggleMediaVisibility, onToggleHidden, @@ -152,7 +154,7 @@ export const DetailedStatus: React.FC<{ media = ; } else if (status.get('media_attachments').size > 0) { if ( - ['image', 'gifv'].includes( + ['image', 'gifv', 'unknown'].includes( status.getIn(['media_attachments', 0, 'type']) as string, ) || status.get('media_attachments').size > 1 @@ -319,7 +321,11 @@ export const DetailedStatus: React.FC<{
- + + {overrideDisplayName ?? ( + + )} + {withLogo && ( <>
diff --git a/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx b/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx new file mode 100644 index 0000000000..8c39c0b3aa --- /dev/null +++ b/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx @@ -0,0 +1,21 @@ +import { useEffect } from 'react'; + +import { AnnualReport } from 'mastodon/features/annual_report'; + +const AnnualReportModal: React.FC<{ + year: string; + onChangeBackgroundColor: (arg0: string) => void; +}> = ({ year, onChangeBackgroundColor }) => { + useEffect(() => { + onChangeBackgroundColor('var(--indigo-1)'); + }, [onChangeBackgroundColor]); + + return ( +
+ +
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default AnnualReportModal; diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx index 64933fd1ae..42a00acf81 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.jsx +++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx @@ -18,6 +18,7 @@ import { SubscribedLanguagesModal, ClosedRegistrationsModal, IgnoreNotificationsModal, + AnnualReportModal, } from 'mastodon/features/ui/util/async-components'; import { getScrollbarWidth } from 'mastodon/utils/scrollbar'; @@ -72,6 +73,7 @@ export const MODAL_COMPONENTS = { 'INTERACTION': InteractionModal, 'CLOSED_REGISTRATIONS': ClosedRegistrationsModal, 'IGNORE_NOTIFICATIONS': IgnoreNotificationsModal, + 'ANNUAL_REPORT': AnnualReportModal, }; export default class ModalRoot extends PureComponent { diff --git a/app/javascript/mastodon/features/ui/components/mute_modal.jsx b/app/javascript/mastodon/features/ui/components/mute_modal.jsx index 70d95b5931..90b88030a0 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/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js index 7e9a7af00a..ff5db65347 100644 --- a/app/javascript/mastodon/features/ui/util/async-components.js +++ b/app/javascript/mastodon/features/ui/util/async-components.js @@ -217,3 +217,7 @@ export function NotificationRequest () { export function LinkTimeline () { return import(/*webpackChunkName: "features/link_timeline" */'../../link_timeline'); } + +export function AnnualReportModal () { + return import(/*webpackChunkName: "modals/annual_report_modal" */'../components/annual_report_modal'); +} diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index b11382cf03..54ed1cb8c8 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -157,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": "الطراز", @@ -302,7 +301,6 @@ "filter_modal.select_filter.subtitle": "استخدم فئة موجودة أو قم بإنشاء فئة جديدة", "filter_modal.select_filter.title": "تصفية هذا المنشور", "filter_modal.title.status": "تصفية منشور", - "filter_warning.matches_filter": "يطابق عامل التصفية \"{title}\"", "filtered_notifications_banner.title": "الإشعارات المصفاة", "firehose.all": "الكل", "firehose.local": "هذا الخادم", diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 219ea0d17c..e5b1168bea 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", @@ -213,6 +214,7 @@ "hashtag.counter_by_accounts": "{count, plural, one {{counter} participante} other {{counter} participantes}}", "hashtag.follow": "Siguir a la etiqueta", "hashtag.unfollow": "Dexar de siguir a la etiqueta", + "hints.threads.replies_may_be_missing": "Ye posible que falten les rempuestes d'otros sirvidores.", "home.column_settings.show_reblogs": "Amosar los artículos compartíos", "home.column_settings.show_replies": "Amosar les rempuestes", "home.pending_critical_update.body": "¡Anueva'l sirvidor de Mastodon namás que puedas!", @@ -251,7 +253,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 +301,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 +421,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 +472,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 d3a29eae40..97d4dc4b4c 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -98,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": "Халера!", @@ -195,6 +197,7 @@ "confirmations.unfollow.title": "Адпісацца ад карыстальніка?", "content_warning.hide": "Схаваць допіс", "content_warning.show": "Усё адно паказаць", + "content_warning.show_more": "Паказаць усё роўна", "conversation.delete": "Выдаліць размову", "conversation.mark_as_read": "Адзначыць прачытаным", "conversation.open": "Прагледзець размову", @@ -220,6 +223,8 @@ "domain_block_modal.they_cant_follow": "Ніхто з гэтага сервера не зможа падпісацца на вас.", "domain_block_modal.they_wont_know": "Карыстальнік не будзе ведаць пра блакіроўку.", "domain_block_modal.title": "Заблакіраваць дамен?", + "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 размаўляе з іншымі сацыяльнымі сеткамі.", @@ -301,7 +306,7 @@ "filter_modal.select_filter.subtitle": "Скарыстайцеся існуючай катэгорыяй або стварыце новую", "filter_modal.select_filter.title": "Фільтраваць гэты допіс", "filter_modal.title.status": "Фільтраваць допіс", - "filter_warning.matches_filter": "Адпавядае фільтру \"{title}\"", + "filter_warning.matches_filter": "Адпавядае фільтру \"{title}\"", "filtered_notifications_banner.pending_requests": "Ад {count, plural, =0 {# людзей якіх} one {# чалавека якіх} few {# чалавек якіх} many {# людзей якіх} other {# чалавека якіх}} вы магчыма ведаеце", "filtered_notifications_banner.title": "Адфільтраваныя апавяшчэнні", "firehose.all": "Усе", @@ -351,6 +356,9 @@ "hashtag.follow": "Падпісацца на хэштэг", "hashtag.unfollow": "Адпісацца ад хэштэга", "hashtags.and_other": "…і яшчэ {count, plural, other {#}}", + "hints.profiles.followers_may_be_missing": "Падпісчыкі гэтага профілю могуць адсутнічаць.", + "hints.profiles.follows_may_be_missing": "Падпіскі гэтага профілю могуць адсутнічаць.", + "hints.profiles.posts_may_be_missing": "Некаторыя допісы гэтага профілю могуць адсутнічаць.", "home.column_settings.show_reblogs": "Паказваць пашырэнні", "home.column_settings.show_replies": "Паказваць адказы", "home.hide_announcements": "Схаваць аб'явы", @@ -435,6 +443,7 @@ "lists.subheading": "Вашыя спісы", "load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}", "loading_indicator.label": "Загрузка…", + "media_gallery.hide": "Схаваць", "moved_to_account_banner.text": "Ваш уліковы запіс {disabledAccount} зараз адключаны таму што вы перанесены на {movedToAccount}.", "mute_modal.hide_from_notifications": "Схаваць з апавяшчэнняў", "mute_modal.hide_options": "Схаваць опцыі", @@ -480,11 +489,13 @@ "notification.favourite": "Ваш допіс упадабаны {name}", "notification.follow": "{name} падпісаўся на вас", "notification.follow_request": "{name} адправіў запыт на падпіску", + "notification.follow_request.name_and_others": "{name} і {count, plural, one {# іншы} many {# іншых} 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": "Некаторыя вашыя допісы былі выдаленыя.", @@ -497,6 +508,7 @@ "notification.own_poll": "Ваша апытанне скончылася", "notification.poll": "Апытанне, дзе вы прынялі ўдзел, скончылася", "notification.reblog": "{name} пашырыў ваш допіс", + "notification.reblog.name_and_others_with_link": "{name} і {count, plural, one {# іншы} many {# іншых} 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, one {# уліковы запіс} few {# уліковыя запісы} many {# уліковых запісаў} other {# уліковых запісаў}}.", @@ -526,6 +538,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-апавяшчэнні", @@ -744,6 +757,7 @@ "status.edit": "Рэдагаваць", "status.edited": "Апошняе рэдагаванне {date}", "status.edited_x_times": "Рэдагавана {count, plural, one {{count} раз} few {{count} разы} many {{count} разоў} other {{count} разу}}", + "status.embed": "Атрымаць убудаваны код", "status.favourite": "Упадабанае", "status.favourites": "{count, plural, one {# упадабанае} few {# упадабаныя} many {# упадабаных} other {# упадабанага}}", "status.filter": "Фільтраваць гэты допіс", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 1e462ba752..3d5d8a8585 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -158,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": "Стил", @@ -490,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 79949ed91f..13ca521ab0 100644 --- a/app/javascript/mastodon/locales/br.json +++ b/app/javascript/mastodon/locales/br.json @@ -82,6 +82,8 @@ "alert.unexpected.message": "Ur fazi dic'hortozet zo degouezhet.", "alert.unexpected.title": "Hopala !", "announcement.announcement": "Kemennad", + "annual_report.summary.followers.followers": "heulier", + "annual_report.summary.highlighted_post.possessive": "{name}", "attachments_list.unprocessed": "(ket meret)", "audio.hide": "Kuzhat ar c'hleved", "block_modal.show_less": "Diskouez nebeutoc'h", @@ -145,7 +147,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", @@ -172,6 +173,7 @@ "confirmations.reply.message": "Respont bremañ a zilamo ar gemennadenn emaoc'h o skrivañ. Sur e oc'h e fell deoc'h kenderc'hel ganti?", "confirmations.unfollow.confirm": "Diheuliañ", "confirmations.unfollow.message": "Ha sur oc'h e fell deoc'h paouez da heuliañ {name} ?", + "content_warning.show_more": "Diskouez muioc'h", "conversation.delete": "Dilemel ar gaozeadenn", "conversation.mark_as_read": "Merkañ evel lennet", "conversation.open": "Gwelout ar gaozeadenn", @@ -250,6 +252,7 @@ "filter_modal.select_filter.subtitle": "Implijout ur rummad a zo anezhañ pe krouiñ unan nevez", "filter_modal.select_filter.title": "Silañ an toud-mañ", "filter_modal.title.status": "Silañ un toud", + "filter_warning.matches_filter": "A glot gant ar sil “{title}”", "firehose.all": "Pep tra", "firehose.local": "Ar servijer-mañ", "firehose.remote": "Servijerioù all", @@ -385,6 +388,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", @@ -399,6 +403,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 1b583b3204..160a74af4f 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -87,6 +87,18 @@ "alert.unexpected.title": "Vaja!", "alt_text_badge.title": "Text alternatiu", "announcement.announcement": "Anunci", + "annual_report.summary.archetype.oracle": "L'Oracle", + "annual_report.summary.followers.followers": "seguidors", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "El repàs del vostre {year}:", + "annual_report.summary.highlighted_post.by_favourites": "la publicació més afavorida", + "annual_report.summary.highlighted_post.by_reblogs": "la publicació més impulsada", + "annual_report.summary.highlighted_post.by_replies": "la publicació amb més respostes", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "l'aplicació més utilitzada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "l'etiqueta més utilitzada", + "annual_report.summary.new_posts.new_posts": "publicacions noves", + "annual_report.summary.thanks": "Gràcies per formar part de Mastodon!", "attachments_list.unprocessed": "(sense processar)", "audio.hide": "Amaga l'àudio", "block_modal.remote_users_caveat": "Li demanarem al servidor {domain} que respecti la vostra decisió, tot i que no podem garantir-ho, ja que alguns servidors gestionen de forma diferent els blocatges. És possible que els usuaris no autenticats puguin veure les publicacions públiques.", @@ -158,7 +170,7 @@ "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.single": "Única opció", "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", @@ -197,6 +209,7 @@ "confirmations.unfollow.title": "Deixar de seguir l'usuari?", "content_warning.hide": "Amaga la publicació", "content_warning.show": "Mostra-la igualment", + "content_warning.show_more": "Mostra'n més", "conversation.delete": "Elimina la conversa", "conversation.mark_as_read": "Marca com a llegida", "conversation.open": "Mostra la conversa", @@ -305,7 +318,7 @@ "filter_modal.select_filter.subtitle": "Usa una categoria existent o crea'n una de nova", "filter_modal.select_filter.title": "Filtra aquest tut", "filter_modal.title.status": "Filtra un tut", - "filter_warning.matches_filter": "Coincideix amb el filtre “{title}”", + "filter_warning.matches_filter": "Coincideix amb el filtre “{title}”", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {De ningú} one {D'una persona} other {De # persones}} que potser coneixes", "filtered_notifications_banner.title": "Notificacions filtrades", "firehose.all": "Tots", @@ -385,6 +398,7 @@ "interaction_modal.description.follow": "Amb un compte a Mastodon, pots seguir a {name} per a rebre els seus tuts en la teva línia de temps d'Inici.", "interaction_modal.description.reblog": "Amb un compte a Mastodon, pots impulsar aquest tut per a compartir-lo amb els teus seguidors.", "interaction_modal.description.reply": "Amb un compte a Mastodon, pots respondre aquest tut.", + "interaction_modal.description.vote": "Si teniu compte a Mastodon, podeu votar aquesta enquesta.", "interaction_modal.login.action": "Torna a l'inici", "interaction_modal.login.prompt": "Domini del teu servidor domèstic, p.ex. mastodon.social", "interaction_modal.no_account_yet": "No a Mastodon?", @@ -396,6 +410,7 @@ "interaction_modal.title.follow": "Segueix {name}", "interaction_modal.title.reblog": "Impulsa el tut de {name}", "interaction_modal.title.reply": "Respon al tut de {name}", + "interaction_modal.title.vote": "Voteu l'enquesta de {name}", "intervals.full.days": "{number, plural, one {# dia} other {# dies}}", "intervals.full.hours": "{number, plural, one {# hora} other {# hores}}", "intervals.full.minutes": "{number, plural, one {# minut} other {# minuts}}", @@ -508,7 +523,7 @@ "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.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ó", @@ -567,6 +582,7 @@ "notifications.column_settings.filter_bar.category": "Barra ràpida de filtres", "notifications.column_settings.follow": "Nous seguidors:", "notifications.column_settings.follow_request": "Noves sol·licituds de seguiment:", + "notifications.column_settings.group": "Agrupa", "notifications.column_settings.mention": "Mencions:", "notifications.column_settings.poll": "Resultats de l’enquesta:", "notifications.column_settings.push": "Notificacions push", diff --git a/app/javascript/mastodon/locales/ckb.json b/app/javascript/mastodon/locales/ckb.json index bea6e5ceec..469cf4410d 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": "ستایڵ", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index 1f2804daa5..7198bcab58 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", diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json index 52dc6a49e2..675f7a203e 100644 --- a/app/javascript/mastodon/locales/cy.json +++ b/app/javascript/mastodon/locales/cy.json @@ -13,7 +13,7 @@ "about.rules": "Rheolau'r gweinydd", "account.account_note_header": "Nodyn personol", "account.add_or_remove_from_list": "Ychwanegu neu Ddileu o'r rhestrau", - "account.badges.bot": "Bot", + "account.badges.bot": "Awtomataidd", "account.badges.group": "Grŵp", "account.block": "Blocio @{name}", "account.block_domain": "Blocio parth {domain}", @@ -36,7 +36,7 @@ "account.followers.empty": "Does neb yn dilyn y defnyddiwr hwn eto.", "account.followers_counter": "{count, plural, one {{counter} dilynwr} two {{counter} ddilynwr} other {{counter} dilynwyr}}", "account.following": "Yn dilyn", - "account.following_counter": "{count, plural, one {Yn dilyn {counter}} other {Yn dilyn {counter}}}", + "account.following_counter": "{count, plural, one {Yn dilyn {counter}} other {Yn dilyn {counter} arall}}", "account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.", "account.go_to_profile": "Mynd i'r proffil", "account.hide_reblogs": "Cuddio hybiau gan @{name}", @@ -62,7 +62,7 @@ "account.requested_follow": "Mae {name} wedi gwneud cais i'ch dilyn", "account.share": "Rhannwch broffil @{name}", "account.show_reblogs": "Dangos hybiau gan @{name}", - "account.statuses_counter": "{count, plural, one {{counter} post} two {{counter} bost} few {{counter} phost} many {{counter} post} other {{counter} post}}", + "account.statuses_counter": "{count, plural, one {{counter} postiad} two {{counter} bostiad} few {{counter} phostiad} many {{counter} postiad} other {{counter} postiad}}", "account.unblock": "Dadflocio @{name}", "account.unblock_domain": "Dadflocio parth {domain}", "account.unblock_short": "Dadflocio", @@ -158,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", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "Dad-ddilyn defnyddiwr?", "content_warning.hide": "Cuddio'r postiad", "content_warning.show": "Dangos beth bynnag", + "content_warning.show_more": "Dangos rhagor", "conversation.delete": "Dileu sgwrs", "conversation.mark_as_read": "Nodi fel wedi'i ddarllen", "conversation.open": "Gweld sgwrs", @@ -222,6 +223,7 @@ "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_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.", @@ -304,8 +306,8 @@ "filter_modal.select_filter.subtitle": "Defnyddiwch gategori sy'n bodoli eisoes neu crëu un newydd", "filter_modal.select_filter.title": "Hidlo'r postiad hwn", "filter_modal.title.status": "Hidlo postiad", - "filter_warning.matches_filter": "Yn cydweddu'r hidlydd “{title}”", - "filtered_notifications_banner.pending_requests": "Gan {count, plural, =0 {no one} one {un person} two {# berson} few {# pherson} other {# person}} efallai eich bod yn eu hadnabod", + "filter_warning.matches_filter": "Yn cyd-fynd â'r hidlydd “ {title} ”", + "filtered_notifications_banner.pending_requests": "Oddi wrth {count, plural, =0 {no one} one {un person} two {# berson} few {# pherson} other {# person}} efallai eich bod yn eu hadnabod", "filtered_notifications_banner.title": "Hysbysiadau wedi'u hidlo", "firehose.all": "Popeth", "firehose.local": "Gweinydd hwn", @@ -348,12 +350,12 @@ "hashtag.column_settings.tag_mode.any": "Unrhyw un o'r rhain", "hashtag.column_settings.tag_mode.none": "Dim o'r rhain", "hashtag.column_settings.tag_toggle": "Include additional tags in this column", - "hashtag.counter_by_accounts": "{cyfrif, lluosog, un {{counter} cyfranogwr} arall {{counter} cyfranogwr}}", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} cyfranogwr} other {{counter} cyfranogwr}}", "hashtag.counter_by_uses": "{count, plural, one {postiad {counter}} other {postiad {counter}}}", - "hashtag.counter_by_uses_today": "{cyfrif, lluosog, un {{counter} postiad} arall {{counter} postiad}} heddiw", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} postiad} other {{counter} postiad}} heddiw", "hashtag.follow": "Dilyn hashnod", "hashtag.unfollow": "Dad-ddilyn hashnod", - "hashtags.and_other": "…a {count, plural, other {# more}}", + "hashtags.and_other": "…a {count, plural, other {# arall}}", "hints.profiles.followers_may_be_missing": "Mae'n bosibl bod dilynwyr y proffil hwn ar goll.", "hints.profiles.follows_may_be_missing": "Mae'n bosibl bod dilynwyr y proffil hwn ar goll.", "hints.profiles.posts_may_be_missing": "Mae'n bosibl bod rhai postiadau y proffil hwn ar goll.", @@ -384,6 +386,7 @@ "interaction_modal.description.follow": "Gyda chyfrif ar Mastodon, gallwch ddilyn {name} i dderbyn eu postiadau yn eich ffrwd gartref.", "interaction_modal.description.reblog": "Gyda chyfrif ar Mastodon, gallwch hybu'r postiad hwn i'w rannu â'ch dilynwyr.", "interaction_modal.description.reply": "Gyda chyfrif ar Mastodon, gallwch ymateb i'r postiad hwn.", + "interaction_modal.description.vote": "Gyda chyfrif ar Mastodon, gallwch bleidleisio yn y bleidlais hon.", "interaction_modal.login.action": "Mynd i'm ffrwd gartref", "interaction_modal.login.prompt": "Parth eich gweinydd cartref, e.e. mastodon.social", "interaction_modal.no_account_yet": "Dim ar Mastodon?", @@ -395,6 +398,7 @@ "interaction_modal.title.follow": "Dilyn {name}", "interaction_modal.title.reblog": "Hybu postiad {name}", "interaction_modal.title.reply": "Ymateb i bostiad {name}", + "interaction_modal.title.vote": "Pleidleisiwch ym mhleidlais {name}", "intervals.full.days": "{number, plural, one {# diwrnod} two {# ddiwrnod} other {# diwrnod}}", "intervals.full.hours": "{number, plural, one {# awr} other {# o oriau}}", "intervals.full.minutes": "{number, plural, one {# funud} other {# o funudau}}", @@ -441,7 +445,7 @@ "limited_account_hint.title": "Mae'r proffil hwn wedi cael ei guddio gan gymedrolwyr {domain}.", "link_preview.author": "Gan {name}", "link_preview.more_from_author": "Mwy gan {name}", - "link_preview.shares": "{count, plural, one {{counter} ostiad } two {{counter} bostiad } few {{counter} postiad} many {{counter} postiad} other {{counter} postiad}}", + "link_preview.shares": "{count, plural, one {{counter} postiad } two {{counter} bostiad } few {{counter} postiad} many {{counter} postiad} other {{counter} postiad}}", "lists.account.add": "Ychwanegu at restr", "lists.account.remove": "Tynnu o'r rhestr", "lists.delete": "Dileu rhestr", @@ -498,23 +502,24 @@ "navigation_bar.security": "Diogelwch", "not_signed_in_indicator.not_signed_in": "Rhaid i chi fewngofnodi i weld yr adnodd hwn.", "notification.admin.report": "Adroddwyd ar {name} {target}", - "notification.admin.report_account": "{name} reported {count, plural, one {un postiad} other {# postiad}} from {target} for {category}", - "notification.admin.report_account_other": "Adroddodd {name} {count, plural, one {un postiad} two {# bostiad} few {# phost} other {# postiad}} gan {target}", + "notification.admin.report_account": "Adroddodd {name} {count, plural, one {un postiad} other {# postiad}} gan {target} oherwydd {category}", + "notification.admin.report_account_other": "Adroddodd {name} {count, plural, one {un postiad} two {# bostiad} few {# postiad} other {# postiad}} gan {target}", "notification.admin.report_statuses": "Adroddodd {name} {target} ar gyfer {category}", "notification.admin.report_statuses_other": "Adroddodd {name} {target}", "notification.admin.sign_up": "Cofrestrodd {name}", - "notification.admin.sign_up.name_and_others": "Cofrestrodd {name} {count, plural, one {ac # arall} other {a # eraill}}", + "notification.admin.sign_up.name_and_others": "Cofrestrodd {name} {count, plural, one {ac # arall} other {a # arall}}", "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.favourite.name_and_others_with_link": "Ffafriodd {name} a {count, plural, one {# arall} other {# arall}} 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 {# arall} two {# arall} few {# arall} many {# others} other {# arall}} 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.follow_request.name_and_others": "Mae {name} a{count, plural, one {# arall} other {# arall}} wedi gofyn i'ch dilyn chi", "notification.label.mention": "Crybwyll", "notification.label.private_mention": "Crybwyll preifat", "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.", @@ -527,7 +532,7 @@ "notification.own_poll": "Mae eich pleidlais wedi dod i ben", "notification.poll": "Mae arolwg y gwnaethoch bleidleisio ynddo wedi dod i ben", "notification.reblog": "Hybodd {name} eich post", - "notification.reblog.name_and_others_with_link": "Mae {name} a {count, plural, one {# other} other {# others}} wedi hybu eich postiad", + "notification.reblog.name_and_others_with_link": "Mae {name} a {count, plural, one {# arall} other {# arall}} wedi hybu eich postiad", "notification.relationships_severance_event": "Wedi colli cysylltiad â {name}", "notification.relationships_severance_event.account_suspension": "Mae gweinyddwr o {from} wedi atal {target}, sy'n golygu na allwch dderbyn diweddariadau ganddynt mwyach na rhyngweithio â nhw.", "notification.relationships_severance_event.domain_block": "Mae gweinyddwr o {from} wedi blocio {target}, gan gynnwys {followersCount} o'ch dilynwyr a {followingCount, plural, one {# cyfrif} other {# cyfrif}} arall rydych chi'n ei ddilyn.", @@ -536,9 +541,9 @@ "notification.status": "{name} newydd ei bostio", "notification.update": "Golygodd {name} bostiad", "notification_requests.accept": "Derbyn", - "notification_requests.accept_multiple": "{count, plural, one {Accept # request…} other {Accept # requests…}}", - "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accept request} other {Accept requests}}", - "notification_requests.confirm_accept_multiple.message": "Rydych ar fin derbyn {count, plural, one {one notification request} other {# notification requests}}. Ydych chi'n siŵr eich bod am barhau?", + "notification_requests.accept_multiple": "{count, plural, one {Derbyn # cais…} other {Derbyn # cais…}}", + "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Derbyn cais} other {Derbyn cais}}", + "notification_requests.confirm_accept_multiple.message": "Rydych ar fin derbyn {count, plural, one {un cais hysbysiad} other {# cais hysbysiad}}. Ydych chi'n siŵr eich bod am barhau?", "notification_requests.confirm_accept_multiple.title": "Derbyn ceisiadau hysbysu?", "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Diystyru cais} other {Diystyru ceisiadau}}", "notification_requests.confirm_dismiss_multiple.message": "Rydych ar fin diystyru {count, plural, one {un cais hysbysu} other {# cais hysbysiad}}. Fyddwch chi ddim yn gallu cyrchu {count, plural, one {it} other {them}} yn hawdd eto. Ydych chi'n yn siŵr eich bod am fwrw ymlaen?", @@ -565,6 +570,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", @@ -686,7 +692,7 @@ "relative_time.minutes": "{number} munud", "relative_time.seconds": "{number} eiliad", "relative_time.today": "heddiw", - "reply_indicator.attachments": "{count, plural, one {# attachment} arall {# attachments}}", + "reply_indicator.attachments": "{count, plural, one {# atodiad} other {# atodiad}}", "reply_indicator.cancel": "Canslo", "reply_indicator.poll": "Arolwg", "report.block": "Blocio", @@ -729,7 +735,7 @@ "report.thanks.title_actionable": "Diolch am adrodd, byddwn yn ymchwilio i hyn.", "report.unfollow": "Dad-ddilyn @{name}", "report.unfollow_explanation": "Rydych chi'n dilyn y cyfrif hwn. I beidio â gweld eu postiadau yn eich ffrwd gartref mwyach, dad-ddilynwch nhw.", - "report_notification.attached_statuses": "{count, plural, one {{count} postiad} arall {{count} postiad}} atodwyd", + "report_notification.attached_statuses": "{count, plural, one {{count} postiad} other {{count} postiad}} wedi'i atodi", "report_notification.categories.legal": "Cyfreithiol", "report_notification.categories.legal_sentence": "cynnwys anghyfreithlon", "report_notification.categories.other": "Arall", @@ -809,7 +815,7 @@ "status.reblog": "Hybu", "status.reblog_private": "Hybu i'r gynulleidfa wreiddiol", "status.reblogged_by": "Hybodd {name}", - "status.reblogs": "{count, plural, one {hwb} other {hwb}}", + "status.reblogs": "{count, plural, one {# hwb} other {# hwb}}", "status.reblogs.empty": "Does neb wedi hybio'r post yma eto. Pan y bydd rhywun yn gwneud, byddent yn ymddangos yma.", "status.redraft": "Dileu ac ailddrafftio", "status.remove_bookmark": "Tynnu nod tudalen", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index e225bb30ae..5531576447 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -158,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", @@ -197,6 +196,7 @@ "confirmations.unfollow.title": "Følg ikke længere bruger?", "content_warning.hide": "Skjul indlæg", "content_warning.show": "Vis alligevel", + "content_warning.show_more": "Vis flere", "conversation.delete": "Slet samtale", "conversation.mark_as_read": "Markér som læst", "conversation.open": "Vis samtale", @@ -305,7 +305,7 @@ "filter_modal.select_filter.subtitle": "Vælg en eksisterende kategori eller opret en ny", "filter_modal.select_filter.title": "Filtrér dette indlæg", "filter_modal.title.status": "Filtrér et indlæg", - "filter_warning.matches_filter": "Matcher filteret “{title}”", + "filter_warning.matches_filter": "Matcher filteret “{title}”", "filtered_notifications_banner.pending_requests": "Fra {count, plural, =0 {ingen} one {én person} other {# personer}}, man måske kender", "filtered_notifications_banner.title": "Filtrerede notifikationer", "firehose.all": "Alle", @@ -385,6 +385,7 @@ "interaction_modal.description.follow": "Med en konto på Mastodon kan du følge {name} for at modtage vedkommendes indlæg i dit hjemmefeed.", "interaction_modal.description.reblog": "Med en konto på Mastodon kan dette indlæg fremhæves så det deles med egne følgere.", "interaction_modal.description.reply": "Med en konto på Mastodon kan dette indlæg besvares.", + "interaction_modal.description.vote": "Med en konto på Mastodon kan man deltage i denne afstemning.", "interaction_modal.login.action": "Gå til hjemmeserver", "interaction_modal.login.prompt": "Hjemmeserverdomænet, f.eks. mastodon.social", "interaction_modal.no_account_yet": "Ikke på Mastodon?", @@ -396,6 +397,7 @@ "interaction_modal.title.follow": "Følg {name}", "interaction_modal.title.reblog": "Boost {name}s indlæg", "interaction_modal.title.reply": "Besvar {name}s indlæg", + "interaction_modal.title.vote": "Deltag i {name}s afstemning", "intervals.full.days": "{number, plural, one {# dag} other {# dage}}", "intervals.full.hours": "{number, plural, one {# time} other {# timer}}", "intervals.full.minutes": "{number, plural, one {# minut} other {# minutter}}", @@ -508,7 +510,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", @@ -567,6 +569,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", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index b807d93ab3..d048a191e3 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Oha!", "alt_text_badge.title": "Bildbeschreibung", "announcement.announcement": "Ankündigung", + "annual_report.summary.archetype.booster": "Trendjäger*in", + "annual_report.summary.archetype.lurker": "Beobachter*in", + "annual_report.summary.archetype.oracle": "Orakel", + "annual_report.summary.archetype.pollster": "Meinungsforscher*in", + "annual_report.summary.archetype.replier": "Geselliger Schmetterling", + "annual_report.summary.followers.followers": "Follower", + "annual_report.summary.followers.total": "{count} insgesamt", + "annual_report.summary.here_it_is": "Dein Jahresrückblick für {year}:", + "annual_report.summary.highlighted_post.by_favourites": "am häufigsten favorisierter Beitrag", + "annual_report.summary.highlighted_post.by_reblogs": "am häufigsten geteilter Beitrag", + "annual_report.summary.highlighted_post.by_replies": "Beitrag mit den meisten Antworten", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "am häufigsten verwendete App", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "am häufigsten verwendeter Hashtag", + "annual_report.summary.new_posts.new_posts": "neue Beiträge", + "annual_report.summary.percentile.text": "Damit gehörst du zu den oberstender Mastodon-Nutzer*innen.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Wir werden Bernie nichts verraten.", + "annual_report.summary.thanks": "Danke, dass du Teil von Mastodon bist!", "attachments_list.unprocessed": "(ausstehend)", "audio.hide": "Audio ausblenden", "block_modal.remote_users_caveat": "Wir werden den Server {domain} bitten, deine Entscheidung zu respektieren. Allerdings kann nicht garantiert werden, dass sie eingehalten wird, weil einige Server Blockierungen unterschiedlich handhaben können. Öffentliche Beiträge können für nicht angemeldete Nutzer*innen weiterhin sichtbar sein.", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Profil entfolgen?", "content_warning.hide": "Beitrag ausblenden", "content_warning.show": "Trotzdem anzeigen", + "content_warning.show_more": "Mehr anzeigen", "conversation.delete": "Unterhaltung löschen", "conversation.mark_as_read": "Als gelesen markieren", "conversation.open": "Unterhaltung anzeigen", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Einem vorhandenen Filter hinzufügen oder einen neuen erstellen", "filter_modal.select_filter.title": "Diesen Beitrag filtern", "filter_modal.title.status": "Beitrag per Filter ausblenden", - "filter_warning.matches_filter": "Übereinstimmend mit dem Filter „{title}“", + "filter_warning.matches_filter": "Übereinstimmend mit dem Filter „{title}“", "filtered_notifications_banner.pending_requests": "Von {count, plural, =0 {keinem, den} one {einer Person, die} other {# Personen, die}} du möglicherweise kennst", "filtered_notifications_banner.title": "Gefilterte Benachrichtigungen", "firehose.all": "Alles", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Mit einem Mastodon-Konto kannst du {name} folgen, um die Beiträge auf deiner Startseite zu sehen.", "interaction_modal.description.reblog": "Mit einem Mastodon-Konto kannst du die Reichweite dieses Beitrags erhöhen, indem du ihn mit deinen Followern teilst.", "interaction_modal.description.reply": "Mit einem Mastodon-Konto kannst du auf diesen Beitrag antworten.", + "interaction_modal.description.vote": "Mit einem Mastodon-Konto kannst du an dieser Umfrage teilnehmen.", "interaction_modal.login.action": "Zurück zur Startseite", "interaction_modal.login.prompt": "Adresse deines Servers, z. B. mastodon.social", "interaction_modal.no_account_yet": "Nicht auf Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Folge {name}", "interaction_modal.title.reblog": "Beitrag von {name} teilen", "interaction_modal.title.reply": "Auf Beitrag von {name} antworten", + "interaction_modal.title.vote": "An der Umfrage von {name} teilnehmen", "intervals.full.days": "{number, plural, one {# Tag} other {# Tage}}", "intervals.full.hours": "{number, plural, one {# Stunde} other {# Stunden}}", "intervals.full.minutes": "{number, plural, one {# Minute} other {# Minuten}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} meldete {target}", "notification.admin.sign_up": "{name} registrierte sich", "notification.admin.sign_up.name_and_others": "{name} und {count, plural, one {# weitere Person} other {# weitere Personen}} registrierten sich", + "notification.annual_report.message": "Dein {year} #Wrapstodon erwartet dich! Lass deine Highlights und unvergesslichen Momente auf Mastodon erneut aufleben!", + "notification.annual_report.view": "#Wrapstodon ansehen", "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", @@ -567,6 +590,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", @@ -597,15 +621,15 @@ "notifications.policy.filter": "Filtern", "notifications.policy.filter_hint": "An gefilterte Benachrichtigungen im Posteingang senden", "notifications.policy.filter_limited_accounts_hint": "Durch Server-Moderator*innen eingeschränkt", - "notifications.policy.filter_limited_accounts_title": "Moderierte Konten", + "notifications.policy.filter_limited_accounts_title": "moderierten Konten", "notifications.policy.filter_new_accounts.hint": "Innerhalb {days, plural, one {des letzten Tages} other {der letzten # Tagen}} erstellt", - "notifications.policy.filter_new_accounts_title": "Neuen Konten", + "notifications.policy.filter_new_accounts_title": "neuen Konten", "notifications.policy.filter_not_followers_hint": "Einschließlich Profilen, die dir seit weniger als {days, plural, one {einem Tag} other {# Tagen}} folgen", "notifications.policy.filter_not_followers_title": "Profilen, die mir nicht folgen", "notifications.policy.filter_not_following_hint": "Bis du sie manuell genehmigst", "notifications.policy.filter_not_following_title": "Profilen, denen ich nicht folge", "notifications.policy.filter_private_mentions_hint": "Solange sie keine Antwort auf deine Erwähnung ist oder du dem Profil nicht folgst", - "notifications.policy.filter_private_mentions_title": "Unerwünschten privaten Erwähnungen", + "notifications.policy.filter_private_mentions_title": "unerwünschten privaten Erwähnungen", "notifications.policy.title": "Benachrichtigungen verwalten von …", "notifications_permission_banner.enable": "Aktiviere Desktop-Benachrichtigungen", "notifications_permission_banner.how_to_control": "Um Benachrichtigungen zu erhalten, wenn Mastodon nicht geöffnet ist, aktiviere die Desktop-Benachrichtigungen. Du kannst genau bestimmen, welche Arten von Interaktionen Desktop-Benachrichtigungen über die {icon} -Taste erzeugen, sobald diese aktiviert sind.", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 2565f5da68..40517f8340 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -158,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": "Στυλ", @@ -305,7 +304,6 @@ "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": "Όλα", @@ -508,7 +506,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": "Επισήμανση", diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index 1834dd82d5..4f7de62730 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -158,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", @@ -305,7 +304,6 @@ "filter_modal.select_filter.subtitle": "Use an existing category or create a new one", "filter_modal.select_filter.title": "Filter this post", "filter_modal.title.status": "Filter a post", - "filter_warning.matches_filter": "Matches filter “{title}”", "filtered_notifications_banner.pending_requests": "From {count, plural, =0 {no one} one {one person} other {# people}} you may know", "filtered_notifications_banner.title": "Filtered notifications", "firehose.all": "All", @@ -508,7 +506,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", @@ -791,7 +788,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}", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 6ce079c4e9..25143ebd79 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Oops!", "alt_text_badge.title": "Alt text", "announcement.announcement": "Announcement", + "annual_report.summary.archetype.booster": "The cool-hunter", + "annual_report.summary.archetype.lurker": "The lurker", + "annual_report.summary.archetype.oracle": "The oracle", + "annual_report.summary.archetype.pollster": "The pollster", + "annual_report.summary.archetype.replier": "The social butterfly", + "annual_report.summary.followers.followers": "followers", + "annual_report.summary.followers.total": "{count} total", + "annual_report.summary.here_it_is": "Here is your {year} in review:", + "annual_report.summary.highlighted_post.by_favourites": "most favourited post", + "annual_report.summary.highlighted_post.by_reblogs": "most boosted post", + "annual_report.summary.highlighted_post.by_replies": "post with the most replies", + "annual_report.summary.highlighted_post.possessive": "{name}'s", + "annual_report.summary.most_used_app.most_used_app": "most used app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "most used hashtag", + "annual_report.summary.new_posts.new_posts": "new posts", + "annual_report.summary.percentile.text": "That puts you in the topof Mastodon users.", + "annual_report.summary.percentile.we_wont_tell_bernie": "We won't tell Bernie.", + "annual_report.summary.thanks": "Thanks for being part of Mastodon!", "attachments_list.unprocessed": "(unprocessed)", "audio.hide": "Hide audio", "block_modal.remote_users_caveat": "We will ask the server {domain} to respect your decision. However, compliance is not guaranteed since some servers may handle blocks differently. Public posts may still be visible to non-logged-in users.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Unfollow user?", "content_warning.hide": "Hide post", "content_warning.show": "Show anyway", + "content_warning.show_more": "Show more", "conversation.delete": "Delete conversation", "conversation.mark_as_read": "Mark as read", "conversation.open": "View conversation", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Use an existing category or create a new one", "filter_modal.select_filter.title": "Filter this post", "filter_modal.title.status": "Filter a post", - "filter_warning.matches_filter": "Matches filter “{title}”", + "filter_warning.matches_filter": "Matches filter “{title}”", "filtered_notifications_banner.pending_requests": "From {count, plural, =0 {no one} one {one person} other {# people}} you may know", "filtered_notifications_banner.title": "Filtered notifications", "firehose.all": "All", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "With an account on Mastodon, you can follow {name} to receive their posts in your home feed.", "interaction_modal.description.reblog": "With an account on Mastodon, you can boost this post to share it with your own followers.", "interaction_modal.description.reply": "With an account on Mastodon, you can respond to this post.", + "interaction_modal.description.vote": "With an account on Mastodon, you can vote in this poll.", "interaction_modal.login.action": "Take me home", "interaction_modal.login.prompt": "Domain of your home server, e.g. mastodon.social", "interaction_modal.no_account_yet": "Not on Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Follow {name}", "interaction_modal.title.reblog": "Boost {name}'s post", "interaction_modal.title.reply": "Reply to {name}'s post", + "interaction_modal.title.vote": "Vote in {name}'s poll", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", @@ -505,11 +526,13 @@ "notification.admin.report_statuses_other": "{name} reported {target}", "notification.admin.sign_up": "{name} signed up", "notification.admin.sign_up.name_and_others": "{name} and {count, plural, one {# other} other {# others}} signed up", + "notification.annual_report.message": "Your {year} #Wrapstodon awaits! Unveil your year's highlights and memorable moments on Mastodon!", + "notification.annual_report.view": "View #Wrapstodon", "notification.favourite": "{name} favorited your post", "notification.reaction": "{name} reacted to 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", @@ -569,6 +592,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", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 5f6582fb68..757bb39866 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -2,7 +2,7 @@ "about.blocks": "Administritaj serviloj", "about.contact": "Kontakto:", "about.disclaimer": "Mastodon estas libera, malfermitkoda programo kaj varmarko de la firmao Mastodon gGmbH.", - "about.domain_blocks.no_reason_available": "Kialo ne disponebla", + "about.domain_blocks.no_reason_available": "Kialo ne disponeblas", "about.domain_blocks.preamble": "Mastodon ĝenerale rajtigas vidi la enhavojn de uzantoj el aliaj serviloj en la fediverso, kaj komuniki kun ili. Jen la limigoj deciditaj de tiu ĉi servilo mem.", "about.domain_blocks.silenced.explanation": "Vi ne ĝenerale vidos profilojn kaj enhavojn de ĉi tiu servilo, krom se vi eksplice trovas aŭ estas permesita de via sekvato.", "about.domain_blocks.silenced.title": "Limigita", @@ -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}", @@ -45,7 +45,7 @@ "account.languages": "Ŝanĝi la abonitajn lingvojn", "account.link_verified_on": "Propreco de tiu ligilo estis konfirmita je {date}", "account.locked_info": "Tiu konto estas privatigita. La posedanto mane akceptas tiun, kiu povas sekvi rin.", - "account.media": "Plurmedioj", + "account.media": "Plurmedio", "account.mention": "Mencii @{name}", "account.moved_to": "{name} indikis, ke ria nova konto estas nun:", "account.mute": "Silentigi @{name}", @@ -86,7 +86,12 @@ "alert.unexpected.message": "Neatendita eraro okazis.", "alert.unexpected.title": "Aj!", "alt_text_badge.title": "Alt-teksto", - "announcement.announcement": "Anoncoj", + "announcement.announcement": "Anonco", + "annual_report.summary.archetype.replier": "La plej societema", + "annual_report.summary.followers.followers": "sekvantoj", + "annual_report.summary.highlighted_post.by_replies": "afiŝo kun la plej multaj respondoj", + "annual_report.summary.new_posts.new_posts": "novaj afiŝoj", + "annual_report.summary.thanks": "Dankon pro esti parto de Mastodon!", "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.", @@ -105,13 +110,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", @@ -142,7 +147,7 @@ "column_header.unpin": "Malfiksi", "column_subheading.settings": "Agordoj", "community.column_settings.local_only": "Nur loka", - "community.column_settings.media_only": "Nur plurmedioj", + "community.column_settings.media_only": "Nur plurmedio", "community.column_settings.remote_only": "Nur fora", "compose.language.change": "Ŝanĝi lingvon", "compose.language.search": "Serĉi lingvojn...", @@ -158,7 +163,7 @@ "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", @@ -182,8 +187,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,8 +202,9 @@ "confirmations.unfollow.title": "Ĉu ĉesi sekvi uzanton?", "content_warning.hide": "Kaŝi afiŝon", "content_warning.show": "Montri ĉiukaze", + "content_warning.show_more": "Montri pli", "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", @@ -247,18 +253,18 @@ "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!", @@ -305,7 +311,7 @@ "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 afiŝon", - "filter_warning.matches_filter": "Filtrilo de kongruoj “{title}”", + "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", @@ -343,7 +349,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", @@ -385,6 +391,7 @@ "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 afiŝo.", + "interaction_modal.description.vote": "Kun konto ĉe Mastodon, vi povas voĉdoni en ĉi tiu balotenketo.", "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?", @@ -396,43 +403,44 @@ "interaction_modal.title.follow": "Sekvi {name}", "interaction_modal.title.reblog": "Akceli la afiŝon de {name}", "interaction_modal.title.reply": "Respondi al la afiŝo de {name}", + "interaction_modal.title.vote": "Voĉdonu en la balotenketo de {name}", "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 kolumnon", - "keyboard_shortcuts.compose": "enfokusigi la tekstujon", + "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.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.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": "malfermi la profilon de la aŭtoro", + "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": "Komencu novan afiŝon", - "keyboard_shortcuts.unfocus": "malenfokusigi la tekstujon aŭ la serĉilon", - "keyboard_shortcuts.up": "iri supren en la listo", + "keyboard_shortcuts.unfocus": "Senfokusigi verki tekstareon/serĉon", + "keyboard_shortcuts.up": "Movu supren en la listo", "lightbox.close": "Fermi", "lightbox.next": "Antaŭen", "lightbox.previous": "Malantaŭen", @@ -505,10 +513,11 @@ "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.annual_report.view": "Vidu #Wrapstodon", "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.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", @@ -526,7 +535,7 @@ "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.own_poll": "Via balotenketo finiĝitis", "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", @@ -567,6 +576,7 @@ "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": "Grupigi", "notifications.column_settings.mention": "Mencioj:", "notifications.column_settings.poll": "Balotenketaj rezultoj:", "notifications.column_settings.push": "Puŝsciigoj", @@ -612,8 +622,8 @@ "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": "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:", @@ -633,17 +643,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.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.", @@ -657,7 +667,7 @@ "poll.total_people": "{count, plural, one {# homo} other {# homoj}}", "poll.total_votes": "{count, plural, one {# voĉdono} other {# voĉdonoj}}", "poll.vote": "Voĉdoni", - "poll.voted": "Vi elektis por ĉi tiu respondo", + "poll.voted": "Vi voĉdonis por ĉi tiu respondo", "poll.votes": "{votes, plural, one {# voĉdono} other {# voĉdonoj}}", "poll_button.add_poll": "Aldoni balotenketon", "poll_button.remove_poll": "Forigi balotenketon", @@ -825,7 +835,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", @@ -848,7 +858,7 @@ "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", @@ -871,17 +881,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 7fec88a96e..a556d90e33 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "¡Epa!", "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "El cazador de tendencias", + "annual_report.summary.archetype.lurker": "El acechador", + "annual_report.summary.archetype.oracle": "El oráculo", + "annual_report.summary.archetype.pollster": "El encuestador", + "annual_report.summary.archetype.replier": "El más sociable", + "annual_report.summary.followers.followers": "seguidores", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "Aquí está tu resumen de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "publicación con más favoritos", + "annual_report.summary.highlighted_post.by_reblogs": "publicación más impulsada", + "annual_report.summary.highlighted_post.by_replies": "publicación con más respuestas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "aplicación más usada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "etiqueta más usada", + "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", + "annual_report.summary.percentile.text": "Eso te pone en el topde usuarios de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", + "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "[sin procesar]", "audio.hide": "Ocultar audio", "block_modal.remote_users_caveat": "Le pediremos al servidor {domain} que respete tu decisión. Sin embargo, el cumplimiento no está garantizado, ya que algunos servidores pueden manejar los bloqueos de forma diferente. Los mensajes públicos todavía podrían estar visibles para los usuarios no conectados.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "¿Dejar de seguir al usuario?", "content_warning.hide": "Ocultar mensaje", "content_warning.show": "Mostrar de todos modos", + "content_warning.show_more": "Mostrar más", "conversation.delete": "Eliminar conversación", "conversation.mark_as_read": "Marcar como leída", "conversation.open": "Ver conversación", @@ -249,7 +268,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", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva", "filter_modal.select_filter.title": "Filtrar este mensaje", "filter_modal.title.status": "Filtrar un mensaje", - "filter_warning.matches_filter": "Coincide con el filtro “{title}”", + "filter_warning.matches_filter": "Coincide con el filtro “{title}”", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que podrías conocer", "filtered_notifications_banner.title": "Notificaciones filtradas", "firehose.all": "Todos", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Con una cuenta en Mastodon, podés seguir a {name} para recibir sus mensajes en tu línea temporal principal.", "interaction_modal.description.reblog": "Con una cuenta en Mastodon, podés adherir a este mensaje para compartirlo con tus propios seguidores.", "interaction_modal.description.reply": "Con una cuenta en Mastodon, podés responder a este mensaje.", + "interaction_modal.description.vote": "Con una cuenta en Mastodon, podés votar en esta encuesta.", "interaction_modal.login.action": "Llevame al comienzo", "interaction_modal.login.prompt": "Dominio de su servidor de inicio, p. ej., mastodon.social", "interaction_modal.no_account_yet": "¿No tenés cuenta en Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Seguir a {name}", "interaction_modal.title.reblog": "Adherir al mensaje de {name}", "interaction_modal.title.reply": "Responder al mensaje de {name}", + "interaction_modal.title.vote": "Votá en la encuesta de {name}", "intervals.full.days": "{number, plural, one {# día} other {# días}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} denunció a {target}", "notification.admin.sign_up": "Se registró {name}", "notification.admin.sign_up.name_and_others": "Se registraron {name} y {count, plural, one {# cuenta más} other {# cuentas más}}", + "notification.annual_report.message": "¡Tu #Wrapstodon {year} te espera! ¡Desvela los momentos más destacados y memorables de tu año en Mastodon!", + "notification.annual_report.view": "Ver #Wrapstodon", "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", @@ -567,6 +590,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", @@ -855,7 +879,7 @@ "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_end": "El archivo adjunto {item} fue soltado.", "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", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index ddfdf6960b..4faa35e5c8 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "¡Ups!", "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "El cazador de tendencias", + "annual_report.summary.archetype.lurker": "El acechador", + "annual_report.summary.archetype.oracle": "El oráculo", + "annual_report.summary.archetype.pollster": "El encuestador", + "annual_report.summary.archetype.replier": "El más sociable", + "annual_report.summary.followers.followers": "seguidores", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "Aquí está tu resumen de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "publicación con más favoritos", + "annual_report.summary.highlighted_post.by_reblogs": "publicación más impulsada", + "annual_report.summary.highlighted_post.by_replies": "publicación con más respuestas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "aplicación más usada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "etiqueta más usada", + "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", + "annual_report.summary.percentile.text": "Eso te pone en el topde usuarios de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", + "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", "block_modal.remote_users_caveat": "Le pediremos al servidor {domain} que respete tu decisión. Sin embargo, el cumplimiento no está garantizado ya que algunos servidores pueden manejar bloques de forma diferente. Las publicaciones públicas pueden ser todavía visibles para los usuarios no conectados.", @@ -158,9 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "¿Dejar de seguir al usuario?", "content_warning.hide": "Ocultar publicación", "content_warning.show": "Mostrar de todos modos", + "content_warning.show_more": "Mostrar más", "conversation.delete": "Borrar conversación", "conversation.mark_as_read": "Marcar como leído", "conversation.open": "Ver conversación", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva", "filter_modal.select_filter.title": "Filtrar esta publicación", "filter_modal.title.status": "Filtrar una publicación", - "filter_warning.matches_filter": "Coincide con el filtro “{title}”", + "filter_warning.matches_filter": "Coincide con el filtro “{title}”", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# people}} que puede que tú conozcas", "filtered_notifications_banner.title": "Notificaciones filtradas", "firehose.all": "Todas", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Con una cuenta en Mastodon, puedes seguir {name} para recibir sus publicaciones en tu fuente de inicio.", "interaction_modal.description.reblog": "Con una cuenta en Mastodon, puedes impulsar esta publicación para compartirla con tus propios seguidores.", "interaction_modal.description.reply": "Con una cuenta en Mastodon, puedes responder a esta publicación.", + "interaction_modal.description.vote": "Con una cuenta en Mastodon, puedes votar en esta encuesta.", "interaction_modal.login.action": "Ir a Inicio", "interaction_modal.login.prompt": "Dominio de tu servidor, por ejemplo: mastodon.social", "interaction_modal.no_account_yet": "¿Aún no tienes cuenta en Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Seguir a {name}", "interaction_modal.title.reblog": "Impulsar la publicación de {name}", "interaction_modal.title.reply": "Responder la publicación de {name}", + "interaction_modal.title.vote": "Votar en la encuesta de {name}", "intervals.full.days": "{number, plural, one {# día} other {# días}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} reportó {target}", "notification.admin.sign_up": "{name} se unio", "notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# otro} other {# otros}} se registraron", + "notification.annual_report.message": "¡Tu #Wrapstodon {year} te espera! ¡Desvela los momentos más destacados y memorables de tu año en Mastodon!", + "notification.annual_report.view": "Ver #Wrapstodon", "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", @@ -516,7 +539,7 @@ "notification.label.private_reply": "Respuesta privada", "notification.label.reply": "Respuesta", "notification.mention": "Mención", - "notification.mentioned_you": "{name} te ha mencionado", + "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.", @@ -567,6 +590,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", @@ -644,7 +668,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!", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 2aeb7d47ea..d14b718016 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "¡Ups!", "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Anuncio", + "annual_report.summary.archetype.booster": "El cazador de tendencias", + "annual_report.summary.archetype.lurker": "El acechador", + "annual_report.summary.archetype.oracle": "El oráculo", + "annual_report.summary.archetype.pollster": "El encuestador", + "annual_report.summary.archetype.replier": "El más sociable", + "annual_report.summary.followers.followers": "seguidores", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "Aquí está tu resumen de {year}:", + "annual_report.summary.highlighted_post.by_favourites": "publicación con más favoritos", + "annual_report.summary.highlighted_post.by_reblogs": "publicación más impulsada", + "annual_report.summary.highlighted_post.by_replies": "publicación con más respuestas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "aplicación más usada", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "etiqueta más usada", + "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", + "annual_report.summary.percentile.text": "Eso te pone en el topde usuarios de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", + "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", "block_modal.remote_users_caveat": "Le pediremos al servidor {domain} que respete tu decisión. Sin embargo, el cumplimiento no está garantizado, ya que algunos servidores pueden manejar bloqueos de forma distinta. Los mensajes públicos pueden ser todavía visibles para los usuarios que no hayan iniciado sesión.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "¿Dejar de seguir al usuario?", "content_warning.hide": "Ocultar publicación", "content_warning.show": "Mostrar de todos modos", + "content_warning.show_more": "Mostrar más", "conversation.delete": "Borrar conversación", "conversation.mark_as_read": "Marcar como leído", "conversation.open": "Ver conversación", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Usar una categoría existente o crear una nueva", "filter_modal.select_filter.title": "Filtrar esta publicación", "filter_modal.title.status": "Filtrar una publicación", - "filter_warning.matches_filter": "Coincide con el filtro “{title}”", + "filter_warning.matches_filter": "Coincide con el filtro “{title}”", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {nadie} one {una persona} other {# personas}} que puede que conozcas", "filtered_notifications_banner.title": "Notificaciones filtradas", "firehose.all": "Todas", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Con una cuenta en Mastodon, puedes seguir {name} para recibir sus publicaciones en tu línea temporal de inicio.", "interaction_modal.description.reblog": "Con una cuenta en Mastodon, puedes impulsar esta publicación para compartirla con tus propios seguidores.", "interaction_modal.description.reply": "Con una cuenta en Mastodon, puedes responder a esta publicación.", + "interaction_modal.description.vote": "Con una cuenta en Mastodon, puedes votar en esta encuesta.", "interaction_modal.login.action": "Ir a Inicio", "interaction_modal.login.prompt": "Dominio de tu servidor, por ejemplo mastodon.social", "interaction_modal.no_account_yet": "¿Aún no tienes cuenta en Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Seguir a {name}", "interaction_modal.title.reblog": "Impulsar la publicación de {name}", "interaction_modal.title.reply": "Responder a la publicación de {name}", + "interaction_modal.title.vote": "Vota en la encuesta de {name}", "intervals.full.days": "{number, plural, one {# día} other {# días}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} informó de {target}", "notification.admin.sign_up": "{name} se registró", "notification.admin.sign_up.name_and_others": "{name} y {count, plural, one {# más} other {# más}} se registraron", + "notification.annual_report.message": "¡Tu #Wrapstodon {year} te espera! ¡Desvela los momentos más destacados y memorables de tu año en Mastodon!", + "notification.annual_report.view": "Ver #Wrapstodon", "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", @@ -567,6 +590,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 votación:", "notifications.column_settings.push": "Notificaciones push", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 69df3c4140..8376641179 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,7 @@ "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.single": "Üks valik", "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", @@ -196,6 +197,7 @@ "confirmations.unfollow.title": "Ei jälgi enam kasutajat?", "content_warning.hide": "Peida postitus", "content_warning.show": "Näita ikkagi", + "content_warning.show_more": "Näita rohkem", "conversation.delete": "Kustuta vestlus", "conversation.mark_as_read": "Märgi loetuks", "conversation.open": "Vaata vestlust", @@ -221,6 +223,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_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.", @@ -302,7 +306,7 @@ "filter_modal.select_filter.subtitle": "Kasuta olemasolevat kategooriat või loo uus", "filter_modal.select_filter.title": "Filtreeri seda postitust", "filter_modal.title.status": "Postituse filtreerimine", - "filter_warning.matches_filter": "Sobib filtriga “{title}”", + "filter_warning.matches_filter": "Sobib filtriga “{title}”", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Mitte üheltki inimeselt} one {Ühelt inimeselt} other {# inimeselt}}, keda võid teada", "filtered_notifications_banner.title": "Filtreeritud teavitused", "firehose.all": "Kõik", @@ -382,6 +386,7 @@ "interaction_modal.description.follow": "Mastodoni kontoga saad jälgida kasutajat {name}, et tema postitusi oma koduvoos näha.", "interaction_modal.description.reblog": "Mastodoni kontoga saad seda postitust levitada, jagades seda oma jälgijatele.", "interaction_modal.description.reply": "Mastodoni kontoga saad sellele postitusele vastata.", + "interaction_modal.description.vote": "Mastodoni kontoga saad sellest küsitlusest osa võtta.", "interaction_modal.login.action": "Vii mind avalehele", "interaction_modal.login.prompt": "Sinu koduserveri domeen, näiteks mastodon.social", "interaction_modal.no_account_yet": "Pole Mastodonis?", @@ -393,6 +398,7 @@ "interaction_modal.title.follow": "Jälgi kontot {name}", "interaction_modal.title.reblog": "Jaga {name} postitust", "interaction_modal.title.reply": "Vasta kasutaja {name} postitusele", + "interaction_modal.title.vote": "Hääleta {name} küsitluses", "intervals.full.days": "{number, plural, one {# päev} other {# päeva}}", "intervals.full.hours": "{number, plural, one {# tund} other {# tundi}}", "intervals.full.minutes": "{number, plural, one {# minut} other {# minutit}}", @@ -433,6 +439,8 @@ "lightbox.close": "Sulge", "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", @@ -503,7 +511,7 @@ "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.name_and_others": "{name} ja veel {count, plural, one {# kasutaja} other {# kasutajat}} 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", @@ -511,6 +519,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.", @@ -561,6 +570,7 @@ "notifications.column_settings.filter_bar.category": "Kiirfiltri riba", "notifications.column_settings.follow": "Uued jälgijad:", "notifications.column_settings.follow_request": "Uued jälgimistaotlused:", + "notifications.column_settings.group": "Grupp", "notifications.column_settings.mention": "Mainimised:", "notifications.column_settings.poll": "Küsitluse tulemused:", "notifications.column_settings.push": "Push teated", @@ -847,6 +857,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 63449e9342..c8349dc6a1 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -158,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", @@ -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.", @@ -303,7 +302,6 @@ "filter_modal.select_filter.subtitle": "Hautatu lehendik dagoen kategoria bat edo sortu berria", "filter_modal.select_filter.title": "Iragazi bidalketa hau", "filter_modal.title.status": "Iragazi bidalketa bat", - "filter_warning.matches_filter": "“{title}” iragazkiarekin bat dator", "filtered_notifications_banner.pending_requests": "Ezagutu dezakezun {count, plural, =0 {inoren} one {pertsona baten} other {# pertsonen}}", "filtered_notifications_banner.title": "Iragazitako jakinarazpenak", "firehose.all": "Guztiak", @@ -504,7 +502,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", @@ -597,7 +594,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 d510c2a6a4..3bc96cf9f2 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -158,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": "سبک", @@ -196,7 +196,7 @@ "confirmations.unfollow.message": "مطمئنید که می‌خواهید به پی‌گیری از {name} پایان دهید؟", "confirmations.unfollow.title": "ناپی‌گیری کاربر؟", "content_warning.hide": "نهفتن فرسته", - "content_warning.show": "نمایش به هر روی", + "content_warning.show": "در هر صورت نشان داده شود", "conversation.delete": "حذف گفتگو", "conversation.mark_as_read": "علامت‌گذاری به عنوان خوانده شده", "conversation.open": "دیدن گفتگو", @@ -222,6 +222,7 @@ "domain_block_modal.they_cant_follow": "هیچ‌کسی از این کارساز نمی‌تواند پیتان بگیرد.", "domain_block_modal.they_wont_know": "نخواهند دانست که مسدود شده‌اند.", "domain_block_modal.title": "انسداد دامنه؟", + "domain_block_modal.you_will_lose_num_followers": "تعداد {followersCount, plural,other {{followersCount}}} پی‌گیرنده و {followingCount, plural,other {{followingCount}}} شخص پی‌گرفته شده را از دست خواهید داد.", "domain_block_modal.you_will_lose_relationships": "شما تمام پیگیرکنندگان و افرادی که از این کارساز پیگیری می‌کنید را از دست خواهید داد.", "domain_block_modal.you_wont_see_posts": "فرسته‌ها یا آگاهی‌ها از کاربران روی این کارساز را نخواهید دید.", "domain_pill.activitypub_lets_connect": "این به شما اجازه می‌دهد تا نه تنها در ماستودون، بلکه در برنامه‌های اجتماعی مختلف نیز با افراد ارتباط برقرار کرده و تعامل داشته باشید.", @@ -303,7 +304,6 @@ "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": "همه", @@ -368,11 +368,13 @@ "home.pending_critical_update.link": "دیدن به‌روز رسانی‌ها", "home.pending_critical_update.title": "به‌روز رسانی امنیتی بحرانی موجود است!", "home.show_announcements": "نمایش اعلامیه‌ها", + "ignore_notifications_modal.filter_instead": "به جایش پالوده شود", "ignore_notifications_modal.ignore": "چشم‌پوشی از آگاهی‌ها", "ignore_notifications_modal.limited_accounts_title": "چشم‌پوشی از آگاهی‌های حساب‌های نظارت شده؟", "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": "با حسابی روی ماستودون می‌توانید این فرسته را با پی‌گیران خودتان هم‌رسانی کنید.", @@ -428,6 +430,8 @@ "lightbox.close": "بستن", "lightbox.next": "بعدی", "lightbox.previous": "قبلی", + "lightbox.zoom_in": "بزرگ‌نمایی به اندازهٔ اصلی", + "lightbox.zoom_out": "بزرگ نمایی برای برازش", "limited_account_hint.action": "به هر روی نمایه نشان داده شود", "limited_account_hint.title": "این نمایه از سوی ناظم‌های {domain} پنهان شده.", "link_preview.author": "از {name}", @@ -455,6 +459,7 @@ "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": "فرسته‌هایی که به او اشاره کرده‌اند را نخواهید دید.", @@ -494,7 +499,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, other {#}} نفر دیگر پیتان گرفتند", "notification.follow_request": "{name} درخواست پی‌گیریتان را داد", "notification.follow_request.name_and_others": "{name} و {count, plural, one {# نفر دیگر} other {# نفر دیگر}} درخواست پی‌گیریتان را دادند", "notification.label.mention": "اشاره", @@ -502,6 +507,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": "برخی از فرسته‌هایتان برداشته شدند.", @@ -520,7 +526,10 @@ "notification.status": "{name} چیزی فرستاد", "notification.update": "{name} فرسته‌ای را ویرایش کرد", "notification_requests.accept": "پذیرش", + "notification_requests.confirm_accept_multiple.button": "پذیرش {count, plural,one {درخواست} other {درخواست‌ها}}", + "notification_requests.confirm_accept_multiple.message": "در حال پذیرش {count, plural,one {یک}other {#}} درخواست آگاهی هستید. مطمئنید که می‌خواهید ادامه دهید؟", "notification_requests.confirm_accept_multiple.title": "پذیرش درخواست‌های آگاهی؟", + "notification_requests.confirm_dismiss_multiple.button": "رد {count, plural,one {درخواست} other {درخواست‌ها}}", "notification_requests.confirm_dismiss_multiple.title": "رد کردن درخواست‌های آگاهی؟", "notification_requests.dismiss": "دورانداختن", "notification_requests.edit_selection": "ویرایش", @@ -541,6 +550,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": "آگاهی‌های ارسالی", @@ -554,7 +564,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": "به‌روز رسانی‌ها از کسانی که پی‌گیرشانید", @@ -572,10 +582,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} بالا واپایید.", @@ -592,7 +606,7 @@ "onboarding.profile.discoverable_hint": "خواسته‌اید روی ماستودون کشف شوید. ممکن است فرسته‌هایتان در نتیحهٔ جست‌وجوها و فرسته‌های داغ ظاهر شده و نمایه‌تان به افرادی با علایق مشابهتان پیشنهاد شود.", "onboarding.profile.display_name": "نام نمایشی", "onboarding.profile.display_name_hint": "نام کامل یا نام باحالتان…", - "onboarding.profile.lead": "همواره می‌توانید این مورد را در تنظیمات که گزینه‌ّای شخصی سازی بیش‌تری نیز دارد کامل کنید.", + "onboarding.profile.lead": "همواره می‌توانید این مورد را در تنظیمات که گزینه‌های شخصی سازی بیش‌تری نیز دارد کامل کنید.", "onboarding.profile.note": "درباره شما", "onboarding.profile.note_hint": "می‌توانید افراد دیگر را @نام‌بردن یا #برچسب بزنید…", "onboarding.profile.save_and_continue": "ذخیره کن و ادامه بده", @@ -757,6 +771,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": "پالایش این فرسته", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index ac7ab097fa..32069b1a03 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -87,6 +87,11 @@ "alert.unexpected.title": "Hups!", "alt_text_badge.title": "Vaihtoehtoinen teksti", "announcement.announcement": "Tiedote", + "annual_report.summary.archetype.replier": "Sosiaalinen perhonen", + "annual_report.summary.highlighted_post.by_reblogs": "tehostetuin julkaisu", + "annual_report.summary.most_used_app.most_used_app": "käytetyin sovellus", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "käytetyin aihetunniste", + "annual_report.summary.thanks": "Kiitos, että olet osa Mastodonia!", "attachments_list.unprocessed": "(käsittelemätön)", "audio.hide": "Piilota ääni", "block_modal.remote_users_caveat": "Pyydämme palvelinta {domain} kunnioittamaan päätöstäsi. Myötämielisyyttä ei kuitenkaan taata, koska jotkin palvelimet voivat käsitellä estoja eri tavalla. Julkiset julkaisut voivat silti näkyä kirjautumattomille käyttäjille.", @@ -158,7 +163,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", @@ -197,6 +202,7 @@ "confirmations.unfollow.title": "Lopetetaanko käyttäjän seuraaminen?", "content_warning.hide": "Piilota julkaisu", "content_warning.show": "Näytä kuitenkin", + "content_warning.show_more": "Näytä lisää", "conversation.delete": "Poista keskustelu", "conversation.mark_as_read": "Merkitse luetuksi", "conversation.open": "Näytä keskustelu", @@ -305,7 +311,7 @@ "filter_modal.select_filter.subtitle": "Käytä olemassa olevaa luokkaa tai luo uusi", "filter_modal.select_filter.title": "Suodata tämä julkaisu", "filter_modal.title.status": "Suodata julkaisu", - "filter_warning.matches_filter": "Vastaa suodatinta ”{title}”", + "filter_warning.matches_filter": "Vastaa suodatinta ”{title}”", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Ei keneltäkään, jonka} one {Yhdeltä käyttäjältä, jonka} other {# käyttäjältä, jotka}} saatat tuntea", "filtered_notifications_banner.title": "Suodatetut ilmoitukset", "firehose.all": "Kaikki", @@ -385,6 +391,7 @@ "interaction_modal.description.follow": "Mastodon-tilillä voit seurata käyttäjää {name} saadaksesi hänen julkaisunsa kotisyötteeseesi.", "interaction_modal.description.reblog": "Mastodon-tilillä voit tehostaa tätä julkaisua jakaaksesi sen seuraajiesi kanssa.", "interaction_modal.description.reply": "Mastodon-tilillä voit vastata tähän julkaisuun.", + "interaction_modal.description.vote": "Mastodon-tilillä voit osallistua tähän äänestykseen.", "interaction_modal.login.action": "Siirry kotiin", "interaction_modal.login.prompt": "Kotipalvelimesi verkkotunnus, kuten mastodon.social", "interaction_modal.no_account_yet": "Etkö ole vielä Mastodonissa?", @@ -396,6 +403,7 @@ "interaction_modal.title.follow": "Seuraa käyttäjää {name}", "interaction_modal.title.reblog": "Tehosta käyttäjän {name} julkaisua", "interaction_modal.title.reply": "Vastaa käyttäjän {name} julkaisuun", + "interaction_modal.title.vote": "Osallistu käyttäjän {name} äänestykseen", "intervals.full.days": "{number, plural, one {# päivä} other {# päivää}}", "intervals.full.hours": "{number, plural, one {# tunti} other {# tuntia}}", "intervals.full.minutes": "{number, plural, one {# minuutti} other {# minuuttia}}", @@ -436,8 +444,8 @@ "lightbox.close": "Sulje", "lightbox.next": "Seuraava", "lightbox.previous": "Edellinen", - "lightbox.zoom_in": "Zoomaa todelliseen kokoon", - "lightbox.zoom_out": "Zoomaa mahtumaan", + "lightbox.zoom_in": "Näytä todellisen kokoisena", + "lightbox.zoom_out": "Näytä sovitettuna", "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}", @@ -505,10 +513,11 @@ "notification.admin.report_statuses_other": "{name} raportoi käyttäjän {target}", "notification.admin.sign_up": "{name} rekisteröityi", "notification.admin.sign_up.name_and_others": "{name} ja {count, plural, one {# muu} other {# muuta}} rekisteröityivät", + "notification.annual_report.view": "Näytä #Wrapstodon", "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", @@ -567,6 +576,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", diff --git a/app/javascript/mastodon/locales/fil.json b/app/javascript/mastodon/locales/fil.json index 40292c2691..14c7b70bd2 100644 --- a/app/javascript/mastodon/locales/fil.json +++ b/app/javascript/mastodon/locales/fil.json @@ -46,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", @@ -56,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", @@ -107,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", @@ -122,7 +129,9 @@ "confirmations.discard_edit_media.confirm": "Ipagpaliban", "confirmations.edit.confirm": "Baguhin", "confirmations.reply.confirm": "Tumugon", + "content_warning.show_more": "Magpakita ng higit pa", "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", @@ -176,17 +185,20 @@ "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", "explore.trending_links": "Mga balita", "filter_modal.select_filter.search": "Hanapin o gumawa", + "filter_warning.matches_filter": "Tinutugma ang pangsala \"{title}\"", "firehose.all": "Lahat", "firehose.local": "Itong serbiro", "firehose.remote": "Ibang mga serbiro", "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", @@ -196,6 +208,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", @@ -207,6 +220,7 @@ "interaction_modal.on_another_server": "Sa ibang serbiro", "interaction_modal.on_this_server": "Sa serbirong ito", "interaction_modal.title.follow": "Sundan si {name}", + "interaction_modal.title.vote": "Bumoto sa botohan ni {name}", "intervals.full.days": "{number, plural, one {# araw} other {# na araw}}", "intervals.full.hours": "{number, plural, one {# oras} other {# na oras}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# na minuto}}", @@ -223,11 +237,14 @@ "lists.account.add": "Idagdag sa talaan", "lists.account.remove": "Tanggalin mula sa 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", @@ -242,16 +259,22 @@ "navigation_bar.search": "Maghanap", "notification.admin.report": "Iniulat ni {name} si {target}", "notification.follow": "Sinundan ka ni {name}", + "notification.follow.name_and_others": "Sinundan ka ng/nina {name} at {count, plural, one {# iba pa} other {# na iba pa}}", "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:", "notifications.column_settings.follow": "Mga bagong tagasunod:", + "notifications.column_settings.group": "Pangkat", "notifications.column_settings.poll": "Resulta ng botohan:", "notifications.column_settings.unread_notifications.category": "Hindi Nabasang mga Abiso", "notifications.column_settings.update": "Mga pagbago:", @@ -259,6 +282,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", @@ -275,6 +300,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", @@ -286,6 +315,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", @@ -293,9 +323,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?", @@ -342,5 +374,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 5ad8ba557b..6b26ed84fd 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Annar tekstur", "announcement.announcement": "Kunngerð", + "annual_report.summary.archetype.booster": "Kuli jagarin", + "annual_report.summary.archetype.lurker": "Lúrarin", + "annual_report.summary.archetype.oracle": "Oraklið", + "annual_report.summary.archetype.pollster": "Spyrjarin", + "annual_report.summary.archetype.replier": "Sosiali firvaldurin", + "annual_report.summary.followers.followers": "fylgjarar", + "annual_report.summary.followers.total": "{count} íalt", + "annual_report.summary.here_it_is": "Her er ein samandráttur av {year}:", + "annual_report.summary.highlighted_post.by_favourites": "mest dámdi postur", + "annual_report.summary.highlighted_post.by_reblogs": "oftast lyfti postur", + "annual_report.summary.highlighted_post.by_replies": "postur við flestum svarum", + "annual_report.summary.highlighted_post.possessive": "hjá {name}", + "annual_report.summary.most_used_app.most_used_app": "mest brúkta app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest brúkta frámerki", + "annual_report.summary.new_posts.new_posts": "nýggir postar", + "annual_report.summary.percentile.text": "Tað fær teg í toppav Mastodon brúkarum.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Vit fara ikki at fortelja Bernie tað.", + "annual_report.summary.thanks": "Takk fyri at tú er partur av Mastodon!", "attachments_list.unprocessed": "(óviðgjørt)", "audio.hide": "Fjal ljóð", "block_modal.remote_users_caveat": "Vit biðja ambætaran {domain} virða tína avgerð. Kortini er eingin vissa um samsvar, av tí at fleiri ambætarar handfara blokkar ymiskt. Almennir postar kunnu framvegis vera sjónligir fyri brúkarar, sum ikki eru innritaðir.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Gevst at fylgja brúkara?", "content_warning.hide": "Fjal post", "content_warning.show": "Vís kortini", + "content_warning.show_more": "Vís meiri", "conversation.delete": "Strika samrøðu", "conversation.mark_as_read": "Merk sum lisið", "conversation.open": "Vís samrøðu", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Brúka ein verandi bólk ella skapa ein nýggjan", "filter_modal.select_filter.title": "Filtrera hendan postin", "filter_modal.title.status": "Filtrera ein post", - "filter_warning.matches_filter": "Samsvarar við filtrið “{title}”", + "filter_warning.matches_filter": "Samsvarar við filtrið “{title}”", "filtered_notifications_banner.pending_requests": "Frá {count, plural, =0 {ongum} one {einum persóni} other {# persónum}}, sum tú kanska kennir", "filtered_notifications_banner.title": "Filtreraðar fráboðanir", "firehose.all": "Allar", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Við eini kontu á Mastodon kanst tú fylgja {name} fyri at síggja teirra postar á tíni heimarás.", "interaction_modal.description.reblog": "Við eini kontu á Mastodon kanst tú stimbra hendan postin og soleiðis deila hann við tínar fylgjarar.", "interaction_modal.description.reply": "Við eini kontu á Mastodon, so kanst tú svara hesum posti.", + "interaction_modal.description.vote": "Við eini kontu á Mastodon, so kanst tú atkvøða í hesi spurnarkanningini.", "interaction_modal.login.action": "Tak meg heim", "interaction_modal.login.prompt": "Navnaøki hjá tínum heimaambætara, t.d. mastodon.social", "interaction_modal.no_account_yet": "Ikki á Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Fylg {name}", "interaction_modal.title.reblog": "Stimbra postin hjá {name}", "interaction_modal.title.reply": "Svara postinum hjá {name}", + "interaction_modal.title.vote": "Atkvøði í spurnarkanningini hjá {name}", "intervals.full.days": "{number, plural, one {# dagur} other {# dagar}}", "intervals.full.hours": "{number, plural, one {# tími} other {# tímar}}", "intervals.full.minutes": "{number, plural, one {# minuttur} other {# minuttir}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} meldaði {target}", "notification.admin.sign_up": "{name} meldaði seg til", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# annar/onnur} other {# onnur}} teknaðu seg", + "notification.annual_report.message": "Títt {year} #Wrapstodon bíðar! Avdúka hæddarpunktini og minniligu løturnar á Mastodon!", + "notification.annual_report.view": "Sí #Wrapstodon", "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", @@ -567,6 +590,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", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 3349be4fad..65bbc25c21 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -89,7 +89,7 @@ "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.", @@ -194,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", @@ -224,7 +224,7 @@ "domain_block_modal.title": "Bloquer le domaine ?", "domain_block_modal.you_will_lose_num_followers": "Vous allez perdre {followersCount, plural, one {{followersCountDisplay} abonné·e} other {{followersCountDisplay} abonné·e·s}} et {followingCount, plural, one {{followingCountDisplay} personne que vous suivez} other {{followingCountDisplay} personnes que vous suivez}}.", "domain_block_modal.you_will_lose_relationships": "Vous allez perdre tous les abonné·e·s et les personnes que vous suivez sur ce serveur.", - "domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.", + "domain_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", @@ -305,7 +305,6 @@ "filter_modal.select_filter.subtitle": "Utilisez une catégorie existante ou en créer une nouvelle", "filter_modal.select_filter.title": "Filtrer cette publication", "filter_modal.title.status": "Filtrer une publication", - "filter_warning.matches_filter": "Correspond au filtre « {title} »", "filtered_notifications_banner.pending_requests": "De la part {count, plural, =0 {d’aucune personne} one {d'une personne} other {de # personnes}} que vous pourriez connaître", "filtered_notifications_banner.title": "Notifications filtrées", "firehose.all": "Tout", @@ -508,7 +507,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", @@ -516,6 +515,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.", @@ -542,12 +542,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", @@ -566,6 +566,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", @@ -853,6 +854,8 @@ "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.drag_and_drop.on_drag_over": "La pièce jointe du média {item} a été déplacé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 5c4e582a87..ed751c244b 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -79,7 +79,7 @@ "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é", @@ -89,7 +89,7 @@ "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.", @@ -194,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", @@ -224,7 +224,7 @@ "domain_block_modal.title": "Bloquer le domaine ?", "domain_block_modal.you_will_lose_num_followers": "Vous allez perdre {followersCount, plural, one {{followersCountDisplay} abonné·e} other {{followersCountDisplay} abonné·e·s}} et {followingCount, plural, one {{followingCountDisplay} personne que vous suivez} other {{followingCountDisplay} personnes que vous suivez}}.", "domain_block_modal.you_will_lose_relationships": "Vous allez perdre tous les abonné·e·s et les personnes que vous suivez sur ce serveur.", - "domain_block_modal.you_wont_see_posts": "Vous ne verrez plus les publications ou les notifications des utilisateurs de ce serveur.", + "domain_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", @@ -262,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.", @@ -305,7 +305,6 @@ "filter_modal.select_filter.subtitle": "Utilisez une catégorie existante ou créez-en une nouvelle", "filter_modal.select_filter.title": "Filtrer ce message", "filter_modal.title.status": "Filtrer un message", - "filter_warning.matches_filter": "Correspond au filtre « {title} »", "filtered_notifications_banner.pending_requests": "De la part {count, plural, =0 {d’aucune personne} one {d'une personne} other {de # personnes}} que vous pourriez connaître", "filtered_notifications_banner.title": "Notifications filtrées", "firehose.all": "Tout", @@ -508,7 +507,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", @@ -516,6 +515,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.", @@ -542,12 +542,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", @@ -566,6 +566,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", @@ -853,6 +854,8 @@ "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.drag_and_drop.on_drag_over": "La pièce jointe du média {item} a été déplacé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 9fa2300fbc..3f4d942b61 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -158,7 +158,7 @@ "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.single": "Inkelde kar", "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", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "Brûker net mear folgje?", "content_warning.hide": "Berjocht ferstopje", "content_warning.show": "Dochs toane", + "content_warning.show_more": "Mear toane", "conversation.delete": "Petear fuortsmite", "conversation.mark_as_read": "As lêzen markearje", "conversation.open": "Petear toane", @@ -305,7 +306,7 @@ "filter_modal.select_filter.subtitle": "In besteande kategory brûke of in nije oanmeitsje", "filter_modal.select_filter.title": "Dit berjocht filterje", "filter_modal.title.status": "In berjocht filterje", - "filter_warning.matches_filter": "Komt oerien mei filter ‘{title}’", + "filter_warning.matches_filter": "Komt oerien mei filter ‘{title}’", "filtered_notifications_banner.pending_requests": "Fan {count, plural, =0 {net ien} one {ien persoan} other {# persoanen}} dy’t jo mooglik kinne", "filtered_notifications_banner.title": "Filtere meldingen", "firehose.all": "Alles", @@ -385,6 +386,7 @@ "interaction_modal.description.follow": "Jo kinne mei in Mastodon-account {name} folgje, om sa harren berjochten op jo starttiidline te ûntfangen.", "interaction_modal.description.reblog": "Jo kinne mei in Mastodon-account dit berjocht booste, om it sa mei jo folgers te dielen.", "interaction_modal.description.reply": "Jo kinne mei in Mastodon-account op dit berjocht reagearje.", + "interaction_modal.description.vote": "Mei in Mastodon-account kinne jo yn dizze enkête stimme.", "interaction_modal.login.action": "Gean nei start", "interaction_modal.login.prompt": "Domein fan jo server, byg. mastodon.social", "interaction_modal.no_account_yet": "Net op Mastodon?", @@ -396,6 +398,7 @@ "interaction_modal.title.follow": "{name} folgje", "interaction_modal.title.reblog": "Berjocht fan {name} booste", "interaction_modal.title.reply": "Op it berjocht fan {name} reagearje", + "interaction_modal.title.vote": "Stimme yn {name}’s peiling", "intervals.full.days": "{number, plural, one {# dei} other {# dagen}} lyn", "intervals.full.hours": "{number, plural, one {# oere} other {# oeren}} lyn", "intervals.full.minutes": "{number, plural, one {# minút} other {# minuten}} lyn", @@ -508,7 +511,7 @@ "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.name_and_others": "{name} en {count, plural, one {# oar persoan} other {# oare persoanen}} folgje jo no", "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", @@ -567,6 +570,7 @@ "notifications.column_settings.filter_bar.category": "Flugge filterbalke", "notifications.column_settings.follow": "Nije folgers:", "notifications.column_settings.follow_request": "Nij folchfersyk:", + "notifications.column_settings.group": "Groepearje", "notifications.column_settings.mention": "Fermeldingen:", "notifications.column_settings.poll": "Enkêteresultaten:", "notifications.column_settings.push": "Pushmeldingen", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 84c76478d1..3181d7978e 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Hiúps!", "alt_text_badge.title": "Téacs alt", "announcement.announcement": "Fógra", + "annual_report.summary.archetype.booster": "An sealgair fionnuar", + "annual_report.summary.archetype.lurker": "An lurker", + "annual_report.summary.archetype.oracle": "An oracal", + "annual_report.summary.archetype.pollster": "An pollaire", + "annual_report.summary.archetype.replier": "An féileacán sóisialta", + "annual_report.summary.followers.followers": "leanúna", + "annual_report.summary.followers.total": "{count} san iomlán", + "annual_report.summary.here_it_is": "Seo do {year} faoi athbhreithniú:", + "annual_report.summary.highlighted_post.by_favourites": "post is fearr leat", + "annual_report.summary.highlighted_post.by_reblogs": "post is treisithe", + "annual_report.summary.highlighted_post.by_replies": "post leis an líon is mó freagraí", + "annual_report.summary.highlighted_post.possessive": "{name}'s", + "annual_report.summary.most_used_app.most_used_app": "aip is mó a úsáidtear", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag is mó a úsáidtear", + "annual_report.summary.new_posts.new_posts": "postanna nua", + "annual_report.summary.percentile.text": "Cuireann sé sin i mbarr úsáideoirí Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Ní inseoidh muid do Bernie.", + "annual_report.summary.thanks": "Go raibh maith agat as a bheith mar chuid de Mastodon!", "attachments_list.unprocessed": "(neamhphróiseáilte)", "audio.hide": "Cuir fuaim i bhfolach", "block_modal.remote_users_caveat": "Iarrfaimid ar an bhfreastalaí {domain} meas a bheith agat ar do chinneadh. Mar sin féin, ní ráthaítear comhlíonadh toisc go bhféadfadh roinnt freastalaithe bloic a láimhseáil ar bhealach difriúil. Seans go mbeidh postálacha poiblí fós le feiceáil ag úsáideoirí nach bhfuil logáilte isteach.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Dílean ​​an t-úsáideoir?", "content_warning.hide": "Folaigh postáil", "content_warning.show": "Taispeáin ar aon nós", + "content_warning.show_more": "Taispeáin níos mó", "conversation.delete": "Scrios comhrá", "conversation.mark_as_read": "Marcáil mar léite", "conversation.open": "Féach ar comhrá", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Bain úsáid as catagóir reatha nó cruthaigh ceann nua", "filter_modal.select_filter.title": "Déan scagadh ar an bpostáil seo", "filter_modal.title.status": "Déan scagadh ar phostáil", - "filter_warning.matches_filter": "Meaitseálann an scagaire “{title}”", + "filter_warning.matches_filter": "Meaitseálann an scagaire “{title}”", "filtered_notifications_banner.pending_requests": "Ó {count, plural, =0 {duine ar bith} one {duine amháin} two {# daoine} few {# daoine} many {# daoine} other {# daoine}} b’fhéidir go bhfuil aithne agat orthu", "filtered_notifications_banner.title": "Fógraí scagtha", "firehose.all": "Gach", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Le cuntas ar Mastodon, is féidir leat {name} a leanúint chun a gcuid postálacha a fháil i do fhotha baile.", "interaction_modal.description.reblog": "Le cuntas ar Mastodon, is féidir leat an postáil seo a threisiú chun é a roinnt le do leantóirí féin.", "interaction_modal.description.reply": "Le cuntas ar Mastodon, is féidir leat freagra a thabhairt ar an bpostáil seo.", + "interaction_modal.description.vote": "Le cuntas ar Mastodon, is féidir leat vótáil sa vótaíocht seo.", "interaction_modal.login.action": "Thabhairt dom abhaile", "interaction_modal.login.prompt": "Fearann ​​do fhreastalaí baile, e.g. mastodon.sóisialta", "interaction_modal.no_account_yet": "Ní ar Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Lean {name}", "interaction_modal.title.reblog": "Mol postáil de chuid {name}", "interaction_modal.title.reply": "Freagair postáil {name}", + "interaction_modal.title.vote": "Vótáil i vótaíocht {name}", "intervals.full.days": "{number, plural, one {# lá} other {# lá}}", "intervals.full.hours": "{number, plural, one {# uair} other {# uair}}", "intervals.full.minutes": "{number, plural, one {# nóiméad} other {# nóiméad}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} tuairiscithe {target}", "notification.admin.sign_up": "Chláraigh {name}", "notification.admin.sign_up.name_and_others": "{name} agus {count, plural, one {# duine eile} two {# daoine eile} few {# daoine eile} many {# daoine eile} other {# daoine eile}} a chláraigh", + "notification.annual_report.message": "Tá do {year} #Wrapstodon ag fanacht! Nocht buaicphointí na bliana agus chuimhneacháin i gcuimhne ar Mastodon!", + "notification.annual_report.view": "Amharc #Wrapstodon", "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", @@ -516,6 +539,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.", @@ -566,6 +590,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í", diff --git a/app/javascript/mastodon/locales/gd.json b/app/javascript/mastodon/locales/gd.json index f6d3f172ca..4f68737b14 100644 --- a/app/javascript/mastodon/locales/gd.json +++ b/app/javascript/mastodon/locales/gd.json @@ -158,7 +158,7 @@ "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.single": "Aon taghadh", "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", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "A bheil thu airson sgur de leantainn a chleachdaiche?", "content_warning.hide": "Falaich am post", "content_warning.show": "Seall e co-dhiù", + "content_warning.show_more": "Seall barrachd dheth", "conversation.delete": "Sguab às an còmhradh", "conversation.mark_as_read": "Cuir comharra gun deach a leughadh", "conversation.open": "Seall an còmhradh", @@ -305,7 +306,7 @@ "filter_modal.select_filter.subtitle": "Cleachd roinn-seòrsa a tha ann no cruthaich tè ùr", "filter_modal.select_filter.title": "Criathraich am post seo", "filter_modal.title.status": "Criathraich post", - "filter_warning.matches_filter": "A’ maidseadh na criathraige “{title}”", + "filter_warning.matches_filter": "A’ maidseadh na criathraige “{title}”", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {Chan eil gin ann} one {O # neach} two {O # neach} few {O # daoine} other {O # duine}} air a bheil thu eòlach ’s dòcha", "filtered_notifications_banner.title": "Brathan criathraichte", "firehose.all": "Na h-uile", @@ -385,6 +386,7 @@ "interaction_modal.description.follow": "Le cunntas air Mastodon, ’s urrainn dhut {name} a leantainn ach am faigh thu na postaichean aca nad dhachaigh.", "interaction_modal.description.reblog": "Le cunntas air Mastodon, ’s urrainn dhut am post seo a bhrosnachadh gus a cho-roinneadh leis an luchd-leantainn agad fhèin.", "interaction_modal.description.reply": "Le cunntas air Mastodon, ’s urrainn dhut freagairt a chur dhan phost seo.", + "interaction_modal.description.vote": "Le cunntas air Mastodon, ’s urrainn dhut bhòtadh sa chunntas-bheachd seo.", "interaction_modal.login.action": "Thoir dhachaigh mi", "interaction_modal.login.prompt": "Àrainn-lìn an fhrithealaiche dachaigh agad, can ailbhean.co-shaoghal.net", "interaction_modal.no_account_yet": "Nach eil thu air Mastodon?", @@ -396,6 +398,7 @@ "interaction_modal.title.follow": "Lean {name}", "interaction_modal.title.reblog": "Brosnaich am post aig {name}", "interaction_modal.title.reply": "Freagair dhan phost aig {name}", + "interaction_modal.title.vote": "Bhòt sa chunntas-bheachd aig {name}", "intervals.full.days": "{number, plural, one {# latha} two {# latha} few {# làithean} other {# latha}}", "intervals.full.hours": "{number, plural, one {# uair a thìde} two {# uair a thìde} few {# uairean a thìde} other {# uair a thìde}}", "intervals.full.minutes": "{number, plural, one {# mhionaid} two {# mhionaid} few {# mionaidean} other {# mionaid}}", @@ -462,7 +465,7 @@ "media_gallery.hide": "Falaich", "moved_to_account_banner.text": "Tha an cunntas {disabledAccount} agad à comas on a rinn thu imrich gu {movedToAccount}.", "mute_modal.hide_from_notifications": "Falaich o na brathan", - "mute_modal.hide_options": "Roghainnean falaich", + "mute_modal.hide_options": "Falaich na roghainnean", "mute_modal.indefinite": "Gus an dì-mhùch mi iad", "mute_modal.show_options": "Seall na roghainnean", "mute_modal.they_can_mention_and_follow": "’S urrainn dhaibh iomradh a thoirt ort agus do leantainn ach chan fhaic thu iad-san.", @@ -508,7 +511,7 @@ "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.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", @@ -516,6 +519,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.", @@ -566,6 +570,7 @@ "notifications.column_settings.filter_bar.category": "Bàr-criathraidh luath", "notifications.column_settings.follow": "Luchd-leantainn ùr:", "notifications.column_settings.follow_request": "Iarrtasan leantainn ùra:", + "notifications.column_settings.group": "Buidheann", "notifications.column_settings.mention": "Iomraidhean:", "notifications.column_settings.poll": "Toraidhean cunntais-bheachd:", "notifications.column_settings.push": "Brathan putaidh", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 27b4ad2460..23f444715b 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -87,6 +87,18 @@ "alert.unexpected.title": "Vaites!", "alt_text_badge.title": "Texto Alt", "announcement.announcement": "Anuncio", + "annual_report.summary.followers.followers": "seguidoras", + "annual_report.summary.followers.total": "{count} en total", + "annual_report.summary.here_it_is": "Este é o resumo do teu {year}:", + "annual_report.summary.highlighted_post.by_favourites": "a publicación mais favorecida", + "annual_report.summary.highlighted_post.by_reblogs": "a publicación con mais promocións", + "annual_report.summary.highlighted_post.by_replies": "a publicación con mais respostas", + "annual_report.summary.highlighted_post.possessive": "de {name}", + "annual_report.summary.most_used_app.most_used_app": "app que mais usaches", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "o cancelo mais utilizado", + "annual_report.summary.new_posts.new_posts": "novas publicacións", + "annual_report.summary.percentile.text": "Sitúante no top das usuarias de Mastodon.", + "annual_report.summary.thanks": "Grazas por ser parte de Mastodon!", "attachments_list.unprocessed": "(sen procesar)", "audio.hide": "Agochar audio", "block_modal.remote_users_caveat": "Ímoslle pedir ao servidor {domain} que respecte a túa decisión. Emporiso, non hai garantía de que atenda a petición xa que os servidores xestionan os bloqueos de formas diferentes. As publicacións públicas poderían aínda ser visibles para usuarias que non iniciaron sesión.", @@ -158,7 +170,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", @@ -197,6 +209,7 @@ "confirmations.unfollow.title": "Deixar de seguir á usuaria?", "content_warning.hide": "Agochar publicación", "content_warning.show": "Mostrar igualmente", + "content_warning.show_more": "Mostrar máis", "conversation.delete": "Eliminar conversa", "conversation.mark_as_read": "Marcar como lido", "conversation.open": "Ver conversa", @@ -305,7 +318,7 @@ "filter_modal.select_filter.subtitle": "Usar unha categoría existente ou crear unha nova", "filter_modal.select_filter.title": "Filtrar esta publicación", "filter_modal.title.status": "Filtrar unha publicación", - "filter_warning.matches_filter": "Debido ao filtro “{title}”", + "filter_warning.matches_filter": "Concorda co filtro «{title}»", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {ninguén} one {unha persoa} other {# persoas}} que igual coñeces", "filtered_notifications_banner.title": "Notificacións filtradas", "firehose.all": "Todo", @@ -385,6 +398,7 @@ "interaction_modal.description.follow": "Cunha conta en Mastodon, poderás seguir a {name} e recibir as súas publicacións na túa cronoloxía de inicio.", "interaction_modal.description.reblog": "Cunha conta en Mastodon, poderás promover esta publicación para compartila con quen te siga.", "interaction_modal.description.reply": "Cunha conta en Mastodon, poderás responder a esta publicación.", + "interaction_modal.description.vote": "Podes votar nesta enquisa se tes unha conta en Mastodon.", "interaction_modal.login.action": "Lévame ao inicio", "interaction_modal.login.prompt": "Dominio do teu servidor de inicio, ex. mastodon.social", "interaction_modal.no_account_yet": "Aínda non tes unha conta?", @@ -396,6 +410,7 @@ "interaction_modal.title.follow": "Seguir a {name}", "interaction_modal.title.reblog": "Promover a publicación de {name}", "interaction_modal.title.reply": "Responder á publicación de {name}", + "interaction_modal.title.vote": "Vota na enquisa de {name}", "intervals.full.days": "{number, plural,one {# día} other {# días}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -451,7 +466,7 @@ "lists.exclusive": "Agocha estas publicacións no Inicio", "lists.new.create": "Engadir listaxe", "lists.new.title_placeholder": "Título da nova listaxe", - "lists.replies_policy.followed": "Toda usuaria seguida", + "lists.replies_policy.followed": "Calquera usuaria que siga", "lists.replies_policy.list": "Membros da lista", "lists.replies_policy.none": "Ninguén", "lists.replies_policy.title": "Mostrar respostas a:", @@ -508,7 +523,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", @@ -567,6 +582,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", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index d9b0382f4a..ed08a9aba3 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -158,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": "סוג משאל", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "לבטל מעקב אחר המשתמש.ת?", "content_warning.hide": "הסתרת חיצרוץ", "content_warning.show": "להציג בכל זאת", + "content_warning.show_more": "הצג עוד", "conversation.delete": "מחיקת שיחה", "conversation.mark_as_read": "סמן כנקרא", "conversation.open": "צפו בשיחה", @@ -305,7 +306,7 @@ "filter_modal.select_filter.subtitle": "שימוש בקטגורייה קיימת או יצירת אחת חדשה", "filter_modal.select_filter.title": "סינון ההודעה הזו", "filter_modal.title.status": "סנן הודעה", - "filter_warning.matches_filter": "תואם לסנן “{title}”", + "filter_warning.matches_filter": "תואם לסנן “{title}”", "filtered_notifications_banner.pending_requests": "{count, plural,=0 {אין בקשות ממשתמשים }one {בקשה אחת ממישהו/מישהי }two {יש בקשותיים ממשתמשים }other {יש # בקשות ממשתמשים }}שאולי מוכרים לך", "filtered_notifications_banner.title": "התראות מסוננות", "firehose.all": "הכל", @@ -385,6 +386,7 @@ "interaction_modal.description.follow": "עם חשבון מסטודון, ניתן לעקוב אחרי {name} כדי לקבל את הפוסטים שלו/ה בפיד הבית.", "interaction_modal.description.reblog": "עם חשבון מסטודון, ניתן להדהד את החצרוץ ולשתף עם עוקבים.", "interaction_modal.description.reply": "עם חשבון מסטודון, ניתן לענות לחצרוץ.", + "interaction_modal.description.vote": "עם חשבון מסטודון, ניתן להצביע בסקר.", "interaction_modal.login.action": "קח אותי לדף הבית", "interaction_modal.login.prompt": "שם השרת שלך, למשל mastodon.social", "interaction_modal.no_account_yet": "עדיין לא במסטודון?", @@ -396,6 +398,7 @@ "interaction_modal.title.follow": "לעקוב אחרי {name}", "interaction_modal.title.reblog": "להדהד את החצרוץ של {name}", "interaction_modal.title.reply": "תשובה לחצרוץ של {name}", + "interaction_modal.title.vote": "הצביעו בסקר של {name}", "intervals.full.days": "{number, plural, one {# יום} other {# ימים}}", "intervals.full.hours": "{number, plural, one {# שעה} other {# שעות}}", "intervals.full.minutes": "{number, plural, one {# דקה} other {# דקות}}", @@ -508,7 +511,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": "אזכור", @@ -567,6 +570,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": "התראות בדחיפה", diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index 4a513c1c07..e0de4c8452 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": "स्टाइल", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 0fee79f8b5..0933a7c256 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -158,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", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "Megszünteted a felhasználó követését?", "content_warning.hide": "Bejegyzés elrejtése", "content_warning.show": "Megjelenítés mindenképp", + "content_warning.show_more": "Több megjelenítése", "conversation.delete": "Beszélgetés törlése", "conversation.mark_as_read": "Megjelölés olvasottként", "conversation.open": "Beszélgetés megtekintése", @@ -305,7 +306,7 @@ "filter_modal.select_filter.subtitle": "Válassz egy meglévő kategóriát, vagy hozz létre egy újat", "filter_modal.select_filter.title": "E bejegyzés szűrése", "filter_modal.title.status": "Egy bejegyzés szűrése", - "filter_warning.matches_filter": "Megfelel a szűrőnek: „{title}”", + "filter_warning.matches_filter": "Megfelel a szűrőnek: „{title}”", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {senkitől} one {egy valószínűleg ismerős személytől} other {# valószínűleg ismerős személytől}}", "filtered_notifications_banner.title": "Szűrt értesítések", "firehose.all": "Összes", @@ -385,6 +386,7 @@ "interaction_modal.description.follow": "Egy Mastodon-fiókkal követheted {name} fiókját, hogy lásd a bejegyzéseit a kezdőlapodon.", "interaction_modal.description.reblog": "Egy Mastodon fiókkal megtolhatod ezt a bejegyzést, hogy megoszd a saját követőiddel.", "interaction_modal.description.reply": "Egy Mastodon fiókkal válaszolhatsz erre a bejegyzésre.", + "interaction_modal.description.vote": "Egy Mastodon fiókkal szavazhatsz ebben a szavazásban.", "interaction_modal.login.action": "Vigyen haza", "interaction_modal.login.prompt": "A saját kiszolgálód tartományneve, pl.: mastodon.social", "interaction_modal.no_account_yet": "Nem vagy Mastodonon?", @@ -396,6 +398,7 @@ "interaction_modal.title.follow": "{name} követése", "interaction_modal.title.reblog": "{name} bejegyzésének megtolása", "interaction_modal.title.reply": "Válasz {name} bejegyzésére", + "interaction_modal.title.vote": "Szavazz {name} szavazásában", "intervals.full.days": "{number, plural, one {# nap} other {# nap}}", "intervals.full.hours": "{number, plural, one {# óra} other {# óra}}", "intervals.full.minutes": "{number, plural, one {# perc} other {# perc}}", @@ -508,7 +511,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", @@ -567,6 +570,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", diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json index 35482297f0..e41d390a3f 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,6 +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_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.", @@ -302,7 +304,7 @@ "filter_modal.select_filter.subtitle": "Usa un categoria existente o crea un nove", "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", @@ -351,6 +353,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}", @@ -363,6 +368,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?", @@ -424,6 +434,8 @@ "lightbox.close": "Clauder", "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}", @@ -490,14 +502,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.", @@ -510,6 +526,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.", @@ -518,11 +535,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", @@ -562,8 +589,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", @@ -700,6 +730,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", @@ -747,6 +778,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", @@ -755,6 +787,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", @@ -817,6 +850,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 f5c71d4a36..4b43363960 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -85,6 +85,7 @@ "alert.rate_limited.title": "Jumlah akses dibatasi", "alert.unexpected.message": "Terjadi kesalahan yang tidak terduga.", "alert.unexpected.title": "Ups!", + "alt_text_badge.title": "Teks Alternatif", "announcement.announcement": "Pengumuman", "attachments_list.unprocessed": "(tidak diproses)", "audio.hide": "Sembunyikan audio", @@ -97,6 +98,8 @@ "block_modal.title": "Blokir pengguna?", "block_modal.you_wont_see_mentions": "Anda tidak akan melihat kiriman yang menyebutkan mereka.", "boost_modal.combo": "Anda dapat menekan {combo} untuk melewati ini", + "boost_modal.reblog": "Pacu kiriman?", + "boost_modal.undo_reblog": "Jangan pacu kiriman?", "bundle_column_error.copy_stacktrace": "Salin laporan kesalahan", "bundle_column_error.error.body": "Laman yang diminta tidak dapat ditampilkan. Mungkin karena sebuah kutu dalam kode kami, atau masalah kompatibilitas peramban.", "bundle_column_error.error.title": "Oh, tidak!", @@ -155,7 +158,7 @@ "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.single": "Pilihan tunggal", "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,6 +222,7 @@ "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_relationships": "Kamu akan kehilangan semua pengikut dan orang yang kamu ikuti dari server ini.", "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.", @@ -232,6 +236,7 @@ "domain_pill.who_you_are": ".", "domain_pill.your_handle": "Nama pengguna anda:", "domain_pill.your_server": "Your digital home, where all of your posts live. Don’t like this one? Transfer servers at any time and bring your followers, too.", + "domain_pill.your_username": "Pengenal unik anda di server ini. Itu memungkinkan dapat mencari pengguna dengan nama yang sama di server lain.", "embed.instructions": "Sematkan kiriman ini di situs web Anda dengan menyalin kode di bawah ini.", "embed.preview": "Tampilan akan seperti ini nantinya:", "emoji_button.activity": "Aktivitas", @@ -294,6 +299,7 @@ "filter_modal.select_filter.subtitle": "Gunakan kategori yang sudah ada atau buat yang baru", "filter_modal.select_filter.title": "Saring kiriman ini", "filter_modal.title.status": "Saring sebuah kiriman", + "filtered_notifications_banner.title": "Notifikasi yang disaring", "firehose.all": "Semua", "firehose.local": "Server Ini", "firehose.remote": "Server Lain", @@ -302,6 +308,7 @@ "follow_requests.unlocked_explanation": "Meskipun akun Anda tidak dikunci, staf {domain} menyarankan Anda untuk meninjau permintaan mengikuti dari akun-akun ini secara manual.", "follow_suggestions.curated_suggestion": "Pilihan staf", "follow_suggestions.dismiss": "Jangan tampilkan lagi", + "follow_suggestions.friends_of_friends_longer": "Populer di antara orang yang anda ikuti", "follow_suggestions.hints.featured": "Profil ini telah dipilih sendiri oleh tim {domain}.", "follow_suggestions.hints.friends_of_friends": "Profil ini populer di kalangan orang yang anda ikuti.", "follow_suggestions.personalized_suggestion": "Saran yang dipersonalisasi", @@ -309,6 +316,7 @@ "follow_suggestions.popular_suggestion_longer": "Populer di {domain}", "follow_suggestions.similar_to_recently_followed_longer": "Serupa dengan profil yang baru Anda ikuti", "follow_suggestions.view_all": "Lihat semua", + "follow_suggestions.who_to_follow": "Siapa yang harus diikuti", "followed_tags": "Tagar yang diikuti", "footer.about": "Tentang", "footer.directory": "Direktori profil", diff --git a/app/javascript/mastodon/locales/ie.json b/app/javascript/mastodon/locales/ie.json index d91c49e83f..f58cf1c71c 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", diff --git a/app/javascript/mastodon/locales/ig.json b/app/javascript/mastodon/locales/ig.json index 8a8d043a6b..b8b0f1084d 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 bfc248a845..f9173b65f9 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -158,7 +158,6 @@ "compose_form.poll.duration": "Votpostoduro", "compose_form.poll.multiple": "Multopla selekteso", "compose_form.poll.option_placeholder": "Selektato {number}", - "compose_form.poll.single": "Selektez un", "compose_form.poll.switch_to_multiple": "Chanjez votposto por permisar multiselektaji", "compose_form.poll.switch_to_single": "Chanjez votposto por permisar una selektajo", "compose_form.poll.type": "Stilo", @@ -305,7 +304,6 @@ "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", @@ -508,7 +506,6 @@ "notification.favourite": "{name} favorizis tua mesajo", "notification.favourite.name_and_others_with_link": "{name} e {count, plural,one {# altru} other {# altri}} favorizis vua posto", "notification.follow": "{name} sequeskis tu", - "notification.follow.name_and_others": "{name} e {count, plural,one {# altru} other {#altri}} sequis vu", "notification.follow_request": "{name} demandas sequar vu", "notification.follow_request.name_and_others": "{name} e {count, plural,one {# altru} other {# altri}} volas sequar vu", "notification.label.mention": "Mencionez", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index bbd3a7a358..adc86faf40 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Úbbs!", "alt_text_badge.title": "Hjálpartexti mynda", "announcement.announcement": "Auglýsing", + "annual_report.summary.archetype.booster": "Svali gaurinn", + "annual_report.summary.archetype.lurker": "Lurkurinn", + "annual_report.summary.archetype.oracle": "Völvan", + "annual_report.summary.archetype.pollster": "Kannanafíkillinn", + "annual_report.summary.archetype.replier": "Félagsveran", + "annual_report.summary.followers.followers": "fylgjendur", + "annual_report.summary.followers.total": "{count} alls", + "annual_report.summary.here_it_is": "Hér er yfirlitið þitt fyrir {year}:", + "annual_report.summary.highlighted_post.by_favourites": "færsla sett oftast í eftirlæti", + "annual_report.summary.highlighted_post.by_reblogs": "færsla oftast endurbirt", + "annual_report.summary.highlighted_post.by_replies": "færsla með flestum svörum", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "mest notaða forrit", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest notaða myllumerki", + "annual_report.summary.new_posts.new_posts": "nýjar færslur", + "annual_report.summary.percentile.text": "Það setur þig á meðal efstunotenda Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Við förum ekkert að raupa um þetta.", + "annual_report.summary.thanks": "Takk fyrir að vera hluti af Mastodon-samfélaginu!", "attachments_list.unprocessed": "(óunnið)", "audio.hide": "Fela hljóð", "block_modal.remote_users_caveat": "Við munum biðja {domain} netþjóninn um að virða ákvörðun þína. Hitt er svo annað mál hvort hann fari eftir þessu, ekki er hægt að tryggja eftirfylgni því sumir netþjónar meðhöndla útilokanir á sinn hátt. Opinberar færslur gætu verið sýnilegar notendum sem ekki eru skráðir inn.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Hætta að fylgjast með viðkomandi?", "content_warning.hide": "Fela færslu", "content_warning.show": "Birta samt", + "content_warning.show_more": "Sýna meira", "conversation.delete": "Eyða samtali", "conversation.mark_as_read": "Merkja sem lesið", "conversation.open": "Skoða samtal", @@ -222,6 +241,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_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.", @@ -303,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Notaðu fyrirliggjandi flokk eða útbúðu nýjan", "filter_modal.select_filter.title": "Sía þessa færslu", "filter_modal.title.status": "Sía færslu", - "filter_warning.matches_filter": "Samsvarar síunni“{title}”", + "filter_warning.matches_filter": "Samsvarar síunni “{title}”", "filtered_notifications_banner.pending_requests": "Frá {count, plural, =0 {engum} one {einum aðila} other {# manns}} sem þú gætir þekkt", "filtered_notifications_banner.title": "Síaðar tilkynningar", "firehose.all": "Allt", @@ -383,6 +404,7 @@ "interaction_modal.description.follow": "Með notandaaðgangi á Mastodon geturðu fylgst með {name} og fengið færslur frá viðkomandi í heimastreymið þitt.", "interaction_modal.description.reblog": "Með notandaaðgangi á Mastodon geturðu endurbirt þessa færslu til að deila henni með þeim sem fylgjast með þér.", "interaction_modal.description.reply": "Með notandaaðgangi á Mastodon geturðu svarað þessari færslu.", + "interaction_modal.description.vote": "Þú getur greitt atkvæði í þessari könnun ef þú ert með aðgang á Mastodon.", "interaction_modal.login.action": "Fara á heimastreymið mitt", "interaction_modal.login.prompt": "Lén heimanetþjónsins þíns, t.d. mastodon.social", "interaction_modal.no_account_yet": "Ekki á Mastodon?", @@ -394,6 +416,7 @@ "interaction_modal.title.follow": "Fylgjast með {name}", "interaction_modal.title.reblog": "Endurbirta færsluna frá {name}", "interaction_modal.title.reply": "Svara færslunni frá {name}", + "interaction_modal.title.vote": "Greiða atkvæði í könnun á vegum {name}", "intervals.full.days": "{number, plural, one {# dagur} other {# dagar}}", "intervals.full.hours": "{number, plural, one {# klukkustund} other {# klukkustundir}}", "intervals.full.minutes": "{number, plural, one {# mínúta} other {# mínútur}}", @@ -503,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} kærði {target}", "notification.admin.sign_up": "{name} skráði sig", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# í viðbót hefur} other {# í viðbót hafa}} skráð sig", + "notification.annual_report.message": "{year} á #Wrapstodon bíður! Afhjúpaðu hvað bar hæst á árinu og minnistæðustu augnablikin á Mastodon!", + "notification.annual_report.view": "Skoða #Wrapstodon", "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 á", @@ -565,6 +590,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", @@ -851,6 +877,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 885be73c62..13ba1f8836 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -87,6 +87,19 @@ "alert.unexpected.title": "Oops!", "alt_text_badge.title": "Testo alternativo", "announcement.announcement": "Annuncio", + "annual_report.summary.archetype.oracle": "L'oracolo", + "annual_report.summary.followers.followers": "seguaci", + "annual_report.summary.followers.total": "{count} in totale", + "annual_report.summary.here_it_is": "Ecco il tuo {year} in sintesi:", + "annual_report.summary.highlighted_post.by_favourites": "il post più apprezzato", + "annual_report.summary.highlighted_post.by_reblogs": "il post più condiviso", + "annual_report.summary.highlighted_post.by_replies": "il post con più risposte", + "annual_report.summary.highlighted_post.possessive": "di {name}", + "annual_report.summary.most_used_app.most_used_app": "l'app più utilizzata", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "l'hashtag più usato", + "annual_report.summary.new_posts.new_posts": "nuovi post", + "annual_report.summary.percentile.text": "Questo ti colloca tra ildei migliori utenti Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Non lo diremo a Bernie.", "attachments_list.unprocessed": "(non elaborato)", "audio.hide": "Nascondi audio", "block_modal.remote_users_caveat": "Chiederemo al server {domain} di rispettare la tua decisione. Tuttavia, la conformità non è garantita poiché alcuni server potrebbero gestire i blocchi in modo diverso. I post pubblici potrebbero essere ancora visibili agli utenti che non hanno effettuato l'accesso.", @@ -158,7 +171,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", @@ -197,6 +210,7 @@ "confirmations.unfollow.title": "Smettere di seguire l'utente?", "content_warning.hide": "Nascondi post", "content_warning.show": "Mostra comunque", + "content_warning.show_more": "Mostra di più", "conversation.delete": "Elimina conversazione", "conversation.mark_as_read": "Segna come letto", "conversation.open": "Visualizza conversazione", @@ -305,7 +319,7 @@ "filter_modal.select_filter.subtitle": "Usa una categoria esistente o creane una nuova", "filter_modal.select_filter.title": "Filtra questo post", "filter_modal.title.status": "Filtra un post", - "filter_warning.matches_filter": "Corrisponde al filtro \"{title}\"", + "filter_warning.matches_filter": "Corrisponde al filtro “{title}”", "filtered_notifications_banner.pending_requests": "Da {count, plural, =0 {nessuno} one {una persona} other {# persone}} che potresti conoscere", "filtered_notifications_banner.title": "Notifiche filtrate", "firehose.all": "Tutto", @@ -385,6 +399,7 @@ "interaction_modal.description.follow": "Con un profilo di Mastodon, puoi seguire {name} per ricevere i suoi post nel feed della tua home.", "interaction_modal.description.reblog": "Con un profilo di Mastodon, puoi rebloggare questo post per condividerlo con i tuoi seguaci.", "interaction_modal.description.reply": "Con un profilo di Mastodon, puoi rispondere a questo post.", + "interaction_modal.description.vote": "Con un account su Mastodon puoi votare in questo sondaggio.", "interaction_modal.login.action": "Portami alla pagina iniziale", "interaction_modal.login.prompt": "Dominio del tuo server principale, ad esempio mastodon.social", "interaction_modal.no_account_yet": "Non su Mastodon?", @@ -396,6 +411,7 @@ "interaction_modal.title.follow": "Segui {name}", "interaction_modal.title.reblog": "Reblogga il post di {name}", "interaction_modal.title.reply": "Rispondi al post di {name}", + "interaction_modal.title.vote": "Vota nel sondaggio di {name}", "intervals.full.days": "{number, plural, one {# giorno} other {# giorni}}", "intervals.full.hours": "{number, plural, one {# ora} other {# ore}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minuti}}", @@ -505,10 +521,12 @@ "notification.admin.report_statuses_other": "{name} ha segnalato {target}", "notification.admin.sign_up": "{name} si è iscritto", "notification.admin.sign_up.name_and_others": "Si sono iscritti: {name} e {count, plural, one {# altro utente} other {altri # utenti}}", + "notification.annual_report.message": "Il tuo #Wrapstodon {year} ti aspetta! Scopri i momenti salienti e memorabili del tuo anno su Mastodon!", + "notification.annual_report.view": "Visualizza #Wrapstodon", "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", @@ -567,6 +585,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", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 1810314c84..6f319dbb10 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -196,7 +196,8 @@ "confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?", "confirmations.unfollow.title": "フォローを解除しようとしています", "content_warning.hide": "内容を隠す", - "content_warning.show": "承知の上で表示", + "content_warning.show": "承知して表示", + "content_warning.show_more": "続きを表示", "conversation.delete": "会話を削除", "conversation.mark_as_read": "既読にする", "conversation.open": "会話を表示", @@ -222,6 +223,8 @@ "domain_block_modal.they_cant_follow": "このサーバーのユーザーはあなたをフォローできなくなります。", "domain_block_modal.they_wont_know": "ドメインブロックは相手からはわかりません。", "domain_block_modal.title": "ドメインをブロックしますか?", + "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がほかのサーバーと会話をするときにしゃべる「言葉」のようなものです。", @@ -303,7 +306,7 @@ "filter_modal.select_filter.subtitle": "既存のカテゴリーを使用するか新規作成します", "filter_modal.select_filter.title": "この投稿をフィルターする", "filter_modal.title.status": "投稿をフィルターする", - "filter_warning.matches_filter": "フィルター「{title}」に一致する投稿です", + "filter_warning.matches_filter": "フィルター「{title}」に一致する投稿", "filtered_notifications_banner.pending_requests": "{count, plural, =0 {すべて完了しました} other {#人の通知がブロックされています}}", "filtered_notifications_banner.title": "保留中の通知", "firehose.all": "すべて", @@ -383,6 +386,7 @@ "interaction_modal.description.follow": "Mastodonのアカウントで{name}さんをフォローしてホームフィードで投稿を受け取れます。", "interaction_modal.description.reblog": "Mastodonのアカウントでこの投稿をブーストして自分のフォロワーに共有できます。", "interaction_modal.description.reply": "Mastodonのアカウントでこの投稿に反応できます。", + "interaction_modal.description.vote": "Mastodonのアカウントでこのアンケートに票を入れることができます。", "interaction_modal.login.action": "サーバーに移動", "interaction_modal.login.prompt": "登録したサーバーのドメイン (例: mastodon.social)", "interaction_modal.no_account_yet": "Mastodonにアカウントがない場合は", @@ -394,6 +398,7 @@ "interaction_modal.title.follow": "{name}さんをフォロー", "interaction_modal.title.reblog": "{name}さんの投稿をブースト", "interaction_modal.title.reply": "{name}さんの投稿にリプライ", + "interaction_modal.title.vote": "{name}さんのアンケートに投票", "intervals.full.days": "{number}日", "intervals.full.hours": "{number}時間", "intervals.full.minutes": "{number}分", @@ -502,13 +507,13 @@ "notification.admin.report_statuses": "{name}さんが{target}さんを「{category}」として通報しました", "notification.admin.report_statuses_other": "{name}さんが{target}さんを通報しました", "notification.admin.sign_up": "{name}さんがサインアップしました", - "notification.admin.sign_up.name_and_others": "{name}さんほか{count, plural, other {#人}}がサインアップしました", + "notification.admin.sign_up.name_and_others": "{name}さんとほか{count, plural, other {#人}}がサインアップしました", "notification.favourite": "{name}さんがお気に入りしました", - "notification.favourite.name_and_others_with_link": "{name}さんほか{count, plural, other {#人}}がお気に入りしました", + "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.follow_request.name_and_others": "{name}さんとほか{count, plural, other {#人}}があなたにフォローリクエストしました", "notification.label.mention": "メンション", "notification.label.private_mention": "非公開の返信 (メンション)", "notification.label.private_reply": "非公開の返信", @@ -527,7 +532,7 @@ "notification.own_poll": "アンケートが終了しました", "notification.poll": "投票したアンケートが終了しました", "notification.reblog": "{name}さんがあなたの投稿をブーストしました", - "notification.reblog.name_and_others_with_link": "{name}さんほか{count, plural, other {#人}}にブーストされました", + "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 {#フォロー}}が失われました。", @@ -565,6 +570,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": "プッシュ通知", @@ -779,6 +785,7 @@ "status.bookmark": "ブックマーク", "status.cancel_reblog_private": "ブースト解除", "status.cannot_reblog": "この投稿はブーストできません", + "status.continued_thread": "続きのスレッド", "status.copy": "投稿へのリンクをコピー", "status.delete": "削除", "status.detailed_status": "詳細な会話ビュー", @@ -812,6 +819,7 @@ "status.reblogs.empty": "まだ誰もブーストしていません。ブーストされるとここに表示されます。", "status.redraft": "削除して下書きに戻す", "status.remove_bookmark": "ブックマークを削除", + "status.replied_in_thread": "ほかのユーザーへ", "status.replied_to": "{name}さんへの返信", "status.reply": "返信", "status.replyAll": "全員に返信", @@ -849,6 +857,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 35e9be816e..9cf94f2606 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -137,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", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 78940909f5..6cb1916e3e 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "앗!", "alt_text_badge.title": "대체 문구", "announcement.announcement": "공지사항", + "annual_report.summary.archetype.booster": "연쇄부스트마", + "annual_report.summary.archetype.lurker": "은둔자", + "annual_report.summary.archetype.oracle": "예언자", + "annual_report.summary.archetype.pollster": "여론조사원", + "annual_report.summary.archetype.replier": "인싸", + "annual_report.summary.followers.followers": "팔로워", + "annual_report.summary.followers.total": "총 {count}", + "annual_report.summary.here_it_is": "{year}년 결산입니다:", + "annual_report.summary.highlighted_post.by_favourites": "가장 많은 좋아요를 받은 게시물", + "annual_report.summary.highlighted_post.by_reblogs": "가장 많이 부스트된 게시물", + "annual_report.summary.highlighted_post.by_replies": "가장 많은 답글을 받은 게시물", + "annual_report.summary.highlighted_post.possessive": "{name} 님의", + "annual_report.summary.most_used_app.most_used_app": "가장 많이 사용한 앱", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "가장 많이 사용한 해시태그", + "annual_report.summary.new_posts.new_posts": "새 게시물", + "annual_report.summary.percentile.text": "마스토돈 사용자의 상위입니다.", + "annual_report.summary.percentile.we_wont_tell_bernie": "엄마한테 말 안 할게요.", + "annual_report.summary.thanks": "마스토돈과 함께 해주셔서 감사합니다!", "attachments_list.unprocessed": "(처리 안 됨)", "audio.hide": "소리 숨기기", "block_modal.remote_users_caveat": "우리는 {domain} 서버가 당신의 결정을 존중해 주길 부탁할 것입니다. 하지만 몇몇 서버는 차단을 다르게 취급할 수 있기 때문에 규정이 준수되는 것을 보장할 수는 없습니다. 공개 게시물은 로그인 하지 않은 사용자들에게 여전히 보여질 수 있습니다.", @@ -113,7 +131,7 @@ "bundle_modal_error.message": "컴포넌트를 불러오는 중 문제가 발생했습니다.", "bundle_modal_error.retry": "다시 시도", "closed_registrations.other_server_instructions": "마스토돈은 분산화 되어 있기 때문에, 다른 서버에서 계정을 만들더라도 이 서버와 상호작용 할 수 있습니다.", - "closed_registrations_modal.description": "{domain}은 현재 가입이 막혀있는 상태입니다, 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", + "closed_registrations_modal.description": "{domain}은 현재 가입이 불가능합니다. 하지만 마스토돈을 이용하기 위해 꼭 {domain}을 사용할 필요는 없다는 사실을 인지해 두세요.", "closed_registrations_modal.find_another_server": "다른 서버 찾기", "closed_registrations_modal.preamble": "마스토돈은 분산화 되어 있습니다, 그렇기 때문에 어디에서 계정을 생성하든, 이 서버에 있는 누구와도 팔로우와 상호작용을 할 수 있습니다. 심지어는 스스로 서버를 만드는 것도 가능합니다!", "closed_registrations_modal.title": "마스토돈에서 가입", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "사용자를 언팔로우 할까요?", "content_warning.hide": "게시물 숨기기", "content_warning.show": "무시하고 보기", + "content_warning.show_more": "더 보기", "conversation.delete": "대화 삭제", "conversation.mark_as_read": "읽은 상태로 표시", "conversation.open": "대화 보기", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "기존의 카테고리를 사용하거나 새로 하나를 만듧니다", "filter_modal.select_filter.title": "이 게시물을 필터", "filter_modal.title.status": "게시물 필터", - "filter_warning.matches_filter": "\"{title}\" 필터에 걸림", + "filter_warning.matches_filter": "\"{title}\" 필터에 걸림", "filtered_notifications_banner.pending_requests": "알 수도 있는 {count, plural, =0 {0 명} one {한 명} other {# 명}}의 사람들로부터", "filtered_notifications_banner.title": "걸러진 알림", "firehose.all": "모두", @@ -351,7 +370,7 @@ "hashtag.column_settings.tag_toggle": "추가 해시태그를 이 컬럼에 추가합니다", "hashtag.counter_by_accounts": "{count, plural, other {참여자 {counter}명}}", "hashtag.counter_by_uses": "{count, plural, other {게시물 {counter}개}}", - "hashtag.counter_by_uses_today": "금일 {count, plural, other {게시물 {counter}개}}", + "hashtag.counter_by_uses_today": "오늘 {count, plural, other {{counter} 개의 게시물}}", "hashtag.follow": "해시태그 팔로우", "hashtag.unfollow": "해시태그 팔로우 해제", "hashtags.and_other": "…및 {count, plural,other {#개}}", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "마스토돈 계정을 통해, {name} 님을 팔로우 하고 그의 게시물을 홈 피드에서 받아 볼 수 있습니다.", "interaction_modal.description.reblog": "마스토돈 계정을 통해, 이 게시물을 부스트 하고 자신의 팔로워들에게 공유할 수 있습니다.", "interaction_modal.description.reply": "마스토돈 계정을 통해, 이 게시물에 응답할 수 있습니다.", + "interaction_modal.description.vote": "마스토돈 계정을 통해, 이 투표에 참여할 수 있습니다.", "interaction_modal.login.action": "홈 서버로 가기", "interaction_modal.login.prompt": "내 홈 서버의 도메인. 예시: mastodon.social", "interaction_modal.no_account_yet": "Mastodon 계정이 없나요?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "{name} 님을 팔로우", "interaction_modal.title.reblog": "{name} 님의 게시물을 부스트", "interaction_modal.title.reply": "{name} 님의 게시물에 답글", + "interaction_modal.title.vote": "{name} 님의 투표에 참여", "intervals.full.days": "{number} 일", "intervals.full.hours": "{number} 시간", "intervals.full.minutes": "{number} 분", @@ -499,16 +520,18 @@ "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}을 신고했습니다", "notification.admin.sign_up": "{name} 님이 가입했습니다", "notification.admin.sign_up.name_and_others": "{name} 외 {count, plural, other {# 명}}이 가입했습니다", + "notification.annual_report.message": "{year} #Wrapstodon 이 기다리고 있습니다! 올 해 마스토돈에서 있었던 최고의 순간과 기억들을 열어보세요!", + "notification.annual_report.view": "#Wrapstodon 보기", "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": "멘션", @@ -567,6 +590,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": "푸시 알림", diff --git a/app/javascript/mastodon/locales/la.json b/app/javascript/mastodon/locales/la.json index ac95b590e3..55678dbdf8 100644 --- a/app/javascript/mastodon/locales/la.json +++ b/app/javascript/mastodon/locales/la.json @@ -13,6 +13,8 @@ "account.edit_profile": "Recolere notionem", "account.featured_tags.last_status_never": "Nulla contributa", "account.featured_tags.title": "Hashtag notātī {name}", + "account.followers_counter": "{count, plural, one {{counter} sectator} other {{counter} sectatores}}", + "account.following_counter": "{count, plural, one {{counter} sectans} other {{counter} sectans}}", "account.moved_to": "{name} significavit eum suam rationem novam nunc esse:", "account.muted": "Confutatus", "account.requested_follow": "{name} postulavit ut te sequeretur", @@ -230,6 +232,7 @@ "search_results.all": "Omnis", "server_banner.active_users": "Usūrāriī āctīvī", "server_banner.administered_by": "Administratur:", + "server_banner.is_one_of_many": "{domain} est unum ex multis independentibus servientibus Mastodon quos adhibere potes ut participes in fediverso.", "sign_in_banner.sign_in": "Sign in", "status.admin_status": "Open this status in the moderation interface", "status.block": "Impedire @{name}", diff --git a/app/javascript/mastodon/locales/lad.json b/app/javascript/mastodon/locales/lad.json index c5026fa33b..563eb3b190 100644 --- a/app/javascript/mastodon/locales/lad.json +++ b/app/javascript/mastodon/locales/lad.json @@ -85,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", @@ -154,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", @@ -191,6 +191,7 @@ "confirmations.unfollow.title": "Desige utilizador?", "content_warning.hide": "Eskonde puvlikasyon", "content_warning.show": "Amostra entanto", + "content_warning.show_more": "Amostra mas", "conversation.delete": "Efasa konversasyon", "conversation.mark_as_read": "Marka komo meldado", "conversation.open": "Ve konversasyon", @@ -334,6 +335,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", @@ -342,6 +348,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.", @@ -465,6 +475,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.", @@ -482,6 +493,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", @@ -496,6 +508,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", @@ -523,6 +536,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", @@ -655,6 +669,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", @@ -729,6 +744,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 043dcfb05d..d03833e11f 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Alternatyvus tekstas", "announcement.announcement": "Skelbimas", + "annual_report.summary.archetype.booster": "Šaunus medžiotojas", + "annual_report.summary.archetype.lurker": "Stebėtojas", + "annual_report.summary.archetype.oracle": "Vydūnas", + "annual_report.summary.archetype.pollster": "Apklausos rengėjas", + "annual_report.summary.archetype.replier": "Socialinis drugelis", + "annual_report.summary.followers.followers": "sekėjai (-ų)", + "annual_report.summary.followers.total": "iš viso {count}", + "annual_report.summary.here_it_is": "Štai jūsų {year} apžvalga:", + "annual_report.summary.highlighted_post.by_favourites": "labiausiai pamėgtas įrašas", + "annual_report.summary.highlighted_post.by_reblogs": "labiausiai pasidalintas įrašas", + "annual_report.summary.highlighted_post.by_replies": "įrašas su daugiausiai atsakymų", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "labiausiai naudota programa", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "labiausiai naudotas saitažodis", + "annual_report.summary.new_posts.new_posts": "nauji įrašai", + "annual_report.summary.percentile.text": "Tai reiškia, kad esate tarppopuliariausių „Mastodon“ naudotojų.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Mes nesakysime Bernie.", + "annual_report.summary.thanks": "Dėkojame, kad esate „Mastodon“ dalis!", "attachments_list.unprocessed": "(neapdorotas)", "audio.hide": "Slėpti garsą", "block_modal.remote_users_caveat": "Paprašysime serverio {domain} gerbti tavo sprendimą. Tačiau atitiktis negarantuojama, nes kai kurie serveriai gali skirtingai tvarkyti blokavimus. Vieši įrašai vis tiek gali būti matomi neprisijungusiems naudotojams.", @@ -158,7 +176,7 @@ "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.single": "Vienas pasirinkimas", "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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Nebesekti naudotoją?", "content_warning.hide": "Slėpti įrašą", "content_warning.show": "Rodyti vis tiek", + "content_warning.show_more": "Rodyti daugiau", "conversation.delete": "Ištrinti pokalbį", "conversation.mark_as_read": "Žymėti kaip skaitytą", "conversation.open": "Peržiūrėti pokalbį", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Naudok esamą kategoriją arba sukurk naują.", "filter_modal.select_filter.title": "Filtruoti šį įrašą", "filter_modal.title.status": "Filtruoti įrašą", - "filter_warning.matches_filter": "Atitinka filtrą „{title}“", + "filter_warning.matches_filter": "Atitinka filtrą „{title}“", "filtered_notifications_banner.pending_requests": "Iš {count, plural, =0 {nė vieno} one {žmogaus} few {# žmonių} many {# žmonių} other {# žmonių}}, kuriuos galbūt pažįsti", "filtered_notifications_banner.title": "Filtruojami pranešimai", "firehose.all": "Visi", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Su Mastodon paskyra gali sekti {name}, kad gautum jų įrašus į pagrindinį srautą.", "interaction_modal.description.reblog": "Su Mastodon paskyra gali pakelti šią įrašą ir pasidalyti juo su savo sekėjais.", "interaction_modal.description.reply": "Su Mastodon paskyra gali atsakyti į šį įrašą.", + "interaction_modal.description.vote": "Su „Mastodon“ paskyra galite balsuoti šioje apklausoje.", "interaction_modal.login.action": "Į pagrindinį puslapį", "interaction_modal.login.prompt": "Tavo pagrindinio serverio domenas, pvz., mastodon.social.", "interaction_modal.no_account_yet": "Nesi Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Sekti {name}", "interaction_modal.title.reblog": "Pakelti {name} įrašą", "interaction_modal.title.reply": "Atsakyti į {name} įrašą", + "interaction_modal.title.vote": "Balsuoti {name} apklausoje", "intervals.full.days": "{number, plural, one {# diena} few {# dienos} many {# dienos} other {# dienų}}", "intervals.full.hours": "{number, plural, one {# valanda} few {# valandos} many {# valandos} other {# valandų}}", "intervals.full.minutes": "{number, plural, one {# minutė} few {# minutes} many {# minutės} other {# minučių}}", @@ -504,8 +525,11 @@ "notification.admin.report_statuses": "{name} pranešė {target} kategorijai {category}", "notification.admin.report_statuses_other": "{name} pranešė {target}", "notification.admin.sign_up": "{name} užsiregistravo", + "notification.annual_report.message": "Jūsų laukia {year} #Wrapstodon! Atskleiskite savo metų svarbiausius įvykius ir įsimintinas akimirkas platformoje „Mastodon“.", + "notification.annual_report.view": "Peržiūrėti #Wrapstodon", "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", @@ -559,6 +583,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", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 1e973ffd3e..30fc0ea348 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -36,6 +36,7 @@ "account.followers.empty": "Šim lietotājam vēl nav sekotāju.", "account.followers_counter": "{count, plural, zero {{count} sekotāju} one {{count} sekotājs} other {{count} sekotāji}}", "account.following": "Seko", + "account.following_counter": "{count, plural, one {seko {counter}} other {seko {counter}}}", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.go_to_profile": "Doties uz profilu", "account.hide_reblogs": "Paslēpt @{name} pastiprinātos ierakstus", @@ -61,6 +62,7 @@ "account.requested_follow": "{name} nosūtīja Tev sekošanas pieprasījumu", "account.share": "Dalīties ar @{name} profilu", "account.show_reblogs": "Parādīt @{name} pastiprinātos ierakstus", + "account.statuses_counter": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}", "account.unblock": "Atbloķēt @{name}", "account.unblock_domain": "Atbloķēt domēnu {domain}", "account.unblock_short": "Atbloķēt", @@ -146,14 +148,13 @@ "compose.saved.body": "Ziņa saglabāta.", "compose_form.direct_message_warning_learn_more": "Uzzināt vairāk", "compose_form.encryption_warning": "Mastodon ieraksti nav pilnībā šifrēti. Nedalies ar jebkādu jutīgu informāciju caur Mastodon!", - "compose_form.hashtag_warning": "Šī ziņa netiks norādīta zem nevienas atsauces, jo tā nav publiska. Tikai publiskās ziņās var meklēt pēc atsauces.", + "compose_form.hashtag_warning": "Šis ieraksts netiks uzrādīts nevienā tēmturī, jo tas nav redzams visiem. Tikai visiem redzamos ierakstus var meklēt pēc tēmtura.", "compose_form.lock_disclaimer": "Tavs konts nav {locked}. Ikviens var Tev sekot, lai redzētu tikai sekotājiem paredzētos ierakstus.", "compose_form.lock_disclaimer.lock": "slēgts", "compose_form.placeholder": "Kas Tev padomā?", "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", @@ -192,6 +193,7 @@ "confirmations.unfollow.title": "Pārtraukt sekošanu lietotājam?", "content_warning.hide": "Paslēpt ierakstu", "content_warning.show": "Tomēr rādīt", + "content_warning.show_more": "Rādīt vairāk", "conversation.delete": "Dzēst sarunu", "conversation.mark_as_read": "Atzīmēt kā izlasītu", "conversation.open": "Skatīt sarunu", @@ -209,9 +211,10 @@ "dismissable_banner.dismiss": "Atcelt", "dismissable_banner.explore_links": "Par šiem jaunumiem šobrīd runā cilvēki šajā un citos decentralizētā tīkla serveros.", "dismissable_banner.explore_statuses": "Šie ir ieraksti, kas šodien gūst arvien lielāku ievērību visā sociālajā tīklā. Augstāk tiek kārtoti jaunāki ieraksti, kuri tiek vairāk pastiprināti un ievietoti izlasēs.", - "dismissable_banner.explore_tags": "Šie tēmturi šobrīd kļūst arvien populārāki cilvēku vidū šajā un citos decentralizētā tīkla serveros.", + "dismissable_banner.explore_tags": "Šie ir tēmturi, kas šodien gūst uzmanību sabiedriskajā tīmeklī. Tēmturi, kurus izmanto vairāk dažādu cilvēku, tiek vērtēti augstāk.", "dismissable_banner.public_timeline": "Šie ir jaunākie publiskie ieraksti no lietotājiem sociālajā tīmeklī, kuriem {domain} seko cilvēki.", "domain_block_modal.block": "Bloķēt serveri", + "domain_block_modal.block_account_instead": "Tā vietā liegt @{name}", "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?", @@ -247,7 +250,7 @@ "empty_column.favourited_statuses": "Tev vēl nav iecienītāko ierakstu. Kad pievienosi kādu izlasei, tas tiks parādīts šeit.", "empty_column.favourites": "Šo ziņu neviens vēl nav pievienojis izlasei. Kad kāds to izdarīs, tas parādīsies šeit.", "empty_column.follow_requests": "Šobrīd Tev nav sekošanas pieprasījumu. Kad saņemsi kādu, tas parādīsies šeit.", - "empty_column.followed_tags": "Tu vēl neesi sekojis nevienam tēmturim. Kad to izdarīsi, tie tiks parādīti šeit.", + "empty_column.followed_tags": "Tu vēl neseko nevienam tēmturim. Kad to izdarīsi, tie tiks parādīti šeit.", "empty_column.hashtag": "Ar šo tēmturi nekas nav atrodams.", "empty_column.home": "Tava mājas laikjosla ir tukša. Seko vairāk cilvēkiem, lai to piepildītu!", "empty_column.list": "Pagaidām šajā sarakstā nekā nav. Kad šī saraksta dalībnieki ievietos jaunus ierakstus, tie parādīsies šeit.", @@ -283,7 +286,6 @@ "filter_modal.select_filter.subtitle": "Izmanto esošu kategoriju vai izveido jaunu", "filter_modal.select_filter.title": "Filtrēt šo ziņu", "filter_modal.title.status": "Filtrēt ziņu", - "filter_warning.matches_filter": "Atbilst filtram “{title}”", "firehose.all": "Visi", "firehose.local": "Šis serveris", "firehose.remote": "Citi serveri", @@ -316,8 +318,8 @@ "hashtag.column_settings.tag_mode.all": "Visi no šiem", "hashtag.column_settings.tag_mode.any": "Kāds no šiem", "hashtag.column_settings.tag_mode.none": "Neviens no šiem", - "hashtag.column_settings.tag_toggle": "Pievienot kolonnai papildu tēmturus", - "hashtag.counter_by_accounts": "{count, plural, one {{counter} dalībnieks} other {{counter} dalībnieki}}", + "hashtag.column_settings.tag_toggle": "Iekļaut šajā kolonnā papildu birkas", + "hashtag.counter_by_accounts": "{count, plural, zero{{counter} dalībnieku} one {{counter} dalībnieks} other {{counter} dalībnieki}}", "hashtag.counter_by_uses": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}}", "hashtag.counter_by_uses_today": "{count, plural, zero {{counter} ierakstu} one {{counter} ieraksts} other {{counter} ieraksti}} šodien", "hashtag.follow": "Sekot tēmturim", @@ -331,6 +333,7 @@ "home.pending_critical_update.link": "Skatīt jauninājumus", "home.pending_critical_update.title": "Ir pieejams būtisks drošības atjauninājums.", "home.show_announcements": "Rādīt paziņojumus", + "ignore_notifications_modal.ignore": "Neņemt vērā paziņojumus", "interaction_modal.description.favourite": "Ar Mastodon kontu tu vari pievienot šo ziņu izlasei, lai informētu autoru, ka to novērtē, un saglabātu to vēlākai lasīšanai.", "interaction_modal.description.follow": "Ar Mastodon kontu Tu vari sekot {name}, lai saņemtu lietotāja ierakstus savā mājas plūsmā.", "interaction_modal.description.reblog": "Ar Mastodon kontu Tu vari izvirzīt šo ierakstu, lai kopīgotu to ar saviem sekotājiem.", @@ -413,6 +416,7 @@ "mute_modal.show_options": "Parādīt iespējas", "mute_modal.title": "Apklusināt lietotāju?", "navigation_bar.about": "Par", + "navigation_bar.administration": "Pārvaldība", "navigation_bar.advanced_interface": "Atvērt paplašinātā tīmekļa saskarnē", "navigation_bar.blocks": "Bloķētie lietotāji", "navigation_bar.bookmarks": "Grāmatzīmes", @@ -429,6 +433,7 @@ "navigation_bar.follows_and_followers": "Sekojamie un sekotāji", "navigation_bar.lists": "Saraksti", "navigation_bar.logout": "Iziet", + "navigation_bar.moderation": "Satura pārraudzība", "navigation_bar.mutes": "Apklusinātie lietotāji", "navigation_bar.opened_in_classic_interface": "Ieraksti, konti un citas noteiktas lapas pēc noklusējuma tiek atvērtas klasiskajā tīmekļa saskarnē.", "navigation_bar.personal": "Personīgie", @@ -444,9 +449,11 @@ "notification.follow": "{name} uzsāka Tev sekot", "notification.follow_request": "{name} nosūtīja Tev sekošanas pieprasījumu", "notification.moderation-warning.learn_more": "Uzzināt vairāk", + "notification.moderation_warning": "Ir saņemts satura pārraudzības brīdinājums", "notification.moderation_warning.action_delete_statuses": "Daži no Taviem ierakstiem tika noņemti.", "notification.moderation_warning.action_disable": "Tavs konts tika atspējots.", "notification.moderation_warning.action_mark_statuses_as_sensitive": "Daži no Taviem ierakstiem tika atzīmēti kā jutīgi.", + "notification.moderation_warning.action_none": "Konts ir saņēmis satura pārraudzības brīdinājumu.", "notification.moderation_warning.action_sensitive": "Tavi ieraksti turpmāk tiks atzīmēti kā jutīgi.", "notification.moderation_warning.action_silence": "Tavs konts tika ierobežots.", "notification.moderation_warning.action_suspend": "Tava konta darbība tika apturēta.", @@ -503,10 +510,10 @@ "onboarding.action.back": "Aizved mani atpakaļ", "onboarding.actions.back": "Aizved mani atpakaļ", "onboarding.actions.go_to_explore": "Skatīt tendences", - "onboarding.actions.go_to_home": "Dodieties uz manu mājas plūsmu", + "onboarding.actions.go_to_home": "Doties uz manu sākuma plūsmu", "onboarding.compose.template": "Sveiki, #Mastodon!", "onboarding.follows.empty": "Diemžēl pašlaik nevar parādīt rezultātus. Vari mēģināt izmantot meklēšanu vai pārlūkot izpētes lapu, lai atrastu cilvēkus, kuriem sekot, vai vēlāk mēģināt vēlreiz.", - "onboarding.follows.lead": "Tava mājas plūsma ir galvenais veids, kā pieredzēt Mastodon. Jo vairāk cilvēkiem sekosi, jo dzīvīgāka un aizraujošāka tā būs. Lai sāktu, šeit ir daži ieteikumi:", + "onboarding.follows.lead": "Tava sākuma plūsma ir galvenais veids, kā pieredzēt Mastodon. Jo vairāk cilvēkiem sekosi, jo dzīvīgāka un aizraujošāka tā būs. Lai sāktu, šeit ir daži ieteikumi:", "onboarding.follows.title": "Pielāgo savu mājas barotni", "onboarding.profile.discoverable": "Padarīt manu profilu atklājamu", "onboarding.profile.display_name": "Attēlojamais vārds", @@ -524,7 +531,7 @@ "onboarding.start.lead": "Tagad Tu esi daļa no Mastodon — vienreizējas, decentralizētas sociālās mediju platformas, kurā Tu, nevis algoritms, veido Tavu pieredzi. Sāksim darbu šajā jaunajā sociālajā jomā:", "onboarding.start.skip": "Nav nepieciešama palīdzība darba sākšanai?", "onboarding.start.title": "Tev tas izdevās!", - "onboarding.steps.follow_people.body": "Tu pats veido savu plūsmu. Piepildīsim to ar interesantiem cilvēkiem.", + "onboarding.steps.follow_people.body": "Sekošana aizraujošiem cilvēkiem ir tas, par ko ir Mastodon.", "onboarding.steps.follow_people.title": "Pielāgo savu mājas barotni", "onboarding.steps.publish_status.body": "Pasveicini pasauli ar tekstu, attēliem, video vai aptaujām {emoji}", "onboarding.steps.publish_status.title": "Izveido savu pirmo ziņu", @@ -555,7 +562,8 @@ "privacy.private.long": "Tikai Tavi sekotāji", "privacy.private.short": "Sekotāji", "privacy.public.long": "Jebkurš Mastodon un ārpus tā", - "privacy.public.short": "Publiska", + "privacy.public.short": "Redzams visiem", + "privacy.unlisted.additional": "Šis uzvedas tieši kā publisks, izņemot to, ka ieraksts neparādīsies tiešraides barotnēs vai tēmturos, izpētē vai Mastodon meklēšanā, pat ja esi to norādījis visa konta ietvaros.", "privacy.unlisted.long": "Mazāk algoritmisku fanfaru", "privacy_policy.last_updated": "Pēdējo reizi atjaunināta {date}", "privacy_policy.title": "Privātuma politika", @@ -653,9 +661,9 @@ "sign_in_banner.create_account": "Izveidot kontu", "sign_in_banner.sign_in": "Pieteikties", "sign_in_banner.sso_redirect": "Piesakies vai Reģistrējies", - "status.admin_account": "Atvērt @{name} moderēšanas saskarni", - "status.admin_domain": "Atvērt {domain} moderēšanas saskarni", - "status.admin_status": "Atvērt šo ziņu moderācijas saskarnē", + "status.admin_account": "Atvērt @{name} satura pārraudzības saskarni", + "status.admin_domain": "Atvērt {domain} satura pārraudzības saskarni", + "status.admin_status": "Atvērt šo ziņu satura pārraudzības saskarnē", "status.block": "Bloķēt @{name}", "status.bookmark": "Grāmatzīme", "status.cancel_reblog_private": "Nepastiprināt", diff --git a/app/javascript/mastodon/locales/ml.json b/app/javascript/mastodon/locales/ml.json index 5ed6f219db..b7a2ad2a3f 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/ms.json b/app/javascript/mastodon/locales/ms.json index cbd57ab356..9dea731397 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", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index c0ca8f1766..b66fcf09c0 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Oeps!", "alt_text_badge.title": "Alt-tekst", "announcement.announcement": "Mededeling", + "annual_report.summary.archetype.booster": "De cool-hunter", + "annual_report.summary.archetype.lurker": "De lurker", + "annual_report.summary.archetype.oracle": "Het orakel", + "annual_report.summary.archetype.pollster": "De opiniepeiler", + "annual_report.summary.archetype.replier": "De sociale vlinder", + "annual_report.summary.followers.followers": "volgers", + "annual_report.summary.followers.total": "totaal {count}", + "annual_report.summary.here_it_is": "Hier is jouw terugblik op {year}:", + "annual_report.summary.highlighted_post.by_favourites": "bericht met de meeste favorieten", + "annual_report.summary.highlighted_post.by_reblogs": "bericht met de meeste boosts", + "annual_report.summary.highlighted_post.by_replies": "bericht met de meeste reacties", + "annual_report.summary.highlighted_post.possessive": "{name}'s", + "annual_report.summary.most_used_app.most_used_app": "meest gebruikte app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "meest gebruikte hashtag", + "annual_report.summary.new_posts.new_posts": "nieuwe berichten", + "annual_report.summary.percentile.text": "Dat zet je in de topvan Mastodon-gebruikers.", + "annual_report.summary.percentile.we_wont_tell_bernie": "We zullen Bernie niets vertellen.", + "annual_report.summary.thanks": "Bedankt dat je deel uitmaakt van Mastodon!", "attachments_list.unprocessed": "(niet verwerkt)", "audio.hide": "Audio verbergen", "block_modal.remote_users_caveat": "We vragen de server {domain} om je besluit te respecteren. Het naleven hiervan is echter niet gegarandeerd, omdat sommige servers blokkades anders kunnen interpreteren. Openbare berichten zijn mogelijk nog steeds zichtbaar voor niet-ingelogde gebruikers.", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Gebruiker ontvolgen?", "content_warning.hide": "Bericht verbergen", "content_warning.show": "Alsnog tonen", + "content_warning.show_more": "Meer tonen", "conversation.delete": "Gesprek verwijderen", "conversation.mark_as_read": "Als gelezen markeren", "conversation.open": "Gesprek tonen", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Een bestaande categorie gebruiken of een nieuwe aanmaken", "filter_modal.select_filter.title": "Dit bericht filteren", "filter_modal.title.status": "Een bericht filteren", - "filter_warning.matches_filter": "Komt overeen met filter “{title}”", + "filter_warning.matches_filter": "Komt overeen met filter \"{title}\"", "filtered_notifications_banner.pending_requests": "Van {count, plural, =0 {niemand} one {een persoon} other {# personen}} die je mogelijk kent", "filtered_notifications_banner.title": "Gefilterde meldingen", "firehose.all": "Alles", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Je kunt met een Mastodon-account {name} volgen, om zo diens berichten op jouw starttijdlijn te ontvangen.", "interaction_modal.description.reblog": "Je kunt met een Mastodon-account dit bericht boosten, om het zo met jouw volgers te delen.", "interaction_modal.description.reply": "Je kunt met een Mastodon-account op dit bericht reageren.", + "interaction_modal.description.vote": "Met een Mastodon-account kun je stemmen in deze peiling.", "interaction_modal.login.action": "Ga naar start", "interaction_modal.login.prompt": "Domein van jouw server, bv. mastodon.social", "interaction_modal.no_account_yet": "Niet op Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "{name} volgen", "interaction_modal.title.reblog": "Bericht van {name} boosten", "interaction_modal.title.reply": "Op het bericht van {name} reageren", + "interaction_modal.title.vote": "Stemmen in {name}'s peiling", "intervals.full.days": "{number, plural, one {# dag} other {# dagen}}", "intervals.full.hours": "{number, plural, one {# uur} other {# uur}}", "intervals.full.minutes": "{number, plural, one {# minuut} other {# minuten}}", @@ -459,7 +480,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", @@ -505,10 +526,12 @@ "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 persoon} other {# andere personen}} hebben zich geregistreerd", + "notification.annual_report.message": "Jouw {year} #Wrapstodon staat klaar! Laat de hoogtepunten en memorabele momenten van jouw jaar zien op Mastodon!", + "notification.annual_report.view": "#Wrapstodon bekijken", "notification.favourite": "{name} markeerde jouw bericht als favoriet", "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 persoon} other {# andere personen}} 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 persoon} other {# andere personen}} hebben gevraagd om je te volgen", "notification.label.mention": "Vermelding", @@ -567,6 +590,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", @@ -781,7 +805,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", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index 58ed018ba0..cc56754193 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -158,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", @@ -305,7 +305,6 @@ "filter_modal.select_filter.subtitle": "Bruk ein eksisterande kategori eller opprett ein ny", "filter_modal.select_filter.title": "Filtrer dette innlegget", "filter_modal.title.status": "Filtrer eit innlegg", - "filter_warning.matches_filter": "Passar med filteret «{title}»", "filtered_notifications_banner.pending_requests": "Frå {count, plural, =0 {ingen} one {éin person} other {# personar}} du kanskje kjenner", "filtered_notifications_banner.title": "Filtrerte varslingar", "firehose.all": "Alle", @@ -385,6 +384,7 @@ "interaction_modal.description.follow": "Med ein konto på Mastodon kan du fylgja {name} for å sjå innlegga deira i din heimestraum.", "interaction_modal.description.reblog": "Med ein konto på Mastodon kan du framheva dette innlegget for å dela det med dine eigne fylgjarar.", "interaction_modal.description.reply": "Med ein konto på Mastodon kan du svara på dette innlegget.", + "interaction_modal.description.vote": "Med ein konto på Mastodon kan du røyste i denne avrøystinga.", "interaction_modal.login.action": "Ta meg heim", "interaction_modal.login.prompt": "Domenenamnet til din heime-tenar. t.d. mastodon.social", "interaction_modal.no_account_yet": "Ikkje på Mastodon?", @@ -396,6 +396,7 @@ "interaction_modal.title.follow": "Fylg {name}", "interaction_modal.title.reblog": "Framhev {name} sitt innlegg", "interaction_modal.title.reply": "Svar på innlegge til {name}", + "interaction_modal.title.vote": "Røyst i {name} si avrøysting", "intervals.full.days": "{number, plural, one {# dag} other {# dagar}}", "intervals.full.hours": "{number, plural, one {# time} other {# timar}}", "intervals.full.minutes": "{number, plural, one {# minutt} other {# minutt}}", @@ -508,7 +509,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", @@ -567,6 +568,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", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 1dd5df32b8..9a5f379797 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", @@ -302,7 +301,6 @@ "filter_modal.select_filter.subtitle": "Bruk en eksisterende kategori eller opprett en ny", "filter_modal.select_filter.title": "Filtrer dette innlegget", "filter_modal.title.status": "Filtrer et innlegg", - "filter_warning.matches_filter": "Passer med filteret «{title}»", "filtered_notifications_banner.pending_requests": "Fra {count, plural, =0 {ingen} one {en person} other {# folk}} du kanskje kjenner", "filtered_notifications_banner.title": "Filtrerte varsler", "firehose.all": "Alt", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 9dbd123c9b..37687bc844 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", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index c6555ebb76..c521fabf39 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -158,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", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "Przestać obserwować?", "content_warning.hide": "Ukryj wpis", "content_warning.show": "Pokaż mimo to", + "content_warning.show_more": "Rozwiń", "conversation.delete": "Usuń konwersację", "conversation.mark_as_read": "Oznacz jako przeczytane", "conversation.open": "Zobacz konwersację", @@ -305,7 +306,7 @@ "filter_modal.select_filter.subtitle": "Użyj istniejącej kategorii lub utwórz nową", "filter_modal.select_filter.title": "Filtruj ten wpis", "filter_modal.title.status": "Filtruj wpis", - "filter_warning.matches_filter": "Pasuje do filtra \"{title}\"", + "filter_warning.matches_filter": "Pasuje do filtra \"{title}\"", "filtered_notifications_banner.pending_requests": "Od {count, plural, =0 {żadnej osoby którą możesz znać} one {# osoby którą możesz znać} other {# osób które możesz znać}}", "filtered_notifications_banner.title": "Powiadomienia filtrowane", "firehose.all": "Wszystko", @@ -385,6 +386,7 @@ "interaction_modal.description.follow": "Mając konto na Mastodonie, możesz śledzić {name} by widzieć jego wpisy na swojej głównej osi czasu.", "interaction_modal.description.reblog": "Mając konto na Mastodonie, możesz podbić ten wpis i udostępnić go Twoim obserwującym.", "interaction_modal.description.reply": "Mając konto na Mastodonie, możesz odpowiedzieć na ten wpis.", + "interaction_modal.description.vote": "Mając konto na Mastodonie, możesz wziąć udział w tym głosowaniu.", "interaction_modal.login.action": "Wróć na stronę główną", "interaction_modal.login.prompt": "Domena twojego serwera domowego, np. \"mastodon.social\"", "interaction_modal.no_account_yet": "Nie masz konta na Mastodonie?", @@ -396,6 +398,7 @@ "interaction_modal.title.follow": "Śledź {name}", "interaction_modal.title.reblog": "Podbij wpis {name}", "interaction_modal.title.reply": "Odpowiedz na post {name}", + "interaction_modal.title.vote": "Weź udział w głosowaniu {name}", "intervals.full.days": "{number, plural, one {# dzień} few {# dni} many {# dni} other {# dni}}", "intervals.full.hours": "{number, plural, one {# godzina} few {# godziny} many {# godzin} other {# godzin}}", "intervals.full.minutes": "{number, plural, one {# minuta} few {# minuty} many {# minut} other {# minut}}", @@ -508,7 +511,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", @@ -567,6 +570,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", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index b6d2fe112e..5e69741f20 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Eita!", "alt_text_badge.title": "Texto alternativo", "announcement.announcement": "Comunicados", + "annual_report.summary.archetype.booster": "Caçador legal", + "annual_report.summary.archetype.lurker": "O espreitador", + "annual_report.summary.archetype.oracle": "O oráculo", + "annual_report.summary.archetype.pollster": "O pesquisador", + "annual_report.summary.archetype.replier": "A borboleta social", + "annual_report.summary.followers.followers": "seguidores", + "annual_report.summary.followers.total": "{count} total", + "annual_report.summary.here_it_is": "Aqui está seu {year} em revisão:", + "annual_report.summary.highlighted_post.by_favourites": "publicação mais favoritada", + "annual_report.summary.highlighted_post.by_reblogs": "publicação mais impulsionada", + "annual_report.summary.highlighted_post.by_replies": "publicação com mais respostas", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "aplicativo mais usado", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag mais usada", + "annual_report.summary.new_posts.new_posts": "novas publicações", + "annual_report.summary.percentile.text": "Isso o coloca no topodos usuários de Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Não contaremos à Bernie.", + "annual_report.summary.thanks": "Obrigada por fazer parte do Mastodon!", "attachments_list.unprocessed": "(não processado)", "audio.hide": "Ocultar áudio", "block_modal.remote_users_caveat": "Pediremos ao servidor {domínio} que respeite sua decisão. No entanto, a conformidade não é garantida pois alguns servidores podem lidar com os blocos de maneira diferente. As postagens públicas ainda podem estar visíveis para usuários não logados.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Deixar de seguir o usuário?", "content_warning.hide": "Ocultar post", "content_warning.show": "Mostrar mesmo assim", + "content_warning.show_more": "Mostrar mais", "conversation.delete": "Excluir conversa", "conversation.mark_as_read": "Marcar como lida", "conversation.open": "Ver conversa", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Use uma categoria existente ou crie uma nova", "filter_modal.select_filter.title": "Filtrar esta publicação", "filter_modal.title.status": "Filtrar uma publicação", - "filter_warning.matches_filter": "Correspondente ao filtro “{title}”", + "filter_warning.matches_filter": "Corresponder filtro “{title}”", "filtered_notifications_banner.pending_requests": "Por {count, plural, =0 {no one} one {one person} other {# people}} que você talvez conheça", "filtered_notifications_banner.title": "Notificações filtradas", "firehose.all": "Tudo", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Com uma conta no Mastodon, você pode seguir {name} para receber publicações na sua página inicial.", "interaction_modal.description.reblog": "Com uma conta no Mastodon, você pode impulsionar esta publicação para compartilhá-lo com seus próprios seguidores.", "interaction_modal.description.reply": "Com uma conta no Mastodon, você pode responder a esta publicação.", + "interaction_modal.description.vote": "Com uma conta no Mastodon, você pode votar nesta enquete.", "interaction_modal.login.action": "Leve-me para casa", "interaction_modal.login.prompt": "Domínio do seu servidor hospedeiro; por exemplo, mastodon.social", "interaction_modal.no_account_yet": "Ainda não está no Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Seguir {name}", "interaction_modal.title.reblog": "Impulsionar publicação de {name}", "interaction_modal.title.reply": "Responder à publicação de {name}", + "interaction_modal.title.vote": "Votar na enquete de {name}", "intervals.full.days": "{number, plural, one {# dia} other {# dias}}", "intervals.full.hours": "{number, plural, one {# hora} other {# horas}}", "intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} denunciou {target}", "notification.admin.sign_up": "{name} se inscreveu", "notification.admin.sign_up.name_and_others": "{name} e {count, plural, one {# other} other {# outros}}", + "notification.annual_report.message": "O #Wrapstodon do seu {year} está esperando! Desvende seus destaques do ano e momentos memoráveis no Mastodon!", + "notification.annual_report.view": "Ver #Wrapstodon", "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", @@ -567,6 +590,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", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 6be7e03b39..a4f2e27401 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", @@ -302,7 +301,6 @@ "filter_modal.select_filter.subtitle": "Utilize uma categoria existente ou crie uma nova", "filter_modal.select_filter.title": "Filtrar esta publicação", "filter_modal.title.status": "Filtrar uma publicação", - "filter_warning.matches_filter": "Corresponde ao filtro “{title}”", "filtered_notifications_banner.pending_requests": "De {count, plural, =0 {ninguém} one {uma pessoa} other {# pessoas}} que pode conhecer", "filtered_notifications_banner.title": "Notificações filtradas", "firehose.all": "Todas", @@ -503,7 +501,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", @@ -775,7 +772,7 @@ "status.bookmark": "Guardar nos marcadores", "status.cancel_reblog_private": "Deixar de reforçar", "status.cannot_reblog": "Não é possível partilhar esta publicação", - "status.continued_thread": "Continuação da conserva", + "status.continued_thread": "Continuação da conversa", "status.copy": "Copiar hiperligação para a publicação", "status.delete": "Eliminar", "status.detailed_status": "Vista pormenorizada da conversa", diff --git a/app/javascript/mastodon/locales/ro.json b/app/javascript/mastodon/locales/ro.json index a61f4b0d4f..96f9eac2b3 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", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 9bd2ed5b4e..f5617550e1 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -34,13 +34,13 @@ "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.following_counter": "{count, plural, one {# подписка} many {# подписок} other {# подписки}}", "account.follows.empty": "Этот пользователь пока ни на кого не подписался.", "account.go_to_profile": "Перейти к профилю", "account.hide_reblogs": "Скрыть продвижения от @{name}", - "account.in_memoriam": "В Памяти.", + "account.in_memoriam": "Вечная память.", "account.joined_short": "Присоединился", "account.languages": "Изменить языки подписки", "account.link_verified_on": "Владение этой ссылкой было проверено {date}", @@ -62,12 +62,13 @@ "account.requested_follow": "{name} отправил(а) вам запрос на подписку", "account.share": "Поделиться профилем @{name}", "account.show_reblogs": "Показывать продвижения от @{name}", + "account.statuses_counter": "{count, plural, one {{counter} пост} few {{counter} поста} other {{counter} постов}}", "account.unblock": "Разблокировать @{name}", "account.unblock_domain": "Разблокировать {domain}", "account.unblock_short": "Разблокировать", "account.unendorse": "Не рекомендовать в профиле", "account.unfollow": "Отписаться", - "account.unmute": "Убрать {name} из игнорируемых", + "account.unmute": "Перестать игнорировать @{name}", "account.unmute_notifications_short": "Включить уведомления", "account.unmute_short": "Не игнорировать", "account_note.placeholder": "Текст заметки", @@ -77,14 +78,29 @@ "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": "Упс!", + "alert.unexpected.title": "Ой!", + "alt_text_badge.title": "Альтернативный текст", "announcement.announcement": "Объявление", + "annual_report.summary.archetype.booster": "Репостер", + "annual_report.summary.archetype.lurker": "Молчун", + "annual_report.summary.archetype.pollster": "Опросчик", + "annual_report.summary.archetype.replier": "Душа компании", + "annual_report.summary.followers.followers": "подписчиков", + "annual_report.summary.here_it_is": "Вот ваши итоги {year} года:", + "annual_report.summary.highlighted_post.by_favourites": "пост с наибольшим количеством звёздочек", + "annual_report.summary.highlighted_post.by_reblogs": "пост с наибольшим количеством продвижений", + "annual_report.summary.highlighted_post.by_replies": "пост с наибольшим количеством ответов", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "наиболее часто используемое приложение", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "наиболее часто используемый хэштег", + "annual_report.summary.new_posts.new_posts": "новых постов", + "annual_report.summary.thanks": "Спасибо за то, что были вместе с Mastodon!", "attachments_list.unprocessed": "(не обработан)", "audio.hide": "Скрыть аудио", "block_modal.remote_users_caveat": "Мы попросим сервер {domain} уважать ваше решение. Однако, соблюдение требований не гарантировано, поскольку некоторые серверы могут работать с блокировками по-разному. Публичные записи по-прежнему могут быть видны неавторизованным пользователям.", @@ -93,11 +109,11 @@ "block_modal.they_cant_mention": "Он не может упоминать или подписываться на вас.", "block_modal.they_cant_see_posts": "Он не может видеть ваши сообщения, и вы не увидите его.", "block_modal.they_will_know": "Он может видеть, что он заблокирован.", - "block_modal.title": "Заблокировать пользователя?", + "block_modal.title": "Заблокируем пользователя?", "block_modal.you_wont_see_mentions": "Вы не увидите записи, которые упоминают его.", "boost_modal.combo": "{combo}, чтобы пропустить это в следующий раз", - "boost_modal.reblog": "Повысить пост?", - "boost_modal.undo_reblog": "Разгрузить пост?", + "boost_modal.reblog": "Репостнуть?", + "boost_modal.undo_reblog": "Убрать репост?", "bundle_column_error.copy_stacktrace": "Скопировать отчет об ошибке", "bundle_column_error.error.body": "Запрошенная страница не может быть отображена. Это может быть вызвано ошибкой в нашем коде или проблемой совместимости браузера.", "bundle_column_error.error.title": "О нет!", @@ -142,12 +158,12 @@ "community.column_settings.local_only": "Только локальные", "community.column_settings.media_only": "Только с медиафайлами", "community.column_settings.remote_only": "Только удалённые", - "compose.language.change": "Изменить язык", + "compose.language.change": "Сменить язык", "compose.language.search": "Поиск языков...", - "compose.published.body": "Запись опубликована.", + "compose.published.body": "Пост опубликован.", "compose.published.open": "Открыть", - "compose.saved.body": "Запись сохранена.", - "compose_form.direct_message_warning_learn_more": "Подробнее", + "compose.saved.body": "Пост отредактирован.", + "compose_form.direct_message_warning_learn_more": "Узнать больше", "compose_form.encryption_warning": "Посты в Mastodon не защищены сквозным шифрованием. Не делитесь конфиденциальной информацией через Mastodon.", "compose_form.hashtag_warning": "Этот пост не будет виден ни под одним из хэштегов, так как он не публичный. Только публичные посты можно найти по хэштегу.", "compose_form.lock_disclaimer": "Ваша учётная запись {locked}. Любой пользователь сможет подписаться на вас и просматривать посты для подписчиков.", @@ -156,17 +172,17 @@ "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": "Стиль", + "compose_form.poll.type": "Тип", "compose_form.publish": "Опубликовать", "compose_form.publish_form": "Опубликовать", "compose_form.reply": "Ответить", "compose_form.save_changes": "Сохранить", "compose_form.spoiler.marked": "Текст скрыт за предупреждением", "compose_form.spoiler.unmarked": "Текст не скрыт", - "compose_form.spoiler_placeholder": "Предупреждение о контенте (опционально)", + "compose_form.spoiler_placeholder": "Предупреждение о содержимом (необязательно)", "confirmation_modal.cancel": "Отмена", "confirmations.block.confirm": "Заблокировать", "confirmations.delete.confirm": "Удалить", @@ -176,17 +192,17 @@ "confirmations.delete_list.message": "Вы действительно хотите навсегда удалить этот список?", "confirmations.delete_list.title": "Удалить список?", "confirmations.discard_edit_media.confirm": "Отменить", - "confirmations.discard_edit_media.message": "У вас есть несохранённые изменения описания мультимедиа или предпросмотра, отменить их?", + "confirmations.discard_edit_media.message": "У вас имеются несохранённые изменения превью и описания медиафайла, отменить их?", "confirmations.edit.confirm": "Редактировать", - "confirmations.edit.message": "В данный момент, редактирование перезапишет составляемое вами сообщение. Вы уверены, что хотите продолжить?", + "confirmations.edit.message": "При редактировании, текст набираемого поста будет очищен. Продолжить?", "confirmations.edit.title": "Переписать сообщение?", "confirmations.logout.confirm": "Выйти", "confirmations.logout.message": "Вы уверены, что хотите выйти?", "confirmations.logout.title": "Выйти?", "confirmations.mute.confirm": "Игнорировать", "confirmations.redraft.confirm": "Удалить и исправить", - "confirmations.redraft.message": "Вы уверены, что хотите удалить и переписать этот пост? Отметки «избранного», продвижения и ответы к оригинальному посту будут удалены.", - "confirmations.redraft.title": "Удалим и исправим пост?", + "confirmations.redraft.message": "Вы уверены, что хотите удалить и переписать этот пост? Отметки «избранного», продвижения и ответы к оригинальному посту будут потеряны.", + "confirmations.redraft.title": "Создать пост заново?", "confirmations.reply.confirm": "Ответить", "confirmations.reply.message": "При ответе, текст набираемого поста будет очищен. Продолжить?", "confirmations.reply.title": "Перепишем пост?", @@ -195,6 +211,7 @@ "confirmations.unfollow.title": "Отписаться?", "content_warning.hide": "Скрыть пост", "content_warning.show": "Всё равно показать", + "content_warning.show_more": "Покажи ещё", "conversation.delete": "Удалить беседу", "conversation.mark_as_read": "Отметить как прочитанное", "conversation.open": "Просмотр беседы", @@ -220,6 +237,8 @@ "domain_block_modal.they_cant_follow": "Никто из этого сервера не может подписываться на вас.", "domain_block_modal.they_wont_know": "Он не будет знать, что его заблокировали.", "domain_block_modal.title": "Заблокировать домен?", + "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 говорит с другими социальными сетями.", @@ -238,7 +257,7 @@ "embed.preview": "Так это будет выглядеть:", "emoji_button.activity": "Занятия", "emoji_button.clear": "Очистить", - "emoji_button.custom": "С этого узла", + "emoji_button.custom": "С этого сервера", "emoji_button.flags": "Флаги", "emoji_button.food": "Еда и напитки", "emoji_button.label": "Вставить эмодзи", @@ -301,8 +320,8 @@ "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 {# люди}}", + "filter_warning.matches_filter": "Соответствует фильтру \"{title}\"", + "filtered_notifications_banner.pending_requests": "Вы можете знать {count, plural, =0 {ни одного человека} one {одного человека} other {# человек}}", "filtered_notifications_banner.title": "Отфильтрованные уведомления", "firehose.all": "Все", "firehose.local": "Текущий сервер", @@ -345,13 +364,13 @@ "hashtag.column_settings.tag_mode.any": "Любой из списка", "hashtag.column_settings.tag_mode.none": "Ни один из списка", "hashtag.column_settings.tag_toggle": "Включить дополнительные теги для этой колонки", - "hashtag.counter_by_accounts": "{count, plural, one {{counter} участник} few {{counter} участников} many {{counter} участников} other {{counter} участников}}", - "hashtag.counter_by_uses": "{count, plural, one {{counter} сообщение} few {{counter} сообщения} many {{counter} сообщения} other {{counter} сообщения}}", - "hashtag.counter_by_uses_today": "{count, plural, one {{counter} сообщение} other {{counter} сообщений}} сегодня", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} пользователь} few {{counter} пользователя} other {{counter} пользователей}}", + "hashtag.counter_by_uses": "{count, plural, one {{counter} пост} few {{counter} поста} other {{counter} постов}}", + "hashtag.counter_by_uses_today": "{count, plural, one {{counter} пост} few {{counter} поста} other {{counter} постов}} сегодня", "hashtag.follow": "Подписаться на новые посты", "hashtag.unfollow": "Отписаться", - "hashtags.and_other": "...и {count, plural, other {# ещё}}", - "hints.profiles.followers_may_be_missing": "Последователи для этого профиля могут отсутствовать.", + "hashtags.and_other": "…и {count, plural, other {ещё #}}", + "hints.profiles.followers_may_be_missing": "Подписчики у этого профиля могут отсутствовать.", "hints.profiles.follows_may_be_missing": "Фолловеры для этого профиля могут отсутствовать.", "hints.profiles.posts_may_be_missing": "Некоторые сообщения из этого профиля могут отсутствовать.", "hints.profiles.see_more_followers": "Посмотреть больше подписчиков на {domain}", @@ -381,6 +400,7 @@ "interaction_modal.description.follow": "С учётной записью Mastodon вы можете подписаться на {name}, чтобы получать их посты в своей домашней ленте.", "interaction_modal.description.reblog": "С учётной записью Mastodon, вы можете продвинуть этот пост, чтобы поделиться им со своими подписчиками.", "interaction_modal.description.reply": "Вы можете ответить на этот пост с учётной записью Mastodon.", + "interaction_modal.description.vote": "Вы сможете проголосовать тут имея аккаунт Mastodon.", "interaction_modal.login.action": "Перейти на домашнюю страницу", "interaction_modal.login.prompt": "Домен вашего домашнего сервера, например, mastodon.social", "interaction_modal.no_account_yet": "Еще не на Mastodon?", @@ -392,6 +412,7 @@ "interaction_modal.title.follow": "Подписаться на {name}", "interaction_modal.title.reblog": "Продвинуть публикацию {name}", "interaction_modal.title.reply": "Ответить на пост {name}", + "interaction_modal.title.vote": "Голосовать в опросе {name}", "intervals.full.days": "{number, plural, one {# день} few {# дня} other {# дней}}", "intervals.full.hours": "{number, plural, one {# час} few {# часа} other {# часов}}", "intervals.full.minutes": "{number, plural, one {# минута} few {# минуты} other {# минут}}", @@ -404,8 +425,8 @@ "keyboard_shortcuts.direct": "чтобы открыть столбец личных упоминаний", "keyboard_shortcuts.down": "вниз по списку", "keyboard_shortcuts.enter": "открыть пост", - "keyboard_shortcuts.favourite": "Добавить пост в избранное", - "keyboard_shortcuts.favourites": "Открыть «Избранное»", + "keyboard_shortcuts.favourite": "добавить пост в избранное", + "keyboard_shortcuts.favourites": "открыть «Избранные»", "keyboard_shortcuts.federated": "перейти к глобальной ленте", "keyboard_shortcuts.heading": "Сочетания клавиш", "keyboard_shortcuts.home": "перейти к домашней ленте", @@ -413,7 +434,7 @@ "keyboard_shortcuts.legend": "показать это окно", "keyboard_shortcuts.local": "перейти к локальной ленте", "keyboard_shortcuts.mention": "упомянуть автора поста", - "keyboard_shortcuts.muted": "Открыть список игнорируемых", + "keyboard_shortcuts.muted": "открыть список игнорируемых", "keyboard_shortcuts.my_profile": "перейти к своему профилю", "keyboard_shortcuts.notifications": "перейти к уведомлениям", "keyboard_shortcuts.open_media": "открыть вложение", @@ -425,13 +446,15 @@ "keyboard_shortcuts.spoilers": "показать/скрыть поле предупреждения о содержании", "keyboard_shortcuts.start": "Перейти к разделу \"Начать\"", "keyboard_shortcuts.toggle_hidden": "показать/скрыть текст за предупреждением", - "keyboard_shortcuts.toggle_sensitivity": "Показать/скрыть медиафайлы", + "keyboard_shortcuts.toggle_sensitivity": "показать/скрыть медиафайлы", "keyboard_shortcuts.toot": "начать писать новый пост", "keyboard_shortcuts.unfocus": "убрать фокус с поля ввода/поиска", "keyboard_shortcuts.up": "вверх по списку", "lightbox.close": "Закрыть", "lightbox.next": "Далее", "lightbox.previous": "Назад", + "lightbox.zoom_in": "Масштаб до фактического размера", + "lightbox.zoom_out": "Масштаб по размеру экрана", "limited_account_hint.action": "Все равно показать профиль", "limited_account_hint.title": "Этот профиль был скрыт модераторами {domain}.", "link_preview.author": "Автор: {name}", @@ -465,8 +488,8 @@ "mute_modal.you_wont_see_mentions": "Вы не увидите постов, которые их упоминают.", "mute_modal.you_wont_see_posts": "Они по-прежнему смогут видеть ваши посты, но вы не сможете видеть их посты.", "navigation_bar.about": "О проекте", - "navigation_bar.administration": "Администрация", - "navigation_bar.advanced_interface": "Включить многоколоночный интерфейс", + "navigation_bar.administration": "Администрирование", + "navigation_bar.advanced_interface": "Открыть в многоколоночном интерфейсе", "navigation_bar.blocks": "Заблокированные пользователи", "navigation_bar.bookmarks": "Закладки", "navigation_bar.community_timeline": "Локальная лента", @@ -492,25 +515,29 @@ "navigation_bar.search": "Поиск", "navigation_bar.security": "Безопасность", "not_signed_in_indicator.not_signed_in": "Вам нужно войти, чтобы иметь доступ к этому ресурсу.", - "notification.admin.report": "{name} сообщил о {target}", - "notification.admin.report_account": "{name} сообщил {count, plural, one {один пост} other {# постов}} от {target} для {category}", - "notification.admin.report_account_other": "{name} сообщил {count, plural, one {одно сообщение} other {# сообщений}} от {target}", - "notification.admin.report_statuses": "{name} сообщил {target} для {category}", - "notification.admin.report_statuses_other": "{name} сообщает {target}", - "notification.admin.sign_up": "{name} зарегистрирован", - "notification.admin.sign_up.name_and_others": "{name} и {count, plural, one {# другой} other {# другие}} подписались", + "notification.admin.report": "{name} пожаловался на {target}", + "notification.admin.report_account": "{name} пожаловался на {count, plural, one {# пост} few {# поста} other {# постов}} от пользователя {target} по причине: {category}", + "notification.admin.report_account_other": "{name} пожаловался на {count, plural, one {# пост} few {# поста} other {# постов}} от пользователя {target}", + "notification.admin.report_statuses": "{name} пожаловался на {target} по причине: {category}", + "notification.admin.report_statuses_other": "{name} пожаловался на {target}", + "notification.admin.sign_up": "{name} зарегистрировался", + "notification.admin.sign_up.name_and_others": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} other {# пользователей}} зарегистрировались", + "notification.annual_report.message": "#Wrapstodon за {year} год ждёт вас! Откройте для себя итоги и памятные моменты этого года в Mastodon!", + "notification.annual_report.view": "Перейти к #Wrapstodon", "notification.favourite": "{name} добавил(а) ваш пост в избранное", - "notification.favourite.name_and_others_with_link": "{name} и {count, plural, one {# другие} other {# другие}} отдали предпочтение вашему посту", + "notification.favourite.name_and_others_with_link": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} other {# пользователей}} добавили ваш пост в избранное", "notification.follow": "{name} подписался (-лась) на вас", + "notification.follow.name_and_others": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} other {# пользователей}} подписались на вас", "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.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": "Модераторы вынесли вам предупреждение", "notification.moderation_warning.action_delete_statuses": "Некоторые из ваших публикаций были удалены.", "notification.moderation_warning.action_disable": "Ваша учётная запись была отключена.", "notification.moderation_warning.action_mark_statuses_as_sensitive": "Некоторые из ваших сообщений были отмечены как деликатные.", @@ -521,7 +548,7 @@ "notification.own_poll": "Ваш опрос закончился", "notification.poll": "Голосование, в котором вы приняли участие, завершилось", "notification.reblog": "{name} продвинул(а) ваш пост", - "notification.reblog.name_and_others_with_link": "{name} и {count, plural, one {# other} other {# others}} увеличили ваш пост", + "notification.reblog.name_and_others_with_link": "{name} и ещё {count, plural, one {# пользователь} few {# пользователя} 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, one {# аккаунт} few {# аккаунта} other {# аккаунтов}}, на которые вы подписаны.", @@ -530,10 +557,15 @@ "notification.status": "{name} только что запостил", "notification.update": "{name} изменил(а) пост", "notification_requests.accept": "Принять", + "notification_requests.accept_multiple": "{count, plural, one {Принять # запрос…} few {Принять # запроса…} other {Принять # запросов…}}", "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Принять запрос} other {Принять запросы}}", + "notification_requests.confirm_accept_multiple.message": "Вы собираетесь принять {count, plural, one {# запрос на показ уведомлений} few {# запроса на показ уведомлений} other {# запросов на показ уведомлений}}. Продолжить?", "notification_requests.confirm_accept_multiple.title": "Принимать запросы на уведомления?", + "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Отклонить запрос} other {Отклонить запросы}}", + "notification_requests.confirm_dismiss_multiple.message": "Вы собираетесь отклонить {count, plural, one {# запрос на показ уведомлений} few {# запроса на показ уведомлений} other {# запросов на показ уведомлений}}. Вы не сможете просмотреть {count, plural, other {их}} потом. Продолжить?", "notification_requests.confirm_dismiss_multiple.title": "Отклонять запросы на уведомления?", "notification_requests.dismiss": "Отклонить", + "notification_requests.dismiss_multiple": "{count, plural, one {Отклонить # запрос…} few {Отклонить # запроса…} other {Отклонить # запросов…}}", "notification_requests.edit_selection": "Редактировать", "notification_requests.exit_selection": "Готово", "notification_requests.explainer_for_limited_account": "Уведомления от этой учетной записи были отфильтрованы, поскольку учетная запись была ограничена модератором.", @@ -545,15 +577,16 @@ "notification_requests.view": "Просмотр уведомлений", "notifications.clear": "Очистить уведомления", "notifications.clear_confirmation": "Вы уверены, что хотите очистить все уведомления?", - "notifications.clear_title": "Сбросить уведомления?", + "notifications.clear_title": "Очистить уведомления?", "notifications.column_settings.admin.report": "Новые жалобы:", "notifications.column_settings.admin.sign_up": "Новые регистрации:", "notifications.column_settings.alert": "Уведомления на рабочем столе", - "notifications.column_settings.favourite": "Избранные:", - "notifications.column_settings.filter_bar.advanced": "Отображать все категории", + "notifications.column_settings.favourite": "Ваш пост добавили в избранные:", + "notifications.column_settings.filter_bar.advanced": "Показать все категории", "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": "Пуш-уведомления", @@ -573,31 +606,32 @@ "notifications.filter.statuses": "Обновления от людей, на которых вы подписаны", "notifications.grant_permission": "Предоставить разрешение.", "notifications.group": "{count} уведомл.", - "notifications.mark_as_read": "Отмечать все уведомления прочитанными", + "notifications.mark_as_read": "Отметить все уведомления прочитанными", "notifications.permission_denied": "Уведомления на рабочем столе недоступны, так как вы запретили их отправку в браузере. Проверьте настройки для сайта, чтобы включить их обратно.", "notifications.permission_denied_alert": "Уведомления на рабочем столе недоступны, так как вы ранее отклонили запрос на их отправку.", "notifications.permission_required": "Чтобы включить уведомления на рабочем столе, необходимо разрешить их в браузере.", - "notifications.policy.accept": "Принять", - "notifications.policy.accept_hint": "Показать в уведомлениях", - "notifications.policy.drop": "Игнорируем", - "notifications.policy.drop_hint": "Отправить в пустоту, чтобы никогда больше не увидеть", - "notifications.policy.filter": "Фильтр", - "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 {один день} few {# дней} many {# дней} other {# дня}}", + "notifications.policy.accept": "Принимать", + "notifications.policy.accept_hint": "Показывать в уведомлениях", + "notifications.policy.drop": "Игнорировать", + "notifications.policy.drop_hint": "Отправлять в пустоту, чтобы никогда больше не увидеть", + "notifications.policy.filter": "Фильтровать", + "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 {# день} few {# дня} other {# дней}}", "notifications.policy.filter_not_followers_title": "Люди, не подписанные на вас", "notifications.policy.filter_not_following_hint": "Пока вы не одобрите их вручную", "notifications.policy.filter_not_following_title": "Люди, на которых вы не подписаны", - "notifications.policy.filter_private_mentions_hint": "Фильтруется, если только это не ответ на ваше собственное упоминание или если вы подписаны на отправителя", + "notifications.policy.filter_private_mentions_hint": "Фильтруются, если только это не ответ на ваше собственное упоминание или если вы подписаны на отправителя", "notifications.policy.filter_private_mentions_title": "Нежелательные личные упоминания", - "notifications.policy.title": "………Управлять уведомлениями от…", + "notifications.policy.title": "Управление уведомлениями", "notifications_permission_banner.enable": "Включить уведомления", "notifications_permission_banner.how_to_control": "Получайте уведомления даже когда Mastodon закрыт, включив уведомления на рабочем столе. А чтобы лишний шум не отвлекал, вы можете настроить какие уведомления вы хотите получать, нажав на кнопку {icon} выше.", "notifications_permission_banner.title": "Будьте в курсе происходящего", - "onboarding.action.back": "Вернуть меня", - "onboarding.actions.back": "Вернуть меня", + "onboarding.action.back": "Верните меня", + "onboarding.actions.back": "Верните меня", "onboarding.actions.go_to_explore": "Посмотреть, что актуально", "onboarding.actions.go_to_home": "Перейти к домашней ленте новостей", "onboarding.compose.template": "Привет, #Mastodon!", @@ -615,7 +649,7 @@ "onboarding.profile.title": "Настройка профиля", "onboarding.profile.upload_avatar": "Загрузить фотографию профиля", "onboarding.profile.upload_header": "Загрузить заголовок профиля", - "onboarding.share.lead": "Расскажите людям, как они могут найти вас на Mastodon!", + "onboarding.share.lead": "Расскажите людям, как найти вас на Mastodon!", "onboarding.share.message": "Я {username} на #Mastodon! Следуйте за мной по адресу {url}", "onboarding.share.next_steps": "Возможные дальнейшие шаги:", "onboarding.share.title": "Поделиться вашим профилем", @@ -630,9 +664,9 @@ "onboarding.steps.setup_profile.title": "Настройте свой профиль", "onboarding.steps.share_profile.body": "Расскажите своим друзьям как найти вас на Mastodon!", "onboarding.steps.share_profile.title": "Поделитесь вашим профилем", - "onboarding.tips.2fa": "Знаете ли вы? Вы можете защитить свой аккаунт, настроив двухфакторную аутентификацию в настройках аккаунта. Она работает с любым приложением TOTP по вашему выбору, номер телефона не требуется!", + "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": "Введенные пароли не совпадают.", @@ -674,15 +708,15 @@ "relative_time.minutes": "{number} мин", "relative_time.seconds": "{number} с", "relative_time.today": "сегодня", - "reply_indicator.attachments": "{count, plural, one {# вложение} other {# вложения}}", + "reply_indicator.attachments": "{count, plural, one {# вложение} few {# вложения} other {# вложений}}", "reply_indicator.cancel": "Отмена", "reply_indicator.poll": "Опрос", "report.block": "Заблокировать", "report.block_explanation": "Вы перестанете видеть посты этого пользователя, и он(а) больше не сможет подписаться на вас и читать ваши посты. Он(а) сможет понять, что вы заблокировали его/её.", - "report.categories.legal": "Правовая информация", + "report.categories.legal": "Нарушение закона", "report.categories.other": "Другое", "report.categories.spam": "Спам", - "report.categories.violation": "Содержимое нарушает одно или несколько правил узла", + "report.categories.violation": "Содержимое нарушает одно или несколько правил сервера", "report.category.subtitle": "Выберите наиболее подходящее", "report.category.title": "Расскажите нам, что не так с {type}", "report.category.title_account": "этим профилем", @@ -725,6 +759,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": "Поиск", @@ -752,31 +787,32 @@ "server_banner.about_active_users": "Люди, заходившие на этот сервер за последние 30 дней (ежемесячные активные пользователи)", "server_banner.active_users": "активные пользователи", "server_banner.administered_by": "Управляется:", - "server_banner.is_one_of_many": "{domain} - это один из многих независимых серверов Mastodon, которые вы можете использовать для участия в fediverse.", + "server_banner.is_one_of_many": "{domain} — это один из многих независимых серверов Mastodon, которые вы можете использовать для участия в сети Fediverse.", "server_banner.server_stats": "Статистика сервера:", - "sign_in_banner.create_account": "Создать учётную запись", - "sign_in_banner.follow_anyone": "Следите за любым человеком в федеральной вселенной и смотрите все в хронологическом порядке. Никаких алгоритмов, рекламы или клик бейта.", - "sign_in_banner.mastodon_is": "Mastodon - лучший способ быть в курсе всего происходящего.", + "sign_in_banner.create_account": "Зарегистрироваться", + "sign_in_banner.follow_anyone": "Подписывайтесь на кого угодно в федивёрсе и смотрите ленту в хронологическом порядке. Никаких алгоритмов, рекламы или кликбейта.", + "sign_in_banner.mastodon_is": "Mastodon — лучший способ быть в курсе всего происходящего.", "sign_in_banner.sign_in": "Войти", "sign_in_banner.sso_redirect": "Войдите или Зарегистрируйтесь", "status.admin_account": "Открыть интерфейс модератора для @{name}", - "status.admin_domain": "Открыть интерфейс модерации {domain}", + "status.admin_domain": "Открыть интерфейс модератора для {domain}", "status.admin_status": "Открыть этот пост в интерфейсе модератора", "status.block": "Заблокировать @{name}", - "status.bookmark": "Сохранить в закладки", + "status.bookmark": "Добавить в закладки", "status.cancel_reblog_private": "Не продвигать", "status.cannot_reblog": "Этот пост не может быть продвинут", "status.continued_thread": "Продолжение темы", "status.copy": "Скопировать ссылку на пост", "status.delete": "Удалить", "status.detailed_status": "Подробный просмотр обсуждения", - "status.direct": "Лично упоминать @{name}", - "status.direct_indicator": "Личные упоминания", + "status.direct": "Упомянуть @{name} лично", + "status.direct_indicator": "Личное упоминание", "status.edit": "Изменить", "status.edited": "Дата последнего изменения: {date}", "status.edited_x_times": "{count, plural, one {{count} изменение} many {{count} изменений} other {{count} изменения}}", "status.embed": "Получить код для встраивания", - "status.favourite": "Избранное", + "status.favourite": "Добавить в избранное", + "status.favourites": "{count, plural, other {в избранном}}", "status.filter": "Фильтровать этот пост", "status.history.created": "{name} создал {date}", "status.history.edited": "{name} отредактировал(а) {date}", @@ -795,6 +831,7 @@ "status.reblog": "Продвинуть", "status.reblog_private": "Продвинуть для своей аудитории", "status.reblogged_by": "{name} продвинул(а)", + "status.reblogs": "{count, plural, one {boost} few {boosts} many {boosts} other {boosts}}", "status.reblogs.empty": "Никто ещё не продвинул этот пост. Как только кто-то это сделает, они появятся здесь.", "status.redraft": "Создать заново", "status.remove_bookmark": "Убрать из закладок", @@ -808,13 +845,13 @@ "status.show_less_all": "Свернуть все спойлеры в ветке", "status.show_more_all": "Развернуть все спойлеры в ветке", "status.show_original": "Показать оригинал", - "status.title.with_attachments": "{user} размещено {attachmentCount, plural, one {вложение} other {{attachmentCount} вложений}}", + "status.title.with_attachments": "{user} опубликовал {attachmentCount, plural, one {{attachmentCount} вложение} few {{attachmentCount} вложения} other {{attachmentCount} вложений}}", "status.translate": "Перевод", - "status.translated_from_with": "Переведено с {lang}, используя {provider}", - "status.uncached_media_warning": "Прослушивание недоступно", + "status.translated_from_with": "Переведено с {lang} с помощью {provider}", + "status.uncached_media_warning": "Предварительный просмотр недоступен", "status.unmute_conversation": "Не игнорировать обсуждение", "status.unpin": "Открепить от профиля", - "subscribed_languages.lead": "Посты только на выбранных языках будут отображаться на вашей домашней странице и в списке лент после изменения. Выберите «Нет», чтобы получать посты на всех языках.", + "subscribed_languages.lead": "Посты лишь на выбранных языках будут появляться в вашей домашней ленте и в списках после изменения. Снимите выбор, чтобы получать посты на всех языках.", "subscribed_languages.save": "Сохранить изменения", "subscribed_languages.target": "Изменить языки подписки для {target}", "tabs_bar.home": "Главная", @@ -824,7 +861,7 @@ "time_remaining.minutes": "{number, plural, one {осталась # минута} few {осталось # минуты} many {осталось # минут} other {осталось # минут}}", "time_remaining.moments": "остались считанные мгновения", "time_remaining.seconds": "{number, plural, one {# секунда} many {# секунд} other {# секунды}}", - "trends.counter_by_accounts": "{count, plural, few {{counter} человека} other {{counter} человек}} за {days, plural, one {последний день} few {последние {days} дня} other {последние {days} дней}}", + "trends.counter_by_accounts": "{count, plural, few {{counter} человека} other {{counter} человек}} за {days, plural, one {последний {days} день} few {последние {days} дня} other {последние {days} дней}}", "trends.trending_now": "Самое актуальное", "ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.", "units.short.billion": "{count} млрд", @@ -836,6 +873,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": "Опишите видео для людей с нарушением слуха или зрения", @@ -847,11 +888,11 @@ "upload_modal.detect_text": "Найти текст на картинке", "upload_modal.edit_media": "Изменить файл", "upload_modal.hint": "Нажмите и перетащите круг в предпросмотре в точку фокуса, которая всегда будет видна на эскизах.", - "upload_modal.preparing_ocr": "Подготовка распознования…", + "upload_modal.preparing_ocr": "Подготовка распознавания…", "upload_modal.preview_label": "Предпросмотр ({ratio})", "upload_progress.label": "Загрузка...", "upload_progress.processing": "Обработка…", - "username.taken": "Данное имя пользователя уже занято. Выберите другое.", + "username.taken": "Это имя пользователя уже занято. Выберите другое", "video.close": "Закрыть видео", "video.download": "Загрузить файл", "video.exit_fullscreen": "Покинуть полноэкранный режим", diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json index 02d1c005cf..b55d5e7a7d 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/sc.json b/app/javascript/mastodon/locales/sc.json index 227a7483a7..71bcaef7ab 100644 --- a/app/javascript/mastodon/locales/sc.json +++ b/app/javascript/mastodon/locales/sc.json @@ -157,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", @@ -458,7 +457,6 @@ "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.name_and_others": "{name} e {count, plural, one {un'àtera persone} other {àteras # persones}} ti sighint", "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", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index da3b1eaefd..1102754fd7 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -87,6 +87,13 @@ "alert.unexpected.title": "Ups!", "alt_text_badge.title": "Alternatívny popis", "announcement.announcement": "Oznámenie", + "annual_report.summary.followers.followers": "sledovatelia", + "annual_report.summary.highlighted_post.by_reblogs": "najviac vyzdvihovaný príspevok", + "annual_report.summary.highlighted_post.by_replies": "príspevok s najviac odpoveďami", + "annual_report.summary.most_used_app.most_used_app": "najviac používaná aplikácia", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "najviac užívaný hashtag", + "annual_report.summary.new_posts.new_posts": "nové príspevky", + "annual_report.summary.percentile.we_wont_tell_bernie": "Nepovieme Berniemu.", "attachments_list.unprocessed": "(nespracované)", "audio.hide": "Skryť zvuk", "block_modal.show_less": "Zobraziť menej", @@ -155,7 +162,7 @@ "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.single": "Jediná voľba", "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", @@ -194,6 +201,7 @@ "confirmations.unfollow.title": "Prestať sledovať užívateľa?", "content_warning.hide": "Skryť príspevok", "content_warning.show": "Aj tak zobraziť", + "content_warning.show_more": "Ukázať viac", "conversation.delete": "Vymazať konverzáciu", "conversation.mark_as_read": "Označiť ako prečítanú", "conversation.open": "Zobraziť konverzáciu", @@ -291,7 +299,6 @@ "filter_modal.select_filter.subtitle": "Použite existujúcu kategóriu alebo vytvorte novú", "filter_modal.select_filter.title": "Filtrovanie tohto príspevku", "filter_modal.title.status": "Filtrovanie príspevku", - "filter_warning.matches_filter": "Zhody triedenia “{title}”", "filtered_notifications_banner.title": "Filtrované oznámenia", "firehose.all": "Všetko", "firehose.local": "Tento server", @@ -345,6 +352,9 @@ "home.pending_critical_update.link": "Zobraziť aktualizácie", "home.pending_critical_update.title": "Je dostupná kritická bezpečnostná aktualizácia.", "home.show_announcements": "Zobraziť oznámenia", + "ignore_notifications_modal.filter_instead": "Radšej triediť", + "ignore_notifications_modal.filter_to_act_users": "Stále budeš môcť akceptovať, odmietnuť, alebo nahlásiť užívateľov", + "ignore_notifications_modal.filter_to_avoid_confusion": "Triedenie pomáha vyvarovať sa možnému zmäteniu", "ignore_notifications_modal.ignore": "Ignoruj upozornenia", "interaction_modal.description.favourite": "S účtom na Mastodone môžete tento príspevok ohviezdičkovať, tak dať autorovi vedieť, že sa vám páči, a uložiť si ho na neskôr.", "interaction_modal.description.follow": "S účtom na Mastodone môžete {name} sledovať a vidieť ich príspevky vo svojom domovskom kanáli.", @@ -401,10 +411,12 @@ "lightbox.close": "Zatvoriť", "lightbox.next": "Ďalej", "lightbox.previous": "Späť", + "lightbox.zoom_out": "Priblížiť na mieru", "limited_account_hint.action": "Aj tak zobraziť profil", "limited_account_hint.title": "Tento profil bol skrytý správcami servera {domain}.", "link_preview.author": "Autor: {name}", "link_preview.more_from_author": "Viac od {name}", + "link_preview.shares": "{count, plural, one {{counter} príspevok} other {{counter} príspevkov}}", "lists.account.add": "Pridať do zoznamu", "lists.account.remove": "Odstrániť zo zoznamu", "lists.delete": "Vymazať zoznam", @@ -427,7 +439,11 @@ "mute_modal.hide_options": "Skryť možnosti", "mute_modal.indefinite": "Pokiaľ ich neodtíšim", "mute_modal.show_options": "Zobraziť možnosti", + "mute_modal.they_can_mention_and_follow": "Môže ťa spomenúť a nasledovať, ale ty ho/ju neuvidíš.", + "mute_modal.they_wont_know": "Nebude vedieť, že bol/a stíšený/á.", "mute_modal.title": "Stíšiť užívateľa?", + "mute_modal.you_wont_see_mentions": "Neuvidíš príspevky, ktoré ho/ju spomínajú.", + "mute_modal.you_wont_see_posts": "Stále uvidí tvoje príspevky, ale ty neuvidíš jeho/jej.", "navigation_bar.about": "O tomto serveri", "navigation_bar.administration": "Spravovanie", "navigation_bar.advanced_interface": "Otvoriť v pokročilom webovom rozhraní", @@ -467,12 +483,15 @@ "notification.label.private_reply": "Súkromná odpoveď", "notification.label.reply": "Odpoveď", "notification.mention": "Zmienka", + "notification.mentioned_you": "{name} ťa spomenul/a", "notification.moderation-warning.learn_more": "Zisti viac", + "notification.moderation_warning": "Dostal/a si varovanie od moderátora", "notification.moderation_warning.action_delete_statuses": "Niektoré z tvojich príspevkov boli odstránené.", "notification.moderation_warning.action_disable": "Tvoj účet bol vypnutý.", "notification.moderation_warning.action_silence": "Tvoj účet bol obmedzený.", "notification.moderation_warning.action_suspend": "Tvoj účet bol pozastavený.", "notification.own_poll": "Vaša anketa sa skončila", + "notification.poll": "Anketa, v ktorej si hlasoval/a, skončila", "notification.reblog": "{name} zdieľa váš príspevok", "notification.relationships_severance_event": "Stratené prepojenia s {name}", "notification.relationships_severance_event.account_suspension": "Správca z {from} pozastavil/a {target}, čo znamená, že od nich viac nemôžeš dostávať aktualizácie, alebo s nimi interaktovať.", @@ -484,7 +503,7 @@ "notification_requests.edit_selection": "Uprav", "notification_requests.exit_selection": "Hotovo", "notification_requests.notifications_from": "Oboznámenia od {name}", - "notification_requests.title": "Filtrované oboznámenia", + "notification_requests.title": "Filtrované oznámenia", "notification_requests.view": "Zobraz upozornenia", "notifications.clear": "Vyčistiť upozornenia", "notifications.clear_confirmation": "Určite chcete nenávratne odstrániť všetky svoje upozornenia?", @@ -519,6 +538,8 @@ "notifications.permission_denied": "Upozornenia na ploche sú nedostupné pre už skôr zamietnutú požiadavku prehliadača", "notifications.permission_denied_alert": "Upozornenia na ploche nemôžu byť zapnuté, pretože požiadavka prehliadača bola už skôr zamietnutá", "notifications.permission_required": "Upozornenia na ploche sú nedostupné, pretože neboli udelené potrebné povolenia.", + "notifications.policy.accept": "Prijať", + "notifications.policy.accept_hint": "Ukáž v oznámeniach", "notifications.policy.drop": "Ignoruj", "notifications.policy.filter": "Triediť", "notifications.policy.filter_limited_accounts_title": "Moderované účty", @@ -526,6 +547,7 @@ "notifications.policy.filter_not_followers_title": "Ľudia, ktorí ťa nenasledujú", "notifications.policy.filter_not_following_title": "Ľudia, ktorých nenasleduješ", "notifications.policy.filter_private_mentions_title": "Nevyžiadané priame spomenutia", + "notifications.policy.title": "Spravuj oznámenia od…", "notifications_permission_banner.enable": "Povoliť upozornenia na ploche", "notifications_permission_banner.how_to_control": "Ak chcete dostávať upozornenia, keď Mastodon nie je otvorený, povoľte upozornenia na ploche. Po ich zapnutí môžete presne kontrolovať, ktoré typy interakcií generujú upozornenia na ploche, a to prostredníctvom tlačidla {icon} vyššie.", "notifications_permission_banner.title": "Nenechajte si nič ujsť", @@ -696,6 +718,7 @@ "status.bookmark": "Pridať záložku", "status.cancel_reblog_private": "Zrušiť zdieľanie", "status.cannot_reblog": "Tento príspevok nie je možné zdieľať", + "status.continued_thread": "Pokračujúce vlákno", "status.copy": "Kopírovať odkaz na príspevok", "status.delete": "Vymazať", "status.detailed_status": "Podrobný náhľad celej konverzácie", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 71bee6822b..32626b80f9 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", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index 182f018873..088b48a3f3 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -87,6 +87,19 @@ "alert.unexpected.title": "Hëm!", "alt_text_badge.title": "Tekst alternativ", "announcement.announcement": "Lajmërim", + "annual_report.summary.followers.followers": "ndjekës", + "annual_report.summary.followers.total": "{count} gjithsej", + "annual_report.summary.here_it_is": "Ja {year} juaj e shqyrtuar:", + "annual_report.summary.highlighted_post.by_favourites": "potimi më i parapëlqyer", + "annual_report.summary.highlighted_post.by_reblogs": "postimi me më shumë përforcime", + "annual_report.summary.highlighted_post.by_replies": "postimi me më tepër përgjigje", + "annual_report.summary.highlighted_post.possessive": "nga {name}", + "annual_report.summary.most_used_app.most_used_app": "aplikacioni më i përdorur", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag-u më i përdorur", + "annual_report.summary.new_posts.new_posts": "postime të reja", + "annual_report.summary.percentile.text": "Kjo ju vë në kryetë përdoruesve të Mastodon-it.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Nuk do t’ia themi Bernit.", + "annual_report.summary.thanks": "Faleminderit që jeni pjesë e Mastodon-it!", "attachments_list.unprocessed": "(e papërpunuar)", "audio.hide": "Fshihe audion", "block_modal.remote_users_caveat": "Do t’i kërkojmë shërbyesit {domain} të respektojë vendimin tuaj. Por, pajtimi s’është i garantuar, ngaqë disa shërbyes mund t’i trajtojnë ndryshe bllokimet. Psotimet publike mundet të jenë ende të dukshme për përdorues pa bërë hyrje në llogari.", @@ -158,7 +171,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", @@ -197,6 +210,7 @@ "confirmations.unfollow.title": "Të ndalet ndjekja e përdoruesit?", "content_warning.hide": "Fshihe postimin", "content_warning.show": "Shfaqe, sido qoftë", + "content_warning.show_more": "Shfaq më tepër", "conversation.delete": "Fshije bisedën", "conversation.mark_as_read": "Vëri shenjë si të lexuar", "conversation.open": "Shfaq bisedën", @@ -305,7 +319,7 @@ "filter_modal.select_filter.subtitle": "Përdorni një kategori ekzistuese, ose krijoni një të re", "filter_modal.select_filter.title": "Filtroje këtë postim", "filter_modal.title.status": "Filtroni një postim", - "filter_warning.matches_filter": "Ka përkim me filtrin “{title}”", + "filter_warning.matches_filter": "Ka përkim me filtrin “{title}”", "filtered_notifications_banner.pending_requests": "Nga {count, plural, =0 {askush} one {një person} other {# vetë}} që mund të njihni", "filtered_notifications_banner.title": "Njoftime të filtruar", "firehose.all": "Krejt", @@ -385,6 +399,7 @@ "interaction_modal.description.follow": "Me një llogari në Mastodon, mund ta ndiqni {name} për të marrë postimet e tyre në prurjen tuaj të kreut.", "interaction_modal.description.reblog": "Me një llogari në Mastodon, mund ta përforconi këtë postim për ta ndarë me ndjekësit tuaj.", "interaction_modal.description.reply": "Me një llogari në Mastodon, mund t’i përgjigjeni këtij postimi.", + "interaction_modal.description.vote": "Me një llogari në Mastodon, mund të votoni në këtë pyetësor.", "interaction_modal.login.action": "Shpjemëni në shtëpi", "interaction_modal.login.prompt": "Përkatësia e shërbyesit tuaj vatër, p.sh. mastodon.social", "interaction_modal.no_account_yet": "S’gjendeni në Mastodon?", @@ -396,6 +411,7 @@ "interaction_modal.title.follow": "Ndiq {name}", "interaction_modal.title.reblog": "Përforconi postimin e {name}", "interaction_modal.title.reply": "Përgjigjuni postimit të {name}", + "interaction_modal.title.vote": "Votoni te pyetësori nga {name}", "intervals.full.days": "{number, plural, one {# ditë} other {# ditë}}", "intervals.full.hours": "{number, plural, one {# orë} other {# orë}}", "intervals.full.minutes": "{number, plural, one {# minutë} other {# minuta}}", @@ -505,10 +521,11 @@ "notification.admin.report_statuses_other": "{name} raportoi {target}", "notification.admin.sign_up": "{name} u regjistrua", "notification.admin.sign_up.name_and_others": "U regjistrua {name} dhe {count, plural, one {# tjetër} other {# të tjerë}}", + "notification.annual_report.message": "#Wrapstodon juaj për {year} pret! Zbuloni pikat e theksuara dhe çastet e paharrueshëm të këtij viti për ju në Mastodon!", + "notification.annual_report.view": "Shihni #Wrapstodon", "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", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 1053d581c3..4a33c2f5ca 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", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 9529c41fe3..d80411859e 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": "Стил", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 298852100c..e3571704bb 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -22,7 +22,7 @@ "account.cancel_follow_request": "Återkalla din begäran om att få följa", "account.copy": "Kopiera länk till profil", "account.direct": "Nämn @{name} privat", - "account.disable_notifications": "Sluta notifiera mig när @{name} gör inlägg", + "account.disable_notifications": "Sluta meddela mig när @{name} skriver ett inlägg", "account.domain_blocked": "Domän blockerad", "account.edit_profile": "Redigera profil", "account.enable_notifications": "Notifiera mig när @{name} gör inlägg", @@ -44,7 +44,7 @@ "account.joined_short": "Gick med", "account.languages": "Ändra vilka språk du helst vill se i ditt flöde", "account.link_verified_on": "Ägarskap för denna länk kontrollerades den {date}", - "account.locked_info": "För detta konto har ägaren valt att manuellt godkänna vem som kan följa hen.", + "account.locked_info": "Detta konto har låst integritetsstatus. Ägaren väljer manuellt vem som kan följa det.", "account.media": "Media", "account.mention": "Nämn @{name}", "account.moved_to": "{name} har indikerat att hen har ett nytt konto:", @@ -82,10 +82,29 @@ "admin.impact_report.instance_follows": "Följare som deras användare skulle förlora", "admin.impact_report.title": "Sammanfattning av påverkan", "alert.rate_limited.message": "Vänligen försök igen efter {retry_time, time, medium}.", - "alert.rate_limited.title": "Mängd begränsad", + "alert.rate_limited.title": "Hastighetsbegränsad", "alert.unexpected.message": "Ett oväntat fel uppstod.", "alert.unexpected.title": "Hoppsan!", + "alt_text_badge.title": "Alt-Text", "announcement.announcement": "Meddelande", + "annual_report.summary.archetype.booster": "Häftighetsjägaren", + "annual_report.summary.archetype.lurker": "Smygaren", + "annual_report.summary.archetype.oracle": "Oraklet", + "annual_report.summary.archetype.pollster": "Frågaren", + "annual_report.summary.archetype.replier": "Den sociala fjärilen", + "annual_report.summary.followers.followers": "följare", + "annual_report.summary.followers.total": "{count} totalt", + "annual_report.summary.here_it_is": "Här är en tillbakablick på ditt {year}:", + "annual_report.summary.highlighted_post.by_favourites": "mest favoritmarkerat inlägg", + "annual_report.summary.highlighted_post.by_reblogs": "mest boostat inlägg", + "annual_report.summary.highlighted_post.by_replies": "inlägg med flest svar", + "annual_report.summary.highlighted_post.possessive": "{name}s", + "annual_report.summary.most_used_app.most_used_app": "mest använda app", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "mest använda hashtag", + "annual_report.summary.new_posts.new_posts": "nya inlägg", + "annual_report.summary.percentile.text": "Det placerar dig i toppav Mastodon-användare.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Vi berättar inte för Bernie.", + "annual_report.summary.thanks": "Tack för att du är en del av Mastodon!", "attachments_list.unprocessed": "(obehandlad)", "audio.hide": "Dölj audio", "block_modal.remote_users_caveat": "Vi kommer att be servern {domain} att respektera ditt beslut. Dock garanteras inte efterlevnad eftersom vissa servrar kan hantera blockeringar på olika sätt. Offentliga inlägg kan fortfarande vara synliga för icke-inloggade användare.", @@ -97,6 +116,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 +176,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", @@ -194,6 +215,7 @@ "confirmations.unfollow.title": "Avfölj %s?", "content_warning.hide": "Dölj inlägg", "content_warning.show": "Visa ändå", + "content_warning.show_more": "Visa mer", "conversation.delete": "Radera konversation", "conversation.mark_as_read": "Markera som läst", "conversation.open": "Visa konversation", @@ -219,6 +241,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_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.", @@ -265,7 +289,7 @@ "empty_column.follow_requests": "Du har inga följarförfrågningar än. När du får en kommer den visas här.", "empty_column.followed_tags": "Du följer inga hashtaggar ännu. När du gör det kommer de att dyka upp här.", "empty_column.hashtag": "Det finns inget i denna hashtag ännu.", - "empty_column.home": "Din hemma-tidslinje är tom! Följ fler användare för att fylla den. {suggestions}", + "empty_column.home": "Din hemma-tidslinje är tom! Följ fler användare för att fylla den.", "empty_column.list": "Det finns inget i denna lista än. När listmedlemmar publicerar nya inlägg kommer de synas här.", "empty_column.lists": "Du har inga listor än. När skapar en kommer den dyka upp här.", "empty_column.mutes": "Du har ännu inte tystat några användare.", @@ -300,6 +324,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", @@ -376,9 +401,10 @@ "ignore_notifications_modal.not_following_title": "Vill du blockera aviseringar från personer som du inte följer dig?", "ignore_notifications_modal.private_mentions_title": "Vill du ignorera aviseringar från oönskade privata omnämningar?", "interaction_modal.description.favourite": "Med ett Mastodon-konto kan du favoritmarkera detta inlägg för att visa författaren att du gillar det och för att spara det till senare.", - "interaction_modal.description.follow": "Med ett Mastodon-konto kan du följa {name} för att se hens inlägg i ditt hemflöde.", + "interaction_modal.description.follow": "Med ett Mastodon-konto kan du följa {name} för att se deras inlägg i ditt hemflöde.", "interaction_modal.description.reblog": "Med ett Mastodon-konto kan du boosta detta inlägg för att dela den med dina egna följare.", "interaction_modal.description.reply": "Med ett Mastodon-konto kan du svara på detta inlägg.", + "interaction_modal.description.vote": "Med ett konto på Mastodon kan du delta i denna omröstning.", "interaction_modal.login.action": "Ta hem mig", "interaction_modal.login.prompt": "Domän för din hemserver, t.ex. mastodon.social", "interaction_modal.no_account_yet": "Inte på Mastodon?", @@ -390,17 +416,18 @@ "interaction_modal.title.follow": "Följ {name}", "interaction_modal.title.reblog": "Boosta {name}s inlägg", "interaction_modal.title.reply": "Svara på {name}s inlägg", + "interaction_modal.title.vote": "Rösta i {name}s enkät", "intervals.full.days": "{number, plural, one {# dag} other {# dagar}}", "intervals.full.hours": "{number, plural, one {# timme} other {# timmar}}", "intervals.full.minutes": "{number, plural, one {# minut} other {# minuter}}", "keyboard_shortcuts.back": "Gå bakåt", "keyboard_shortcuts.blocked": "Öppna listan över blockerade användare", "keyboard_shortcuts.boost": "Boosta inlägg", - "keyboard_shortcuts.column": "för att fokusera en status i en av kolumnerna", + "keyboard_shortcuts.column": "Fokusera kolumn", "keyboard_shortcuts.compose": "för att fokusera skrivfältet", "keyboard_shortcuts.description": "Beskrivning", "keyboard_shortcuts.direct": "för att öppna privata nämningskolumnen", - "keyboard_shortcuts.down": "för att flytta nedåt i listan", + "keyboard_shortcuts.down": "Flytta ner i listan", "keyboard_shortcuts.enter": "Öppna inlägg", "keyboard_shortcuts.favourite": "Favoritmarkera inlägg", "keyboard_shortcuts.favourites": "Öppna favoritlistan", @@ -420,16 +447,18 @@ "keyboard_shortcuts.reply": "Svara på inlägg", "keyboard_shortcuts.requests": "för att öppna Följförfrågningar", "keyboard_shortcuts.search": "för att fokusera sökfältet", - "keyboard_shortcuts.spoilers": "visa/dölja CW-fält", - "keyboard_shortcuts.start": "för att öppna \"Kom igång\"-kolumnen", - "keyboard_shortcuts.toggle_hidden": "för att visa/gömma text bakom CW", - "keyboard_shortcuts.toggle_sensitivity": "för att visa/gömma media", + "keyboard_shortcuts.spoilers": "Visa/dölja CW-fält", + "keyboard_shortcuts.start": "Öppna \"Kom igång\"-kolumnen", + "keyboard_shortcuts.toggle_hidden": "Visa/gömma text bakom CW", + "keyboard_shortcuts.toggle_sensitivity": "Visa/gömma media", "keyboard_shortcuts.toot": "Starta nytt inlägg", - "keyboard_shortcuts.unfocus": "för att avfokusera skrivfält/sökfält", - "keyboard_shortcuts.up": "för att flytta uppåt i listan", + "keyboard_shortcuts.unfocus": "Avfokusera skrivfält/sökfält", + "keyboard_shortcuts.up": "Flytta uppåt i listan", "lightbox.close": "Stäng", "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}", @@ -463,6 +492,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", @@ -479,6 +509,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", @@ -495,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} rapporterade {target}", "notification.admin.sign_up": "{name} registrerade sig", "notification.admin.sign_up.name_and_others": "{name} och {count, plural, one {# en annan} other {# andra}} har registrerat sig", + "notification.annual_report.message": "Din {year} #Wrapstodon väntar! Upptäck ditt års höjdpunkter och minnesvärda stunder på Mastodon!", + "notification.annual_report.view": "Visa #Wrapstodon", "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.name_and_others": "{name} och {count, plural, one {# 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", @@ -557,6 +590,7 @@ "notifications.column_settings.filter_bar.category": "Snabbfilter", "notifications.column_settings.follow": "Nya följare:", "notifications.column_settings.follow_request": "Ny följ-förfrågan:", + "notifications.column_settings.group": "Gruppera", "notifications.column_settings.mention": "Omnämningar:", "notifications.column_settings.poll": "Omröstningsresultat:", "notifications.column_settings.push": "Push-aviseringar", @@ -603,11 +637,11 @@ "onboarding.action.back": "Ta mig tillbaka", "onboarding.actions.back": "Ta mig tillbaka", "onboarding.actions.go_to_explore": "See what's trending", - "onboarding.actions.go_to_home": "Go to your home feed", + "onboarding.actions.go_to_home": "Ta mig till mitt hemflöde", "onboarding.compose.template": "Hallå #Mastodon!", "onboarding.follows.empty": "Tyvärr kan inga resultat visas just nu. Du kan prova att använda sökfunktionen eller utforska sidan för att hitta personer att följa, eller försök igen senare.", - "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": "Ditt hemflöde är det primära sättet att uppleva Mastodon. Ju fler människor du följer, desto mer aktiv och intressant blir det. För att komma igång, är här några förslag:", + "onboarding.follows.title": "Anpassa ditt hemflöde", "onboarding.profile.discoverable": "Gör min profil upptäckbar", "onboarding.profile.discoverable_hint": "När du väljer att vara upptäckbar på Mastodon kan dina inlägg visas i sök- och trendresultat, och din profil kan föreslås för personer med liknande intressen som du.", "onboarding.profile.display_name": "Visningsnamn", @@ -628,7 +662,7 @@ "onboarding.start.title": "Du klarade det!", "onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", - "onboarding.steps.publish_status.body": "Say hello to the world.", + "onboarding.steps.publish_status.body": "Säg hej till världen med text, foton, videor eller omröstningar {emoji}", "onboarding.steps.publish_status.title": "Gör ditt första inlägg", "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", @@ -719,8 +753,8 @@ "report.thanks.take_action_actionable": "Medan vi granskar detta kan du vidta åtgärder mot {name}:", "report.thanks.title": "Vill du inte se det här?", "report.thanks.title_actionable": "Tack för att du rapporterar, vi kommer att titta på detta.", - "report.unfollow": "Sluta följ @{username}", - "report.unfollow_explanation": "Du följer detta konto. Avfölj hen för att inte se hens inlägg i ditt hemflöde.", + "report.unfollow": "Sluta följ @{name}", + "report.unfollow_explanation": "Du följer detta konto. Avfölj det för att inte se dess inlägg i ditt hemflöde.", "report_notification.attached_statuses": "bifogade {count, plural, one {{count} inlägg} other {{count} inlägg}}", "report_notification.categories.legal": "Rättsligt", "report_notification.categories.legal_sentence": "olagligt innehåll", @@ -771,6 +805,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", @@ -804,6 +839,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", @@ -813,7 +849,7 @@ "status.show_less_all": "Visa mindre för alla", "status.show_more_all": "Visa mer för alla", "status.show_original": "Visa original", - "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", + "status.title.with_attachments": "{user} lade upp {attachmentCount, plural, one {en bilaga} other {{attachmentCount} bilagor}}", "status.translate": "Översätt", "status.translated_from_with": "Översatt från {lang} med {provider}", "status.uncached_media_warning": "Förhandsvisning inte tillgänglig", @@ -841,6 +877,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 88c48bfb40..5cf95554bc 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -97,7 +97,7 @@ "block_modal.they_will_know": "เขาสามารถเห็นว่ามีการปิดกั้นเขา", "block_modal.title": "ปิดกั้นผู้ใช้?", "block_modal.you_wont_see_mentions": "คุณจะไม่เห็นโพสต์ที่กล่าวถึงเขา", - "boost_modal.combo": "คุณสามารถกด {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป", + "boost_modal.combo": "คุณสามารถกดปุ่ม {combo} เพื่อข้ามสิ่งนี้ในครั้งถัดไป", "boost_modal.reblog": "ดันโพสต์?", "boost_modal.undo_reblog": "เลิกดันโพสต์?", "bundle_column_error.copy_stacktrace": "คัดลอกรายงานข้อผิดพลาด", @@ -158,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": "ลักษณะ", @@ -197,6 +197,7 @@ "confirmations.unfollow.title": "เลิกติดตามผู้ใช้?", "content_warning.hide": "ซ่อนโพสต์", "content_warning.show": "แสดงต่อไป", + "content_warning.show_more": "แสดงเพิ่มเติม", "conversation.delete": "ลบการสนทนา", "conversation.mark_as_read": "ทำเครื่องหมายว่าอ่านแล้ว", "conversation.open": "ดูการสนทนา", @@ -222,6 +223,8 @@ "domain_block_modal.they_cant_follow": "ไม่มีใครจากเซิร์ฟเวอร์นี้สามารถติดตามคุณ", "domain_block_modal.they_wont_know": "เขาจะไม่ทราบว่ามีการปิดกั้นเขา", "domain_block_modal.title": "ปิดกั้นโดเมน?", + "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 พูดกับเครือข่ายสังคมอื่น ๆ", @@ -303,7 +306,7 @@ "filter_modal.select_filter.subtitle": "ใช้หมวดหมู่ที่มีอยู่หรือสร้างหมวดหมู่ใหม่", "filter_modal.select_filter.title": "กรองโพสต์นี้", "filter_modal.title.status": "กรองโพสต์", - "filter_warning.matches_filter": "ตรงกับตัวกรอง “{title}”", + "filter_warning.matches_filter": "ตรงกับตัวกรอง “{title}”", "filtered_notifications_banner.pending_requests": "จาก {count, plural, =0 {ไม่มีใคร} other {# คน}} ที่คุณอาจรู้จัก", "filtered_notifications_banner.title": "การแจ้งเตือนที่กรองอยู่", "firehose.all": "ทั้งหมด", @@ -383,6 +386,7 @@ "interaction_modal.description.follow": "ด้วยบัญชีใน Mastodon คุณสามารถติดตาม {name} เพื่อรับโพสต์ของเขาในฟีดหน้าแรกของคุณ", "interaction_modal.description.reblog": "ด้วยบัญชีใน Mastodon คุณสามารถดันโพสต์นี้เพื่อแชร์โพสต์กับผู้ติดตามของคุณเอง", "interaction_modal.description.reply": "ด้วยบัญชีใน Mastodon คุณสามารถตอบกลับโพสต์นี้", + "interaction_modal.description.vote": "ด้วยบัญชีใน Mastodon คุณสามารถลงคะแนนในการสำรวจความคิดเห็นนี้", "interaction_modal.login.action": "นำฉันกลับบ้าน", "interaction_modal.login.prompt": "โดเมนของเซิร์ฟเวอร์บ้านของคุณ เช่น mastodon.social", "interaction_modal.no_account_yet": "ไม่ได้อยู่ใน Mastodon?", @@ -394,6 +398,7 @@ "interaction_modal.title.follow": "ติดตาม {name}", "interaction_modal.title.reblog": "ดันโพสต์ของ {name}", "interaction_modal.title.reply": "ตอบกลับโพสต์ของ {name}", + "interaction_modal.title.vote": "ลงคะแนนในการสำรวจความคิดเห็นของ {name}", "intervals.full.days": "{number, plural, other {# วัน}}", "intervals.full.hours": "{number, plural, other {# ชั่วโมง}}", "intervals.full.minutes": "{number, plural, other {# นาที}}", @@ -434,6 +439,8 @@ "lightbox.close": "ปิด", "lightbox.next": "ถัดไป", "lightbox.previous": "ก่อนหน้า", + "lightbox.zoom_in": "ซูมเป็นขนาดจริง", + "lightbox.zoom_out": "ซูมให้พอดี", "limited_account_hint.action": "แสดงโปรไฟล์ต่อไป", "limited_account_hint.title": "มีการซ่อนโปรไฟล์นี้โดยผู้กลั่นกรองของ {domain}", "link_preview.author": "โดย {name}", @@ -504,7 +511,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": "การกล่าวถึง", @@ -563,6 +570,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": "การแจ้งเตือนแบบผลัก", @@ -849,6 +857,11 @@ "upload_error.poll": "ไม่อนุญาตการอัปโหลดไฟล์โดยมีการสำรวจความคิดเห็น", "upload_form.audio_description": "อธิบายสำหรับผู้ที่สูญเสียการได้ยิน", "upload_form.description": "อธิบายสำหรับผู้คนที่พิการทางการมองเห็นหรือมีสายตาเลือนราง", + "upload_form.drag_and_drop.instructions": "เพื่อหยิบไฟล์แนบสื่อ กดปุ่มเว้นวรรคหรือขึ้นบรรทัดใหม่ ขณะลาก ใช้ปุ่มลูกศรเพื่อย้ายไฟล์แนบสื่อในทิศทางใดก็ตามที่กำหนด กดปุ่มเว้นวรรคหรือขึ้นบรรทัดใหม่อีกครั้งเพื่อปล่อยไฟล์แนบสื่อในตำแหน่งใหม่ หรือกดปุ่ม 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/tok.json b/app/javascript/mastodon/locales/tok.json index ba5395b7bd..2cf7f1929a 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", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 937b3e8e19..4699b9f4bd 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Hay aksi!", "alt_text_badge.title": "Alternatif metin", "announcement.announcement": "Duyuru", + "annual_report.summary.archetype.booster": "Trend takipçisi", + "annual_report.summary.archetype.lurker": "Gizli meraklı", + "annual_report.summary.archetype.oracle": "Kahin", + "annual_report.summary.archetype.pollster": "Anketör", + "annual_report.summary.archetype.replier": "Sosyal kelebek", + "annual_report.summary.followers.followers": "takipçiler", + "annual_report.summary.followers.total": "{count} toplam", + "annual_report.summary.here_it_is": "İşte {year} yılı değerlendirmeniz:", + "annual_report.summary.highlighted_post.by_favourites": "en çok beğenilen gönderi", + "annual_report.summary.highlighted_post.by_reblogs": "en çok paylaşılan gönderi", + "annual_report.summary.highlighted_post.by_replies": "en çok yanıt alan gönderi", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "en çok kullanılan uygulama", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "en çok kullanılan etiket", + "annual_report.summary.new_posts.new_posts": "yeni gönderiler", + "annual_report.summary.percentile.text": "Mastodon kullanıcılarınınüst dilimindesiniz.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Bernie'ye söylemeyiz.", + "annual_report.summary.thanks": "Mastodon'un bir parçası olduğunuz için teşekkürler!", "attachments_list.unprocessed": "(işlenmemiş)", "audio.hide": "Sesi gizle", "block_modal.remote_users_caveat": "{domain} sunucusundan kararınıza saygı duymasını isteyeceğiz. Ancak, Uymaları garanti değildir çünkü bazı sunucular engellemeyi farklı şekilde yapıyorlar. Herkese açık gönderiler giriş yapmamış kullanıcılara görüntülenmeye devam edebilir.", @@ -158,7 +176,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", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Kullanıcıyı takipten çık?", "content_warning.hide": "Gönderiyi gizle", "content_warning.show": "Yine de göster", + "content_warning.show_more": "Daha fazla göster", "conversation.delete": "Sohbeti sil", "conversation.mark_as_read": "Okundu olarak işaretle", "conversation.open": "Sohbeti görüntüle", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Mevcut bir kategoriyi kullan veya yeni bir tane oluştur", "filter_modal.select_filter.title": "Bu gönderiyi süzgeçle", "filter_modal.title.status": "Bir gönderi süzgeçle", - "filter_warning.matches_filter": "“{title}” filtresiyle eşleşiyor", + "filter_warning.matches_filter": "“{title}” filtresiyle eşleşiyor", "filtered_notifications_banner.pending_requests": "Bildiğiniz {count, plural, =0 {hiç kimseden} one {bir kişiden} other {# kişiden}}", "filtered_notifications_banner.title": "Filtrelenmiş bildirimler", "firehose.all": "Tümü", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Mastodon'daki bir hesapla, {name} kişisini, ana akışınızdaki gönderilerini görmek üzere takip edebilirsiniz.", "interaction_modal.description.reblog": "Mastodon'daki bir hesapla, bu gönderiyi takipçilerinizle paylaşmak için tuşlayabilirsiniz.", "interaction_modal.description.reply": "Mastodon'daki bir hesapla, bu gönderiye yanıt verebilirsiniz.", + "interaction_modal.description.vote": "Mastodon'daki bir hesapla, bu ankette oy kullanabilirsiniz.", "interaction_modal.login.action": "Anasayfaya geri dön", "interaction_modal.login.prompt": "Ev sunucunuzun etki alanı, örneğin mastodon.social", "interaction_modal.no_account_yet": "Mastodon açık değil?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "{name} kişisini takip et", "interaction_modal.title.reblog": "{name} kişisinin gönderisini yeniden paylaş", "interaction_modal.title.reply": "{name} kişisinin gönderisine yanıt ver", + "interaction_modal.title.vote": "{name} kullanıcısının anketinde oy kullan", "intervals.full.days": "{number, plural, one {# gün} other {# gün}}", "intervals.full.hours": "{number, plural, one {# saat} other {# saat}}", "intervals.full.minutes": "{number, plural, one {# dakika} other {# dakika}}", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name}, {target} kişisini bildirdi", "notification.admin.sign_up": "{name} kaydoldu", "notification.admin.sign_up.name_and_others": "{name} ve {count, plural, one {# diğer kişi} other {# diğer kişi}} kaydoldu", + "notification.annual_report.message": "{year} yılı #Wrapstodon'unuz bekliyor! Yılınızın Mastodon'daki öne çıkanlarını ve anılarınızı gösterin!", + "notification.annual_report.view": "#Wrapstodon'u Görüntüle", "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", @@ -567,6 +590,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", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 5a9d388f0b..b34785ebc3 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -87,6 +87,7 @@ "alert.unexpected.title": "Ой!", "alt_text_badge.title": "Альтернативний текст", "announcement.announcement": "Оголошення", + "annual_report.summary.new_posts.new_posts": "нові дописи", "attachments_list.unprocessed": "(не оброблено)", "audio.hide": "Сховати аудіо", "block_modal.remote_users_caveat": "Ми попросимо сервер {domain} поважати ваше рішення. Однак дотримання вимог не гарантується, оскільки деякі сервери можуть обробляти блоки по-різному. Загальнодоступні дописи все ще можуть бути видимими для користувачів, які не увійшли в систему.", @@ -158,7 +159,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": "Стиль", @@ -197,6 +198,7 @@ "confirmations.unfollow.title": "Відписатися від користувача?", "content_warning.hide": "Сховати допис", "content_warning.show": "Усе одно показати", + "content_warning.show_more": "Показати більше", "conversation.delete": "Видалити бесіду", "conversation.mark_as_read": "Позначити як прочитане", "conversation.open": "Переглянути бесіду", @@ -305,7 +307,7 @@ "filter_modal.select_filter.subtitle": "Використати наявну категорію або створити нову", "filter_modal.select_filter.title": "Фільтрувати цей допис", "filter_modal.title.status": "Фільтрувати допис", - "filter_warning.matches_filter": "Збігається з фільтром “{title}”", + "filter_warning.matches_filter": "Збігається з фільтром “{title}”", "filtered_notifications_banner.pending_requests": "Від {count, plural, =0 {жодної особи} one {однієї особи} few {# осіб} many {# осіб} other {# особи}}, котрих ви можете знати", "filtered_notifications_banner.title": "Відфільтровані сповіщення", "firehose.all": "Всі", @@ -385,6 +387,7 @@ "interaction_modal.description.follow": "Маючи обліковий запис на Mastodon, ви можете підписатися на {name}, щоб отримувати дописи цього користувача у свою стрічку.", "interaction_modal.description.reblog": "Маючи обліковий запис на Mastodon, ви можете поширити цей допис, щоб поділитися ним зі своїми підписниками.", "interaction_modal.description.reply": "Маючи обліковий запис на Mastodon, ви можете відповісти на цей допис.", + "interaction_modal.description.vote": "Маючи обліковий запис на Mastodon, ви можете проголосувати в цьому опитуванні.", "interaction_modal.login.action": "На домашню сторінку", "interaction_modal.login.prompt": "Домен вашого домашнього сервера, наприклад, mastodon.social", "interaction_modal.no_account_yet": "Не зареєстровані в Mastodon?", @@ -396,6 +399,7 @@ "interaction_modal.title.follow": "Підписатися на {name}", "interaction_modal.title.reblog": "Поширити допис {name}", "interaction_modal.title.reply": "Відповісти на допис {name}", + "interaction_modal.title.vote": "Проголосувати в опитуванні {name}", "intervals.full.days": "{number, plural, one {# день} few {# дні} other {# днів}}", "intervals.full.hours": "{number, plural, one {# година} few {# години} other {# годин}}", "intervals.full.minutes": "{number, plural, one {# хвилина} few {# хвилини} other {# хвилин}}", @@ -508,7 +512,7 @@ "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.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": "Згадка", @@ -567,6 +571,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-сповіщення", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index cf33a15d32..2b5401a878 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -87,6 +87,24 @@ "alert.unexpected.title": "Ốiii!", "alt_text_badge.title": "Văn bản thay thế", "announcement.announcement": "Có gì mới?", + "annual_report.summary.archetype.booster": "Hiệp sĩ ngầu", + "annual_report.summary.archetype.lurker": "Kẻ rình mò", + "annual_report.summary.archetype.oracle": "Nhà tiên tri", + "annual_report.summary.archetype.pollster": "Chuyên gia khảo sát", + "annual_report.summary.archetype.replier": "Bướm xã hội", + "annual_report.summary.followers.followers": "người theo dõi", + "annual_report.summary.followers.total": "tổng {count}", + "annual_report.summary.here_it_is": "Nhìn lại năm {year} của bạn:", + "annual_report.summary.highlighted_post.by_favourites": "tút được thích nhiều nhất", + "annual_report.summary.highlighted_post.by_reblogs": "tút được đăng lại nhiều nhất", + "annual_report.summary.highlighted_post.by_replies": "tút được trả lời nhiều nhất", + "annual_report.summary.highlighted_post.possessive": "{name}", + "annual_report.summary.most_used_app.most_used_app": "app dùng nhiều nhất", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "hashtag dùng nhiều nhất", + "annual_report.summary.new_posts.new_posts": "tút mới", + "annual_report.summary.percentile.text": "Bạn nằm trong topthành viên Mastodon.", + "annual_report.summary.percentile.we_wont_tell_bernie": "Chúng tôi sẽ không kể cho Bernie.", + "annual_report.summary.thanks": "Cảm ơn đã trở thành một phần của Mastodon!", "attachments_list.unprocessed": "(chưa xử lí)", "audio.hide": "Ẩn âm thanh", "block_modal.remote_users_caveat": "Chúng tôi sẽ yêu cầu {domain} tôn trọng quyết định của bạn. Tuy nhiên, việc tuân thủ không được đảm bảo vì một số máy chủ có thể xử lý việc chặn theo cách khác nhau. Các tút công khai vẫn có thể hiển thị đối với người dùng chưa đăng nhập.", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "Bỏ theo dõi", "content_warning.hide": "Ẩn lại", "content_warning.show": "Nhấn để xem", + "content_warning.show_more": "Hiện thêm", "conversation.delete": "Xóa tin nhắn này", "conversation.mark_as_read": "Đánh dấu là đã đọc", "conversation.open": "Xem toàn bộ tin nhắn", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "Sử dụng một danh mục hiện có hoặc tạo một danh mục mới", "filter_modal.select_filter.title": "Lọc tút này", "filter_modal.title.status": "Lọc một tút", - "filter_warning.matches_filter": "Khớp bộ lọc “{title}”", + "filter_warning.matches_filter": "Khớp bộ lọc “{title}”", "filtered_notifications_banner.pending_requests": "Từ {count, plural, =0 {không ai} other {# người}} bạn có thể biết", "filtered_notifications_banner.title": "Thông báo đã lọc", "firehose.all": "Toàn bộ", @@ -385,6 +404,7 @@ "interaction_modal.description.follow": "Với tài khoản Mastodon, bạn có thể theo dõi {name} để tút của họ hiện trên bảng tin của mình.", "interaction_modal.description.reblog": "Với tài khoản Mastodon, bạn có thể đăng lại tút này để chia sẻ nó với những người đang theo dõi bạn.", "interaction_modal.description.reply": "Với tài khoản Mastodon, bạn có thể trả lời tút này.", + "interaction_modal.description.vote": "Với tài khoản Mastodon, bạn có thể tham gia bình chọn.", "interaction_modal.login.action": "Đăng nhập ngay", "interaction_modal.login.prompt": "Địa chỉ máy chủ của bạn, vd: mastodon.social", "interaction_modal.no_account_yet": "Chưa có tài khoản Mastodon?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "Theo dõi {name}", "interaction_modal.title.reblog": "Đăng lại tút của {name}", "interaction_modal.title.reply": "Trả lời tút của {name}", + "interaction_modal.title.vote": "Bình chọn cùng {name}", "intervals.full.days": "{number, plural, other {# ngày}}", "intervals.full.hours": "{number, plural, other {# giờ}}", "intervals.full.minutes": "{number, plural, other {# phút}}", @@ -441,7 +462,7 @@ "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 {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", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} báo cáo {target}", "notification.admin.sign_up": "{name} tham gia máy chủ của bạn", "notification.admin.sign_up.name_and_others": "{name} và {count, plural, other {# người}} đã đăng ký", + "notification.annual_report.message": "#Wrapstodon {year} của bạn có rồi đây! Hãy chia sẻ những điểm nhấn và khoảnh khắc đáng nhớ trên Mastodon của bạn trong năm qua!", + "notification.annual_report.view": "Xem #Wrapstodon", "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", @@ -527,7 +550,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}", @@ -567,6 +590,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", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 74702e5127..57b2011bb1 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} 条嘟文}}", @@ -87,6 +87,24 @@ "alert.unexpected.title": "哎呀!", "alt_text_badge.title": "替代文本", "announcement.announcement": "公告", + "annual_report.summary.archetype.booster": "潮流捕手", + "annual_report.summary.archetype.lurker": "吃瓜群众", + "annual_report.summary.archetype.oracle": "预言家", + "annual_report.summary.archetype.pollster": "投票狂魔", + "annual_report.summary.archetype.replier": "评论区原住民", + "annual_report.summary.followers.followers": "关注者", + "annual_report.summary.followers.total": "{count} 人", + "annual_report.summary.here_it_is": "你的 {year} 年度回顾在此:", + "annual_report.summary.highlighted_post.by_favourites": "最受欢迎嘟嘟", + "annual_report.summary.highlighted_post.by_reblogs": "传播最广嘟嘟", + "annual_report.summary.highlighted_post.by_replies": "最热闹嘟嘟", + "annual_report.summary.highlighted_post.possessive": "{name} 的", + "annual_report.summary.most_used_app.most_used_app": "最常用的应用", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "最常用的话题", + "annual_report.summary.new_posts.new_posts": "新发嘟", + "annual_report.summary.percentile.text": "这使你跻身 Mastodon 用户的前", + "annual_report.summary.percentile.we_wont_tell_bernie": "我们打死也不会告诉Bernie。", + "annual_report.summary.thanks": "感谢你这一年与 Mastodon 一路同行!", "attachments_list.unprocessed": "(未处理)", "audio.hide": "隐藏音频", "block_modal.remote_users_caveat": "我们将要求服务器 {domain} 尊重您的决定。然而,我们无法保证对方一定遵从,因为某些服务器可能会以不同的方案处理屏蔽操作。公开嘟文仍然可能对未登录的用户可见。", @@ -94,8 +112,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": "是否转嘟?", @@ -197,6 +215,7 @@ "confirmations.unfollow.title": "是否取消关注用户?", "content_warning.hide": "隐藏嘟文", "content_warning.show": "仍然显示", + "content_warning.show_more": "显示更多", "conversation.delete": "删除对话", "conversation.mark_as_read": "标记为已读", "conversation.open": "查看对话", @@ -204,7 +223,7 @@ "copy_icon_button.copied": "已复制到剪贴板", "copypaste.copied": "已复制", "copypaste.copy_to_clipboard": "复制到剪贴板", - "directory.federated": "来自已知的联邦宇宙", + "directory.federated": "来自已知联邦宇宙", "directory.local": "仅来自 {domain}", "directory.new_arrivals": "新来者", "directory.recently_active": "最近活跃", @@ -220,24 +239,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_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": "活动", @@ -305,7 +324,7 @@ "filter_modal.select_filter.subtitle": "使用一个已存在类别,或创建一个新类别", "filter_modal.select_filter.title": "过滤此嘟文", "filter_modal.title.status": "过滤一条嘟文", - "filter_warning.matches_filter": "命中过滤规则 “{title}”", + "filter_warning.matches_filter": "命中过滤规则 “{title}”", "filtered_notifications_banner.pending_requests": "来自你可能认识的 {count, plural, =0 {0 个人} other {# 个人}}", "filtered_notifications_banner.title": "通知(已过滤)", "firehose.all": "全部", @@ -382,9 +401,10 @@ "ignore_notifications_modal.not_following_title": "是否忽略你未关注的人的通知?", "ignore_notifications_modal.private_mentions_title": "是否忽略不请自来的私下提及?", "interaction_modal.description.favourite": "只需一个 Mastodon 账号,即可喜欢这条嘟文,对嘟文的作者展示您欣赏的态度,并保存嘟文以供日后使用。", - "interaction_modal.description.follow": "拥有一个 Mastodon 账号,你可以关注 {name} 并在自己的主页上接收对方的新嘟文。", - "interaction_modal.description.reblog": "拥有一个 Mastodon 账号,你可以向自己的关注者们转发此嘟文。", - "interaction_modal.description.reply": "拥有一个 Mastodon 账号,你可以回复此嘟文。", + "interaction_modal.description.follow": "拥有一个 Mastodon 账号,你就可以关注 {name} 并在自己的主页上接收对方的新嘟文。", + "interaction_modal.description.reblog": "拥有一个 Mastodon 账号,你就可以向自己的关注者们转发此嘟文。", + "interaction_modal.description.reply": "拥有一个 Mastodon 账号,你就可以回复此嘟文。", + "interaction_modal.description.vote": "拥有一个 Mastodon 账号,你就可以参与此投票。", "interaction_modal.login.action": "转到主页", "interaction_modal.login.prompt": "您所入驻的服务器域名,如:mastodon.social", "interaction_modal.no_account_yet": "不在 Mastodon 上?", @@ -396,6 +416,7 @@ "interaction_modal.title.follow": "关注 {name}", "interaction_modal.title.reblog": "转发 {name} 的嘟文", "interaction_modal.title.reply": "回复 {name} 的嘟文", + "interaction_modal.title.vote": "参与 {name} 的投票", "intervals.full.days": "{number} 天", "intervals.full.hours": "{number} 小时", "intervals.full.minutes": "{number} 分钟", @@ -465,11 +486,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": "在高级网页界面中打开", @@ -505,10 +526,12 @@ "notification.admin.report_statuses_other": "{name} 举报了 {target}", "notification.admin.sign_up": "{name} 注册了", "notification.admin.sign_up.name_and_others": "{name} 和 {count, plural, other {另外 # 人}}注册了", + "notification.annual_report.message": "你的 {year} #Wrapstodon 年度回顾来啦!快来看看这一年你在 Mastodon 上的精彩瞬间!", + "notification.annual_report.view": "查看 #Wrapstodon", "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": "提及", @@ -524,15 +547,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} 刚刚发布嘟文", @@ -567,6 +590,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": "推送通知", @@ -781,14 +805,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": "喜欢", @@ -815,10 +839,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": "分享", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index a081e55897..8acd6df078 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -11,6 +11,7 @@ "about.not_available": "本伺服器尚未提供這資訊。", "about.powered_by": "由 {mastodon} 提供之去中心化社交媒體", "about.rules": "伺服器規則", + "account.account_note_header": "個人筆記", "account.add_or_remove_from_list": "從列表中新增或移除", "account.badges.bot": "機械人", "account.badges.group": "群組", @@ -33,6 +34,7 @@ "account.follow_back": "追蹤對方", "account.followers": "追蹤者", "account.followers.empty": "尚未有人追蹤這位使用者。", + "account.followers_counter": "{count, plural, other {{counter} 個追蹤者}}", "account.following": "正在追蹤", "account.follows.empty": "這位使用者尚未追蹤任何人。", "account.go_to_profile": "前往個人檔案", @@ -81,6 +83,7 @@ "alert.rate_limited.title": "已限速", "alert.unexpected.message": "發生意外錯誤。", "alert.unexpected.title": "失敗!", + "alt_text_badge.title": "替代文字", "announcement.announcement": "公告", "attachments_list.unprocessed": "(未處理)", "audio.hide": "隱藏音訊", @@ -151,7 +154,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": "風格", @@ -169,6 +172,7 @@ "confirmations.delete.title": "刪除帖文?", "confirmations.delete_list.confirm": "刪除", "confirmations.delete_list.message": "你確定要永久刪除這列表嗎?", + "confirmations.delete_list.title": "刪除列表?", "confirmations.discard_edit_media.confirm": "捨棄", "confirmations.discard_edit_media.message": "您在媒體描述或預覽有尚未儲存的變更。確定要捨棄它們嗎?", "confirmations.edit.confirm": "編輯", @@ -183,6 +187,9 @@ "confirmations.reply.message": "現在回覆將蓋掉您目前正在撰寫的訊息。是否仍要回覆?", "confirmations.unfollow.confirm": "取消追蹤", "confirmations.unfollow.message": "真的不要繼續追蹤 {name} 了嗎?", + "confirmations.unfollow.title": "取消追蹤使用者?", + "content_warning.hide": "隱藏嘟文", + "content_warning.show": "仍要顯示", "conversation.delete": "刪除對話", "conversation.mark_as_read": "標為已讀", "conversation.open": "檢視對話", @@ -344,6 +351,7 @@ "home.pending_critical_update.link": "查看更新", "home.pending_critical_update.title": "有重要的安全更新!", "home.show_announcements": "顯示公告", + "ignore_notifications_modal.ignore": "忽略推播通知", "interaction_modal.description.favourite": "有了 Mastodon 的帳號,你便可以把這篇帖文加入最愛,讓作者知道你欣賞他的作品,並可以稍後再閱讀。", "interaction_modal.description.follow": "在 Mastodon 上有個帳號的話,您可以追蹤 {name} 以於首頁時間軸接收他們的帖文。", "interaction_modal.description.reblog": "在 Mastodon 上有個帳號的話,您可以向自己的追縱者們轉發此帖文。", @@ -418,6 +426,7 @@ "lists.subheading": "列表", "load_pending": "{count, plural, other {# 個新項目}}", "loading_indicator.label": "載入中…", + "media_gallery.hide": "隱藏", "moved_to_account_banner.text": "您的帳號 {disabledAccount} 目前已停用,因為您已搬家至 {movedToAccount}。", "mute_modal.hide_from_notifications": "隱藏通知", "mute_modal.hide_options": "隱藏選項", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index e93f7d5180..e1f9eeb210 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -1,7 +1,7 @@ { "about.blocks": "被限制的伺服器", "about.contact": "聯絡我們:", - "about.disclaimer": "Mastodon 是一個自由的開源軟體,是 Mastodon gGmbH 的註冊商標。", + "about.disclaimer": "Mastodon 是一個自由的開源軟體,是 Mastodon gGmbH 之註冊商標。", "about.domain_blocks.no_reason_available": "無法存取的原因", "about.domain_blocks.preamble": "Mastodon 基本上允許您瀏覽聯邦宇宙中任何伺服器的內容並與使用者互動。以下是在本伺服器上設定的例外。", "about.domain_blocks.silenced.explanation": "一般來說您不會看到來自這個伺服器的個人檔案和內容,除非您明確搜尋或主動跟隨對方。", @@ -87,6 +87,23 @@ "alert.unexpected.title": "哎呀!", "alt_text_badge.title": "ALT 說明文字", "announcement.announcement": "公告", + "annual_report.summary.archetype.booster": "酷炫的獵人", + "annual_report.summary.archetype.lurker": "潛伏者", + "annual_report.summary.archetype.oracle": "先知", + "annual_report.summary.archetype.pollster": "民調人員", + "annual_report.summary.archetype.replier": "社交菁英", + "annual_report.summary.followers.followers": "跟隨者", + "annual_report.summary.followers.total": "總共 {count}", + "annual_report.summary.here_it_is": "以下是您的{year}年度回顧:", + "annual_report.summary.highlighted_post.by_favourites": "最愛的嘟文", + "annual_report.summary.highlighted_post.by_reblogs": "最多轉嘟的嘟文", + "annual_report.summary.highlighted_post.by_replies": "最多回覆的嘟文", + "annual_report.summary.highlighted_post.possessive": "{name} 的", + "annual_report.summary.most_used_app.most_used_app": "最常使用的應用程式", + "annual_report.summary.most_used_hashtag.most_used_hashtag": "最常使用的主題標籤", + "annual_report.summary.new_posts.new_posts": "新嘟文", + "annual_report.summary.percentile.text": "這讓您成為前Mastodon 的使用者。", + "annual_report.summary.thanks": "感謝您成為 Mastodon 的一員!", "attachments_list.unprocessed": "(未經處理)", "audio.hide": "隱藏音訊", "block_modal.remote_users_caveat": "我們會要求 {domain} 伺服器尊重您的決定。然而,我們無法保證所有伺服器皆會遵守,某些伺服器可能以不同方式處理封鎖。未登入之使用者仍可能看見您的公開嘟文。", @@ -158,7 +175,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": "投票方式", @@ -197,6 +214,7 @@ "confirmations.unfollow.title": "是否取消跟隨該使用者?", "content_warning.hide": "隱藏嘟文", "content_warning.show": "仍要顯示", + "content_warning.show_more": "顯示更多", "conversation.delete": "刪除對話", "conversation.mark_as_read": "標記為已讀", "conversation.open": "檢視對話", @@ -305,7 +323,7 @@ "filter_modal.select_filter.subtitle": "使用既有的類別或是新增", "filter_modal.select_filter.title": "過濾此嘟文", "filter_modal.title.status": "過濾一則嘟文", - "filter_warning.matches_filter": "匹配過濾器「{title}」", + "filter_warning.matches_filter": "符合過濾器「{title}」", "filtered_notifications_banner.pending_requests": "來自您可能認識的 {count, plural, =0 {0 人} other {# 人}}", "filtered_notifications_banner.title": "已過濾之推播通知", "firehose.all": "全部", @@ -385,6 +403,7 @@ "interaction_modal.description.follow": "若於 Mastodon 上有個帳號,您可以跟隨 {name} 以於首頁時間軸接收他們的嘟文。", "interaction_modal.description.reblog": "若於 Mastodon 上有個帳號,您可以轉嘟此嘟文以向您的跟隨者們分享。", "interaction_modal.description.reply": "若於 Mastodon 上有個帳號,您可以回覆此嘟文。", + "interaction_modal.description.vote": "若於 Mastodon 上有個帳號,您可以參與此投票。", "interaction_modal.login.action": "返回首頁", "interaction_modal.login.prompt": "您帳號所屬伺服器之網域,例如:mastodon.social", "interaction_modal.no_account_yet": "還沒有 Mastodon 帳號嗎?", @@ -396,9 +415,10 @@ "interaction_modal.title.follow": "跟隨 {name}", "interaction_modal.title.reblog": "轉嘟 {name} 的嘟文", "interaction_modal.title.reply": "回覆 {name} 的嘟文", - "intervals.full.days": "{number, plural, one {# 天} other {# 天}}", - "intervals.full.hours": "{number, plural, one {# 小時} other {# 小時}}", - "intervals.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}}", + "interaction_modal.title.vote": "參與 {name} 之投票", + "intervals.full.days": "{number, plural, other {# 天}}", + "intervals.full.hours": "{number, plural, other {# 小時}}", + "intervals.full.minutes": "{number, plural, other {# 分鐘}}", "keyboard_shortcuts.back": "上一頁", "keyboard_shortcuts.blocked": "開啟「封鎖使用者」列表", "keyboard_shortcuts.boost": "轉嘟", @@ -457,7 +477,7 @@ "lists.replies_policy.title": "顯示回覆:", "lists.search": "搜尋您跟隨之使用者", "lists.subheading": "您的列表", - "load_pending": "{count, plural, one {# 個新項目} other {# 個新項目}}", + "load_pending": "{count, plural, other {# 個新項目}}", "loading_indicator.label": "正在載入...", "media_gallery.hide": "隱藏", "moved_to_account_banner.text": "您的帳號 {disabledAccount} 目前已停用,因為您已搬家至 {movedToAccount}。", @@ -499,8 +519,8 @@ "navigation_bar.security": "安全性", "not_signed_in_indicator.not_signed_in": "您需要登入才能存取此資源。", "notification.admin.report": "{name} 已檢舉 {target}", - "notification.admin.report_account": "{name} 已檢舉來自 {target} 關於 {category} 之 {count, plural, other {# 則嘟文}} ", - "notification.admin.report_account_other": "{name} 已檢舉來自 {target} 之 {count, plural, other {# 則嘟文}} ", + "notification.admin.report_account": "{name} 已檢舉來自 {target} 關於 {category} 之 {count, plural, other {# 則嘟文}}", + "notification.admin.report_account_other": "{name} 已檢舉來自 {target} 之 {count, plural, other {# 則嘟文}}", "notification.admin.report_statuses": "{name} 已檢舉 {target} 關於 {category}", "notification.admin.report_statuses_other": "{name} 已檢舉 {target}", "notification.admin.sign_up": "{name} 已經註冊", @@ -508,7 +528,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": "提及", @@ -567,6 +587,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": "推播通知", @@ -654,11 +675,11 @@ "poll.closed": "已關閉", "poll.refresh": "重新整理", "poll.reveal": "檢視結果", - "poll.total_people": "{count, plural, one {# 個投票} other {# 個投票}}", - "poll.total_votes": "{count, plural, one {# 個投票} other {# 個投票}}", + "poll.total_people": "{count, plural, other {# 個人}}", + "poll.total_votes": "{count, plural, other {# 張票}}", "poll.vote": "投票", "poll.voted": "您已對此問題投票", - "poll.votes": "{votes, plural, one {# 張票} other {# 張票}}", + "poll.votes": "{votes, plural, other {# 張票}}", "poll_button.add_poll": "新增投票", "poll_button.remove_poll": "移除投票", "privacy.change": "調整嘟文隱私狀態", @@ -679,10 +700,10 @@ "regeneration_indicator.sublabel": "您的首頁時間軸正在準備中!", "relative_time.days": "{number} 天", "relative_time.full.days": "{number, plural, other {# 天}}前", - "relative_time.full.hours": "{number, plural, one {# 小時} other {# 小時}}前", + "relative_time.full.hours": "{number, plural, other {# 小時}}前", "relative_time.full.just_now": "剛剛", - "relative_time.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}}前", - "relative_time.full.seconds": "{number, plural, one {# 秒} other {# 秒}}前", + "relative_time.full.minutes": "{number, plural, other {# 分鐘}}前", + "relative_time.full.seconds": "{number, plural, other {# 秒}}前", "relative_time.hours": "{number} 小時前", "relative_time.just_now": "剛剛", "relative_time.minutes": "{number} 分鐘前", @@ -792,7 +813,7 @@ "status.edited_x_times": "已編輯 {count, plural, one {{count} 次} other {{count} 次}}", "status.embed": "取得嵌入程式碼", "status.favourite": "最愛", - "status.favourites": "{count, plural, other {# 則最愛}}", + "status.favourites": "{count, plural, other {則最愛}}", "status.filter": "過濾此嘟文", "status.history.created": "{name} 於 {date} 建立", "status.history.edited": "{name} 於 {date} 修改", @@ -811,7 +832,7 @@ "status.reblog": "轉嘟", "status.reblog_private": "依照原嘟可見性轉嘟", "status.reblogged_by": "{name} 已轉嘟", - "status.reblogs": "{count, plural, other {# 則轉嘟}}", + "status.reblogs": "{count, plural, other {則轉嘟}}", "status.reblogs.empty": "還沒有人轉嘟過這則嘟文。當有人轉嘟時,它將於此顯示。", "status.redraft": "刪除並重新編輯", "status.remove_bookmark": "移除書籤", @@ -836,11 +857,11 @@ "subscribed_languages.target": "變更 {target} 的訂閱語言", "tabs_bar.home": "首頁", "tabs_bar.notifications": "通知", - "time_remaining.days": "剩餘 {number, plural, one {# 天} other {# 天}}", - "time_remaining.hours": "剩餘 {number, plural, one {# 小時} other {# 小時}}", - "time_remaining.minutes": "剩餘 {number, plural, one {# 分鐘} other {# 分鐘}}", + "time_remaining.days": "剩餘 {number, plural, other {# 天}}", + "time_remaining.hours": "剩餘{number, plural, other {# 小時}}", + "time_remaining.minutes": "剩餘{number, plural, other {# 分鐘}}", "time_remaining.moments": "剩餘時間", - "time_remaining.seconds": "剩餘 {number, plural, one {# 秒} other {# 秒}}", + "time_remaining.seconds": "剩餘{number, plural, other {# 秒}}", "trends.counter_by_accounts": "{count, plural, one {{counter} 人} other {{counter} 人}}於過去 {days, plural, one {日} other {{days} 日}} 之間", "trends.trending_now": "現正熱門趨勢", "ui.beforeunload": "如果離開 Mastodon,您的草稿將會不見。", diff --git a/app/javascript/mastodon/models/annual_report.ts b/app/javascript/mastodon/models/annual_report.ts new file mode 100644 index 0000000000..c0a101e6c8 --- /dev/null +++ b/app/javascript/mastodon/models/annual_report.ts @@ -0,0 +1,44 @@ +export interface Percentiles { + followers: number; + statuses: number; +} + +export interface NameAndCount { + name: string; + count: number; +} + +export interface TimeSeriesMonth { + month: number; + statuses: number; + following: number; + followers: number; +} + +export interface TopStatuses { + by_reblogs: number; + by_favourites: number; + by_replies: number; +} + +export type Archetype = + | 'lurker' + | 'booster' + | 'pollster' + | 'replier' + | 'oracle'; + +interface AnnualReportV1 { + most_used_apps: NameAndCount[]; + percentiles: Percentiles; + top_hashtags: NameAndCount[]; + top_statuses: TopStatuses; + time_series: TimeSeriesMonth[]; + archetype: Archetype; +} + +export interface AnnualReport { + year: number; + schema_version: number; + data: AnnualReportV1; +} diff --git a/app/javascript/mastodon/models/notification_group.ts b/app/javascript/mastodon/models/notification_group.ts index 09d407d449..01a341e8dd 100644 --- a/app/javascript/mastodon/models/notification_group.ts +++ b/app/javascript/mastodon/models/notification_group.ts @@ -1,6 +1,7 @@ import type { ApiAccountRelationshipSeveranceEventJSON, ApiAccountWarningJSON, + ApiAnnualReportEventJSON, BaseNotificationGroupJSON, ApiNotificationGroupJSON, ApiNotificationJSON, @@ -65,6 +66,12 @@ export interface NotificationGroupSeveredRelationships event: AccountRelationshipSeveranceEvent; } +type AnnualReportEvent = ApiAnnualReportEventJSON; +export interface NotificationGroupAnnualReport + extends BaseNotification<'annual_report'> { + annualReport: AnnualReportEvent; +} + interface Report extends Omit { targetAccountId: string; } @@ -86,7 +93,8 @@ export type NotificationGroup = | NotificationGroupModerationWarning | NotificationGroupSeveredRelationships | NotificationGroupAdminSignUp - | NotificationGroupAdminReport; + | NotificationGroupAdminReport + | NotificationGroupAnnualReport; function createReportFromJSON(reportJSON: ApiReportJSON): Report { const { target_account, ...report } = reportJSON; @@ -112,6 +120,12 @@ function createAccountRelationshipSeveranceEventFromJSON( return eventJson; } +function createAnnualReportEventFromJSON( + eventJson: ApiAnnualReportEventJSON, +): AnnualReportEvent { + return eventJson; +} + export function createNotificationGroupFromJSON( groupJson: ApiNotificationGroupJSON, ): NotificationGroup { @@ -145,7 +159,6 @@ export function createNotificationGroupFromJSON( event: createAccountRelationshipSeveranceEventFromJSON(group.event), sampleAccountIds, }; - case 'moderation_warning': { const { moderation_warning, ...groupWithoutModerationWarning } = group; return { @@ -154,6 +167,14 @@ export function createNotificationGroupFromJSON( sampleAccountIds, }; } + case 'annual_report': { + const { annual_report, ...groupWithoutAnnualReport } = group; + return { + ...groupWithoutAnnualReport, + annualReport: createAnnualReportEventFromJSON(annual_report), + sampleAccountIds, + }; + } default: return { sampleAccountIds, diff --git a/app/javascript/mastodon/reducers/accounts.ts b/app/javascript/mastodon/reducers/accounts.ts index 5a9cc7220c..2001353b2e 100644 --- a/app/javascript/mastodon/reducers/accounts.ts +++ b/app/javascript/mastodon/reducers/accounts.ts @@ -57,7 +57,10 @@ export const accountsReducer: Reducer = ( return state.setIn([action.payload.id, 'hidden'], false); else if (importAccounts.match(action)) return normalizeAccounts(state, action.payload.accounts); - else if (followAccountSuccess.match(action)) { + else if ( + followAccountSuccess.match(action) && + !action.payload.alreadyFollowing + ) { return state .update(action.payload.relationship.id, (account) => account?.update('followers_count', (n) => n + 1), diff --git a/app/javascript/mastodon/reducers/notification_groups.ts b/app/javascript/mastodon/reducers/notification_groups.ts index 91e91d7549..7a165f5fec 100644 --- a/app/javascript/mastodon/reducers/notification_groups.ts +++ b/app/javascript/mastodon/reducers/notification_groups.ts @@ -21,7 +21,6 @@ import { unmountNotifications, refreshStaleNotificationGroups, pollRecentNotifications, - shouldGroupNotificationType, } from 'mastodon/actions/notification_groups'; import { disconnectTimeline, @@ -30,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'; @@ -205,8 +205,9 @@ function mergeGapsAround( function processNewNotification( groups: NotificationGroupsState['groups'], notification: ApiNotificationJSON, + groupedTypes: NotificationType[], ) { - if (!shouldGroupNotificationType(notification.type)) { + if (!groupedTypes.includes(notification.type)) { notification = { ...notification, group_key: `ungrouped-${notification.id}`, @@ -476,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); diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 8944555eb9..a1f43735b0 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -81,6 +81,10 @@ const initialState = ImmutableMap({ 'admin.sign_up': true, 'admin.report': true, }), + + group: ImmutableMap({ + follow: true + }), }), firehose: ImmutableMap({ diff --git a/app/javascript/mastodon/selectors/settings.ts b/app/javascript/mastodon/selectors/settings.ts index e722ad0911..ca34374167 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/material-icons/400-24px/celebration-fill.svg b/app/javascript/material-icons/400-24px/celebration-fill.svg new file mode 100644 index 0000000000..d715cf2fb3 --- /dev/null +++ b/app/javascript/material-icons/400-24px/celebration-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/celebration.svg b/app/javascript/material-icons/400-24px/celebration.svg new file mode 100644 index 0000000000..1d1b19ee72 --- /dev/null +++ b/app/javascript/material-icons/400-24px/celebration.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/javascript/material-icons/400-24px/explore-fill.svg b/app/javascript/material-icons/400-24px/explore-fill.svg index febe0a63b4..919ecb580a 100644 --- a/app/javascript/material-icons/400-24px/explore-fill.svg +++ b/app/javascript/material-icons/400-24px/explore-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/explore.svg b/app/javascript/material-icons/400-24px/explore.svg index 547a999421..bb8ba1f4c6 100644 --- a/app/javascript/material-icons/400-24px/explore.svg +++ b/app/javascript/material-icons/400-24px/explore.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss index 465b748078..109b69bca5 100644 --- a/app/javascript/styles/application.scss +++ b/app/javascript/styles/application.scss @@ -15,6 +15,7 @@ @import 'mastodon/polls'; @import 'mastodon/modal'; @import 'mastodon/emoji_picker'; +@import 'mastodon/annual_reports'; @import 'mastodon/about'; @import 'mastodon/tables'; @import 'mastodon/admin'; diff --git a/app/javascript/styles/mastodon-light/variables.scss b/app/javascript/styles/mastodon-light/variables.scss index 76bdc4022e..777c622ace 100644 --- a/app/javascript/styles/mastodon-light/variables.scss +++ b/app/javascript/styles/mastodon-light/variables.scss @@ -76,4 +76,7 @@ body { --background-color-tint: rgba(255, 255, 255, 80%); --background-filter: blur(10px); --on-surface-color: #{transparentize($ui-base-color, 0.65)}; + --rich-text-container-color: rgba(255, 216, 231, 100%); + --rich-text-text-color: rgba(114, 47, 83, 100%); + --rich-text-decorations-color: rgba(255, 175, 212, 100%); } diff --git a/app/javascript/styles/mastodon/annual_reports.scss b/app/javascript/styles/mastodon/annual_reports.scss new file mode 100644 index 0000000000..39784e3b5e --- /dev/null +++ b/app/javascript/styles/mastodon/annual_reports.scss @@ -0,0 +1,335 @@ +:root { + --indigo-1: #17063b; + --indigo-2: #2f0c7a; + --indigo-3: #562cfc; + --indigo-5: #858afa; + --indigo-6: #cccfff; + --lime: #baff3b; + --goldenrod-2: #ffc954; +} + +.annual-report { + flex: 0 0 auto; + background: var(--indigo-1); + padding: 24px; + + &__header { + margin-bottom: 16px; + + h1 { + font-size: 25px; + font-weight: 600; + line-height: 30px; + color: var(--lime); + margin-bottom: 8px; + } + + p { + font-size: 16px; + font-weight: 600; + line-height: 20px; + color: var(--indigo-6); + } + } + + &__bento { + display: grid; + gap: 8px; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); + grid-template-rows: minmax(0, auto) minmax(0, 1fr) minmax(0, auto) minmax( + 0, + auto + ); + + &__box { + padding: 16px; + border-radius: 8px; + background: var(--indigo-2); + color: var(--indigo-5); + } + } + + &__summary { + &__most-boosted-post { + grid-column: span 2; + grid-row: span 2; + padding: 0; + + .status__content, + .content-warning { + color: var(--indigo-6); + } + + .detailed-status { + border: 0; + } + + .content-warning { + border: 0; + background: var(--indigo-1); + + .link-button { + color: var(--indigo-5); + } + } + + .detailed-status__meta__line { + border-bottom-color: var(--indigo-3); + } + + .detailed-status__meta { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .detailed-status__meta, + .poll__footer, + .poll__link, + .detailed-status .logo, + .detailed-status__display-name { + color: var(--indigo-5); + } + + .detailed-status__meta .animated-number, + .detailed-status__display-name strong { + color: var(--indigo-6); + } + + .poll__chart { + background-color: var(--indigo-3); + + &.leading { + background-color: var(--goldenrod-2); + } + } + } + + &__followers { + grid-column: span 1; + text-align: center; + position: relative; + overflow: hidden; + padding-block-start: 24px; + padding-block-end: 24px; + + --sparkline-gradient-top: rgba(86, 44, 252, 50%); + --sparkline-gradient-bottom: rgba(86, 44, 252, 0%); + + &__foreground { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + position: relative; + z-index: 1; + } + + &__number { + font-size: 31px; + font-weight: 600; + line-height: 37px; + color: var(--lime); + } + + &__label { + font-size: 14px; + font-weight: 600; + line-height: 17px; + color: var(--indigo-6); + } + + &__footnote { + display: block; + font-weight: 400; + opacity: 0.5; + } + + svg { + position: absolute; + bottom: 0; + inset-inline-end: 0; + pointer-events: none; + z-index: 0; + height: 70%; + width: auto; + + path:first-child { + fill: url('#gradient') !important; + fill-opacity: 1 !important; + } + + path:last-child { + stroke: var(--indigo-3) !important; + fill: none !important; + } + } + } + + &__archetype { + grid-column: span 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 8px; + padding: 0; + + img { + display: block; + width: 100%; + height: auto; + border-radius: 8px; + } + + &__label { + padding: 16px; + padding-bottom: 8px; + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--lime); + } + } + + &__most-used-app { + grid-column: span 1; + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + box-sizing: border-box; + + &__label { + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--indigo-6); + } + + &__icon { + font-size: 14px; + line-height: 17px; + font-weight: 600; + color: var(--goldenrod-2); + } + } + + &__percentile { + grid-row: span 2; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + text-align: center; + text-wrap: balance; + padding: 16px 8px; + + &__label { + font-size: 14px; + line-height: 17px; + } + + &__number { + font-size: 61px; + font-weight: 600; + line-height: 73px; + color: var(--goldenrod-2); + } + + &__footnote { + font-size: 11px; + line-height: 14px; + opacity: 0.5; + } + } + + &__new-posts { + grid-column: span 2; + text-align: center; + position: relative; + overflow: hidden; + + &__label { + font-size: 20px; + font-weight: 600; + line-height: 24px; + color: var(--indigo-6); + z-index: 1; + position: relative; + } + + &__number { + font-size: 76px; + font-weight: 600; + line-height: 91px; + color: var(--goldenrod-2); + z-index: 1; + position: relative; + } + + svg { + position: absolute; + inset-inline-start: -7px; + top: -4px; + z-index: 0; + } + } + + &__most-used-hashtag { + grid-column: span 2; + text-align: center; + overflow: hidden; + + &__hashtag { + font-size: 42px; + font-weight: 600; + line-height: 58px; + color: var(--indigo-6); + margin-inline-start: -100%; + margin-inline-end: -100%; + } + + &__label { + font-size: 14px; + font-weight: 600; + line-height: 17px; + } + } + } +} + +.annual-report-modal { + max-width: 480px; + background: var(--indigo-1); + border-radius: 16px; + display: flex; + flex-direction: column; + overflow-y: auto; + + .loading-indicator .circular-progress { + color: var(--lime); + } + + @media screen and (max-width: $no-columns-breakpoint) { + border-bottom: 0; + border-radius: 16px 16px 0 0; + } +} + +.notification-group--annual-report { + .notification-group__icon { + color: var(--lime); + } + + .notification-group__main .link-button { + font-weight: 500; + color: var(--lime); + } +} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 2f385cd0a8..44f900bf68 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1691,7 +1691,8 @@ body > [data-popper-placement] { .status__wrapper-direct, .notification-ungrouped--direct, -.notification-group--direct { +.notification-group--direct, +.notification-group--annual-report { background: rgba($ui-highlight-color, 0.05); &:focus { @@ -2774,6 +2775,7 @@ a.account__display-name { flex: 0 1 auto; display: flex; flex-direction: column; + contain: inline-size layout paint style; @media screen and (min-width: $no-gap-breakpoint) { max-width: 600px; @@ -4047,6 +4049,7 @@ $ui-header-logo-wordmark-width: 99px; overflow: hidden; border: 1px solid var(--background-border-color); border-radius: 8px; + contain: inline-size layout paint style; &.bottomless { border-radius: 8px 8px 0 0; @@ -5801,7 +5804,8 @@ a.status-card { inset-inline-start: 0; inset-inline-end: 0; bottom: 0; - background: rgba($base-overlay-background, 0.7); + opacity: 0.9; + background: $base-overlay-background; transition: background 0.5s; } @@ -5828,6 +5832,7 @@ a.status-card { pointer-events: auto; user-select: text; display: flex; + max-width: 100vw; @media screen and (width <= $mobile-breakpoint) { margin-top: auto; @@ -10823,21 +10828,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 { @@ -11132,19 +11133,21 @@ noscript { } .content-warning { + display: block; box-sizing: border-box; background: rgba($ui-highlight-color, 0.05); color: $secondary-text-color; - border-top: 1px solid; - border-bottom: 1px solid; - border-color: rgba($ui-highlight-color, 0.15); + border: 1px solid rgba($ui-highlight-color, 0.15); + border-radius: 8px; padding: 8px (5px + 8px); position: relative; font-size: 15px; line-height: 22px; + cursor: pointer; p { margin-bottom: 8px; + font-weight: 500; } .link-button { @@ -11153,31 +11156,16 @@ noscript { font-weight: 500; } - &::before, - &::after { - content: ''; - display: block; - position: absolute; - height: 100%; - background: url('~images/warning-stripes.svg') repeat-y; - width: 5px; - top: 0; - } + &--filter { + color: $darker-text-color; - &::before { - border-start-start-radius: 4px; - border-end-start-radius: 4px; - inset-inline-start: 0; - } + p { + font-weight: normal; + } - &::after { - border-start-end-radius: 4px; - border-end-end-radius: 4px; - inset-inline-end: 0; - } - - &--filter::before, - &--filter::after { - background-image: url('~images/filter-stripes.svg'); + .filter-name { + font-weight: 500; + color: $secondary-text-color; + } } } diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 957a283522..641fb19a57 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: ''; diff --git a/app/javascript/styles/mastodon/rich_text.scss b/app/javascript/styles/mastodon/rich_text.scss index c57db26e03..0c9237caae 100644 --- a/app/javascript/styles/mastodon/rich_text.scss +++ b/app/javascript/styles/mastodon/rich_text.scss @@ -2,9 +2,29 @@ .e-content, .edit-indicator__content, .reply-indicator__content { + code { + background: var(--rich-text-container-color); + padding: 4px; + border-radius: 4px; + color: var(--rich-text-text-color); + font-size: 0.85em; + } + + pre { + background: var(--rich-text-container-color); + padding: 8px; + border-radius: 4px; + color: var(--rich-text-text-color); + + code { + padding: 0; + background: transparent; + } + } + pre, blockquote { - margin-bottom: 20px; + margin-bottom: 22px; white-space: pre-wrap; unicode-bidi: plaintext; @@ -14,19 +34,45 @@ } blockquote { - padding-inline-start: 10px; - border-inline-start: 3px solid $darker-text-color; - color: $darker-text-color; + padding-inline-start: 32px; + color: var(--rich-text-text-color); white-space: normal; + position: relative; - p:last-child { + &::before { + display: block; + content: ''; + width: 24px; + height: 20px; + mask-image: url('~images/quote.svg'); + background-color: var(--rich-text-decorations-color); + position: absolute; + inset-inline-start: 0; + top: 0; + } + + blockquote { + margin-top: 4px; + border-inline-start: 3px solid var(--rich-text-decorations-color); + padding-inline-start: 16px; + + &::before { + display: none; + } + } + + p:last-of-type { margin-bottom: 0; } } & > ul, & > ol { - margin-bottom: 20px; + margin-bottom: 22px; + + &:last-child { + margin-bottom: 0; + } } b, @@ -41,7 +87,15 @@ ul, ol { - margin-inline-start: 2em; + padding-inline-start: 24px; + + li { + padding-inline-start: 8px; + + &::marker { + text-align: end; + } + } p { margin: 0; @@ -49,7 +103,11 @@ } ul { - list-style-type: disc; + list-style-type: '•'; + + li::marker { + text-align: start; + } } ol { diff --git a/app/javascript/styles/mastodon/rtl.scss b/app/javascript/styles/mastodon/rtl.scss index e4e299ff82..0a05ce7c62 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/variables.scss b/app/javascript/styles/mastodon/variables.scss index 3f2d59217e..517de48cb0 100644 --- a/app/javascript/styles/mastodon/variables.scss +++ b/app/javascript/styles/mastodon/variables.scss @@ -116,4 +116,7 @@ $font-monospace: 'mastodon-font-monospace' !default; --error-background-color: #{darken($error-red, 16%)}; --error-active-background-color: #{darken($error-red, 12%)}; --on-error-color: #fff; + --rich-text-container-color: rgba(87, 24, 60, 100%); + --rich-text-text-color: rgba(255, 175, 212, 100%); + --rich-text-decorations-color: rgba(128, 58, 95, 100%); } diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 19245a2c3b..1042aa2322 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -20,9 +20,9 @@ class ActivityPub::Activity end class << self - def factory(json, account, **options) + def factory(json, account, **) @json = json - klass&.new(json, account, **options) + klass&.new(json, account, **) end private diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index cbc5b309b4..5988415219 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -53,6 +53,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity ApplicationRecord.transaction do @status = Status.create!(@params) attach_tags(@status) + attach_counts(@status) end resolve_thread(@status) @@ -166,6 +167,18 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end end + def attach_counts(status) + likes = @status_parser.favourites_count + shares = @status_parser.reblogs_count + return if likes.nil? && shares.nil? + + status.status_stat.tap do |status_stat| + status_stat.untrusted_reblogs_count = shares unless shares.nil? + status_stat.untrusted_favourites_count = likes unless likes.nil? + status_stat.save if status_stat.changed? + end + end + def process_tags return if @object['tag'].nil? diff --git a/app/lib/activitypub/parser/status_parser.rb b/app/lib/activitypub/parser/status_parser.rb index 025c46449d..994be69856 100644 --- a/app/lib/activitypub/parser/status_parser.rb +++ b/app/lib/activitypub/parser/status_parser.rb @@ -95,6 +95,14 @@ class ActivityPub::Parser::StatusParser lang.presence && NORMALIZED_LOCALE_NAMES.fetch(lang.downcase.to_sym, lang) end + def favourites_count + @object.dig(:likes, :totalItems) + end + + def reblogs_count + @object.dig(:shares, :totalItems) + end + private def raw_language_code diff --git a/app/lib/admin/system_check/database_schema_check.rb b/app/lib/admin/system_check/database_schema_check.rb index c2f01fd55b..a3ef0613ea 100644 --- a/app/lib/admin/system_check/database_schema_check.rb +++ b/app/lib/admin/system_check/database_schema_check.rb @@ -6,7 +6,7 @@ class Admin::SystemCheck::DatabaseSchemaCheck < Admin::SystemCheck::BaseCheck end def pass? - !ActiveRecord::Base.connection.migration_context.needs_migration? + !ActiveRecord::Base.connection_pool.migration_context.needs_migration? end def message diff --git a/app/lib/annual_report.rb b/app/lib/annual_report.rb index cf4297f2a4..275cc4b87d 100644 --- a/app/lib/annual_report.rb +++ b/app/lib/annual_report.rb @@ -17,11 +17,21 @@ class AnnualReport SCHEMA = 1 + def self.table_name_prefix + 'annual_report_' + end + def initialize(account, year) @account = account @year = year end + def self.prepare(year) + SOURCES.each do |klass| + klass.prepare(year) + end + end + def generate return if GeneratedAnnualReport.exists?(account: @account, year: @year) diff --git a/app/lib/annual_report/commonly_interacted_with_accounts.rb b/app/lib/annual_report/commonly_interacted_with_accounts.rb index e7482f0d52..30ab671d8a 100644 --- a/app/lib/annual_report/commonly_interacted_with_accounts.rb +++ b/app/lib/annual_report/commonly_interacted_with_accounts.rb @@ -7,7 +7,7 @@ class AnnualReport::CommonlyInteractedWithAccounts < AnnualReport::Source { commonly_interacted_with_accounts: commonly_interacted_with_accounts.map do |(account_id, count)| { - account_id: account_id, + account_id: account_id.to_s, count: count, } end, diff --git a/app/lib/annual_report/most_reblogged_accounts.rb b/app/lib/annual_report/most_reblogged_accounts.rb index 39ed3868ea..cfc4022ca7 100644 --- a/app/lib/annual_report/most_reblogged_accounts.rb +++ b/app/lib/annual_report/most_reblogged_accounts.rb @@ -7,7 +7,7 @@ class AnnualReport::MostRebloggedAccounts < AnnualReport::Source { most_reblogged_accounts: most_reblogged_accounts.map do |(account_id, count)| { - account_id: account_id, + account_id: account_id.to_s, count: count, } end, diff --git a/app/lib/annual_report/percentiles.rb b/app/lib/annual_report/percentiles.rb index 0251cb66ad..2b0305c415 100644 --- a/app/lib/annual_report/percentiles.rb +++ b/app/lib/annual_report/percentiles.rb @@ -1,62 +1,37 @@ # frozen_string_literal: true class AnnualReport::Percentiles < AnnualReport::Source + def self.prepare(year) + AnnualReport::StatusesPerAccountCount.connection.exec_query(<<~SQL.squish, nil, [year, Mastodon::Snowflake.id_at(DateTime.new(year).beginning_of_year), Mastodon::Snowflake.id_at(DateTime.new(year).end_of_year)]) + INSERT INTO annual_report_statuses_per_account_counts (year, account_id, statuses_count) + SELECT $1, account_id, count(*) + FROM statuses + WHERE id BETWEEN $2 AND $3 + AND (local OR uri IS NULL) + GROUP BY account_id + ON CONFLICT (year, account_id) DO NOTHING + SQL + end + def generate { percentiles: { - followers: (total_with_fewer_followers / (total_with_any_followers + 1.0)) * 100, - statuses: (total_with_fewer_statuses / (total_with_any_statuses + 1.0)) * 100, + statuses: 100.0 - ((total_with_fewer_statuses / (total_with_any_statuses + 1.0)) * 100), }, } end private - def followers_gained - @followers_gained ||= @account.passive_relationships.where("date_part('year', follows.created_at) = ?", @year).count - end - def statuses_created @statuses_created ||= report_statuses.count end - def total_with_fewer_followers - @total_with_fewer_followers ||= Follow.find_by_sql([<<~SQL.squish, { year: @year, comparison: followers_gained }]).first.total - WITH tmp0 AS ( - SELECT follows.target_account_id - FROM follows - INNER JOIN accounts ON accounts.id = follows.target_account_id - WHERE date_part('year', follows.created_at) = :year - AND accounts.domain IS NULL - GROUP BY follows.target_account_id - HAVING COUNT(*) < :comparison - ) - SELECT count(*) AS total - FROM tmp0 - SQL - end - def total_with_fewer_statuses - @total_with_fewer_statuses ||= Status.find_by_sql([<<~SQL.squish, { comparison: statuses_created, min_id: year_as_snowflake_range.first, max_id: year_as_snowflake_range.last }]).first.total - WITH tmp0 AS ( - SELECT statuses.account_id - FROM statuses - INNER JOIN accounts ON accounts.id = statuses.account_id - WHERE statuses.id BETWEEN :min_id AND :max_id - AND accounts.domain IS NULL - GROUP BY statuses.account_id - HAVING count(*) < :comparison - ) - SELECT count(*) AS total - FROM tmp0 - SQL - end - - def total_with_any_followers - @total_with_any_followers ||= Follow.where("date_part('year', follows.created_at) = ?", @year).joins(:target_account).merge(Account.local).count('distinct follows.target_account_id') + @total_with_fewer_statuses ||= AnnualReport::StatusesPerAccountCount.where(year: year).where(statuses_count: ...statuses_created).count end def total_with_any_statuses - @total_with_any_statuses ||= Status.where(id: year_as_snowflake_range).joins(:account).merge(Account.local).count('distinct statuses.account_id') + @total_with_any_statuses ||= AnnualReport::StatusesPerAccountCount.where(year: year).count end end diff --git a/app/lib/annual_report/source.rb b/app/lib/annual_report/source.rb index cb9f7b16e3..86528731f5 100644 --- a/app/lib/annual_report/source.rb +++ b/app/lib/annual_report/source.rb @@ -8,6 +8,14 @@ class AnnualReport::Source @year = year end + def self.prepare(_year) + # Use this method if any pre-calculations must be made before individual annual reports are generated + end + + def generate + raise NotImplementedError + end + protected def report_statuses diff --git a/app/lib/annual_report/top_statuses.rb b/app/lib/annual_report/top_statuses.rb index c5abeaa58d..74b129595a 100644 --- a/app/lib/annual_report/top_statuses.rb +++ b/app/lib/annual_report/top_statuses.rb @@ -8,9 +8,9 @@ class AnnualReport::TopStatuses < AnnualReport::Source { top_statuses: { - by_reblogs: top_reblogs, - by_favourites: top_favourites, - by_replies: top_replies, + by_reblogs: top_reblogs&.to_s, + by_favourites: top_favourites&.to_s, + by_replies: top_replies&.to_s, }, } end diff --git a/app/lib/attachment_batch.rb b/app/lib/attachment_batch.rb index 32ccb0b13c..374abfac49 100644 --- a/app/lib/attachment_batch.rb +++ b/app/lib/attachment_batch.rb @@ -77,10 +77,22 @@ class AttachmentBatch when :fog logger.debug { "Deleting #{attachment.path(style)}" } + retries = 0 begin attachment.send(:directory).files.new(key: attachment.path(style)).destroy - rescue Fog::Storage::OpenStack::NotFound - # Ignore failure to delete a file that has already been deleted + rescue Fog::OpenStack::Storage::NotFound + logger.debug "Will ignore because file is not found #{attachment.path(style)}" + rescue => e + retries += 1 + + if retries < MAX_RETRY + logger.debug "Retry #{retries}/#{MAX_RETRY} after #{e.message}" + sleep 2**retries + retry + else + logger.error "Batch deletion from fog failed after #{e.message}" + raise e + end end when :azure logger.debug { "Deleting #{attachment.path(style)}" } diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb index a6901a6757..2e6c43be8f 100644 --- a/app/lib/content_security_policy.rb +++ b/app/lib/content_security_policy.rb @@ -40,7 +40,7 @@ class ContentSecurityPolicy 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 @@ class ContentSecurityPolicy 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/rss/element.rb b/app/lib/rss/element.rb index 7142fa0396..073fad1234 100644 --- a/app/lib/rss/element.rb +++ b/app/lib/rss/element.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class RSS::Element - def self.with(*args, &block) - new(*args).tap(&block).to_element + def self.with(*, &block) + new(*).tap(&block).to_element end def create_element(name, content = nil) diff --git a/app/lib/suspicious_sign_in_detector.rb b/app/lib/suspicious_sign_in_detector.rb index 74f49aa558..60e5fdad4f 100644 --- a/app/lib/suspicious_sign_in_detector.rb +++ b/app/lib/suspicious_sign_in_detector.rb @@ -19,7 +19,7 @@ class SuspiciousSignInDetector end def previously_seen_ip?(request) - @user.ips.exists?(['ip <<= ?', masked_ip(request)]) + @user.ips.contained_by(masked_ip(request)).exists? end def freshly_signed_up? diff --git a/app/lib/text_formatter.rb b/app/lib/text_formatter.rb index 2b3febc219..5e8e73a217 100644 --- a/app/lib/text_formatter.rb +++ b/app/lib/text_formatter.rb @@ -33,17 +33,24 @@ class TextFormatter def to_s return ''.html_safe if text.blank? - html = rewrite do |entity| - if entity[:url] - link_to_url(entity) - elsif entity[:hashtag] - link_to_hashtag(entity) - elsif entity[:screen_name] - link_to_mention(entity) + html = nil + MastodonOTELTracer.in_span('TextFormatter#to_s extract_and_rewrite') do + html = rewrite do |entity| + if entity[:url] + link_to_url(entity) + elsif entity[:hashtag] + link_to_hashtag(entity) + elsif entity[:screen_name] + link_to_mention(entity) + end end end - html = simple_format(html, {}, sanitize: false).delete("\n") if multiline? + if multiline? + MastodonOTELTracer.in_span('TextFormatter#to_s simple_format') do + html = simple_format(html, {}, sanitize: false).delete("\n") + end + end html.html_safe # rubocop:disable Rails/OutputSafety end @@ -93,48 +100,54 @@ class TextFormatter end def link_to_url(entity) - TextFormatter.shortened_link(entity[:url], rel_me: with_rel_me?) + MastodonOTELTracer.in_span('TextFormatter#link_to_url') do + TextFormatter.shortened_link(entity[:url], rel_me: with_rel_me?) + end end def link_to_hashtag(entity) - hashtag = entity[:hashtag] - url = tag_url(hashtag) + MastodonOTELTracer.in_span('TextFormatter#link_to_hashtag') do + hashtag = entity[:hashtag] + url = tag_url(hashtag) - <<~HTML.squish - - HTML + <<~HTML.squish + + HTML + end end def link_to_mention(entity) - username, domain = entity[:screen_name].split('@') - domain = nil if local_domain?(domain) - account = nil + MastodonOTELTracer.in_span('TextFormatter#link_to_mention') do + username, domain = entity[:screen_name].split('@') + domain = nil if local_domain?(domain) + account = nil - if preloaded_accounts? - same_username_hits = 0 + if preloaded_accounts? + same_username_hits = 0 - preloaded_accounts.each do |other_account| - same_username = other_account.username.casecmp(username).zero? - same_domain = other_account.domain.nil? ? domain.nil? : other_account.domain.casecmp(domain)&.zero? + preloaded_accounts.each do |other_account| + same_username = other_account.username.casecmp(username).zero? + same_domain = other_account.domain.nil? ? domain.nil? : other_account.domain.casecmp(domain)&.zero? - if same_username && !same_domain - same_username_hits += 1 - elsif same_username && same_domain - account = other_account + if same_username && !same_domain + same_username_hits += 1 + elsif same_username && same_domain + account = other_account + end end + else + account = entity_cache.mention(username, domain) end - else - account = entity_cache.mention(username, domain) + + return "@#{h(entity[:screen_name])}" if account.nil? + + url = ActivityPub::TagManager.instance.url_for(account) + display_username = same_username_hits&.positive? || with_domains? ? account.pretty_acct : account.username + + <<~HTML.squish + @#{h(display_username)} + HTML end - - return "@#{h(entity[:screen_name])}" if account.nil? - - url = ActivityPub::TagManager.instance.url_for(account) - display_username = same_username_hits&.positive? || with_domains? ? account.pretty_acct : account.username - - <<~HTML.squish - @#{h(display_username)} - HTML end def entity_cache diff --git a/app/lib/translation_service.rb b/app/lib/translation_service.rb index bfe5de44f8..ee268d7a7c 100644 --- a/app/lib/translation_service.rb +++ b/app/lib/translation_service.rb @@ -8,17 +8,27 @@ class TranslationService class UnexpectedResponseError < Error; end def self.configured - if ENV['DEEPL_API_KEY'].present? - TranslationService::DeepL.new(ENV.fetch('DEEPL_PLAN', 'free'), ENV['DEEPL_API_KEY']) - elsif ENV['LIBRE_TRANSLATE_ENDPOINT'].present? - TranslationService::LibreTranslate.new(ENV['LIBRE_TRANSLATE_ENDPOINT'], ENV['LIBRE_TRANSLATE_API_KEY']) + if configuration.deepl[:api_key].present? + TranslationService::DeepL.new( + configuration.deepl[:plan], + configuration.deepl[:api_key] + ) + elsif configuration.libre_translate[:endpoint].present? + TranslationService::LibreTranslate.new( + configuration.libre_translate[:endpoint], + configuration.libre_translate[:api_key] + ) else raise NotConfiguredError end end def self.configured? - ENV['DEEPL_API_KEY'].present? || ENV['LIBRE_TRANSLATE_ENDPOINT'].present? + configuration.deepl[:api_key].present? || configuration.libre_translate[:endpoint].present? + end + + def self.configuration + Rails.configuration.x.translation end def languages diff --git a/app/lib/translation_service/deepl.rb b/app/lib/translation_service/deepl.rb index 925a1cf172..7761dbe626 100644 --- a/app/lib/translation_service/deepl.rb +++ b/app/lib/translation_service/deepl.rb @@ -42,8 +42,8 @@ class TranslationService::DeepL < TranslationService subtags.join('-') end - def request(verb, path, **options) - req = Request.new(verb, "#{base_url}#{path}", **options) + def request(verb, path, **) + req = Request.new(verb, "#{base_url}#{path}", **) req.add_headers(Authorization: "DeepL-Auth-Key #{@api_key}") req.perform do |res| case res.code diff --git a/app/lib/translation_service/libre_translate.rb b/app/lib/translation_service/libre_translate.rb index de43d7c88c..0df8590f87 100644 --- a/app/lib/translation_service/libre_translate.rb +++ b/app/lib/translation_service/libre_translate.rb @@ -27,8 +27,8 @@ class TranslationService::LibreTranslate < TranslationService private - def request(verb, path, **options) - req = Request.new(verb, "#{@base_url}#{path}", allow_local: true, **options) + def request(verb, path, **) + req = Request.new(verb, "#{@base_url}#{path}", allow_local: true, **) req.add_headers('Content-Type': 'application/json') req.perform do |res| case res.code diff --git a/app/models/account.rb b/app/models/account.rb index 735958db77..6f2636b2b6 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -65,6 +65,8 @@ class Account < ApplicationRecord ) BACKGROUND_REFRESH_INTERVAL = 1.week.freeze + REFRESH_DEADLINE = 6.hours + STALE_THRESHOLD = 1.day DEFAULT_FIELDS_SIZE = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i INSTANCE_ACTOR_ID = -99 @@ -229,13 +231,13 @@ class Account < ApplicationRecord end def possibly_stale? - last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago + last_webfingered_at.nil? || last_webfingered_at <= STALE_THRESHOLD.ago end def schedule_refresh_if_stale! return unless last_webfingered_at.present? && last_webfingered_at <= BACKGROUND_REFRESH_INTERVAL.ago - AccountRefreshWorker.perform_in(rand(6.hours.to_i), id) + AccountRefreshWorker.perform_in(rand(REFRESH_DEADLINE), id) end def refresh! diff --git a/app/models/account_statuses_cleanup_policy.rb b/app/models/account_statuses_cleanup_policy.rb index 6e998e2dca..ef41bb3ee3 100644 --- a/app/models/account_statuses_cleanup_policy.rb +++ b/app/models/account_statuses_cleanup_policy.rb @@ -130,7 +130,7 @@ class AccountStatusesCleanupPolicy < ApplicationRecord end def without_direct_scope - Status.where.not(visibility: :direct) + Status.not_direct_visibility end def old_enough_scope(max_id = nil) diff --git a/app/models/admin/status_filter.rb b/app/models/admin/status_filter.rb index 8d20e4f6ab..fd4d0ef59d 100644 --- a/app/models/admin/status_filter.rb +++ b/app/models/admin/status_filter.rb @@ -32,7 +32,7 @@ class Admin::StatusFilter def scope_for(key, _value) case key.to_s when 'media' - Status.joins(:media_attachments).merge(@account.media_attachments).group(:id).reorder('statuses.id desc') + Status.joins(:media_attachments).merge(@account.media_attachments).group(:id).recent else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end diff --git a/app/models/annual_report/statuses_per_account_count.rb b/app/models/annual_report/statuses_per_account_count.rb new file mode 100644 index 0000000000..05a2f53c9d --- /dev/null +++ b/app/models/annual_report/statuses_per_account_count.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: annual_report_statuses_per_account_counts +# +# id :bigint(8) not null, primary key +# year :integer not null +# account_id :bigint(8) not null +# statuses_count :bigint(8) not null +# + +class AnnualReport::StatusesPerAccountCount < ApplicationRecord + # This table facilitates percentile calculations +end diff --git a/app/models/concerns/inet_container.rb b/app/models/concerns/inet_container.rb new file mode 100644 index 0000000000..da03bcc5d7 --- /dev/null +++ b/app/models/concerns/inet_container.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module InetContainer + extend ActiveSupport::Concern + + included do + scope :containing, ->(value) { where('ip >>= ?', value) } + scope :contained_by, ->(value) { where('ip <<= ?', value) } + end +end diff --git a/app/models/concerns/ranked_trend.rb b/app/models/concerns/ranked_trend.rb index add36afb0c..e707fe0bad 100644 --- a/app/models/concerns/ranked_trend.rb +++ b/app/models/concerns/ranked_trend.rb @@ -9,6 +9,10 @@ module RankedTrend end class_methods do + def locales + distinct.pluck(:language) + end + def recalculate_ordered_rank connection .exec_update(<<~SQL.squish) diff --git a/app/models/concerns/status/safe_reblog_insert.rb b/app/models/concerns/status/safe_reblog_insert.rb index 60ddb78e52..48d585ea18 100644 --- a/app/models/concerns/status/safe_reblog_insert.rb +++ b/app/models/concerns/status/safe_reblog_insert.rb @@ -15,7 +15,9 @@ module Status::SafeReblogInsert # # The code is kept similar to ActiveRecord::Persistence code and calls it # directly when we are not handling a reblog. - def _insert_record(values, returning) + # + # https://github.com/rails/rails/blob/v7.2.1.1/activerecord/lib/active_record/persistence.rb#L238-L263 + def _insert_record(connection, values, returning) return super unless values.is_a?(Hash) && values['reblog_of_id']&.value.present? primary_key = self.primary_key @@ -30,14 +32,19 @@ module Status::SafeReblogInsert # The following line departs from stock ActiveRecord # Original code was: - # im.insert(values.transform_keys { |name| arel_table[name] }) + # im = Arel::InsertManager.new(arel_table) # Instead, we use a custom builder when a reblog is happening: im = _compile_reblog_insert(values) - connection.insert(im, "#{self} Create", primary_key || false, primary_key_value, returning: returning).tap do |result| - # Since we are using SELECT instead of VALUES, a non-error `nil` return is possible. - # For our purposes, it's equivalent to a foreign key constraint violation - raise ActiveRecord::InvalidForeignKey, "(reblog_of_id)=(#{values['reblog_of_id'].value}) is not present in table \"statuses\"" if result.nil? + with_connection do |_c| + connection.insert( + im, "#{self} Create", primary_key || false, primary_key_value, + returning: returning + ).tap do |result| + # Since we are using SELECT instead of VALUES, a non-error `nil` return is possible. + # For our purposes, it's equivalent to a foreign key constraint violation + raise ActiveRecord::InvalidForeignKey, "(reblog_of_id)=(#{values['reblog_of_id'].value}) is not present in table \"statuses\"" if result.nil? + end end end diff --git a/app/models/concerns/status/snapshot_concern.rb b/app/models/concerns/status/snapshot_concern.rb index 08d92f55d1..7199d2242e 100644 --- a/app/models/concerns/status/snapshot_concern.rb +++ b/app/models/concerns/status/snapshot_concern.rb @@ -30,7 +30,7 @@ module Status::SnapshotConcern ) end - def snapshot!(**options) - build_snapshot(**options).save! + def snapshot!(**) + build_snapshot(**).save! end end diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb index f3a86eae8f..583d2e6c1b 100644 --- a/app/models/email_domain_block.rb +++ b/app/models/email_domain_block.rb @@ -28,6 +28,8 @@ class EmailDomainBlock < ApplicationRecord validates :domain, presence: true, uniqueness: true, domain: true + scope :parents, -> { where(parent_id: nil) } + # Used for adding multiple blocks at once attr_accessor :other_domains diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb index a4e7b7cf6f..529056f9c6 100644 --- a/app/models/featured_tag.rb +++ b/app/models/featured_tag.rb @@ -44,8 +44,16 @@ class FeaturedTag < ApplicationRecord update(statuses_count: statuses_count + 1, last_status_at: timestamp) end - def decrement(deleted_status_id) - update(statuses_count: [0, statuses_count - 1].max, last_status_at: visible_tagged_account_statuses.where.not(id: deleted_status_id).pick(:created_at)) + def decrement(deleted_status) + if statuses_count <= 1 + update(statuses_count: 0, last_status_at: nil) + elsif last_status_at > deleted_status.created_at + update(statuses_count: statuses_count - 1) + else + # Fetching the latest status creation time can be expensive, so only perform it + # if we know we are deleting the latest status using this tag + update(statuses_count: statuses_count - 1, last_status_at: visible_tagged_account_statuses.where(id: ...deleted_status.id).pick(:created_at)) + end end private diff --git a/app/models/follow_recommendation_filter.rb b/app/models/follow_recommendation_filter.rb index 62a02eba5a..f3b0fd319b 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 @@ class FollowRecommendationFilter 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/ip_block.rb b/app/models/ip_block.rb index d6242efbf7..416ae38382 100644 --- a/app/models/ip_block.rb +++ b/app/models/ip_block.rb @@ -17,6 +17,7 @@ class IpBlock < ApplicationRecord CACHE_KEY = 'blocked_ips' include Expireable + include InetContainer include Paginable enum :severity, { @@ -36,9 +37,14 @@ class IpBlock < ApplicationRecord class << self def blocked?(remote_ip) - blocked_ips_map = Rails.cache.fetch(CACHE_KEY) { FastIpMap.new(IpBlock.where(severity: :no_access).pluck(:ip)) } blocked_ips_map.include?(remote_ip) end + + private + + def blocked_ips_map + Rails.cache.fetch(CACHE_KEY) { FastIpMap.new(severity_no_access.pluck(:ip)) } + end end private diff --git a/app/models/link_feed.rb b/app/models/link_feed.rb index 32efb331b6..29ea430cc0 100644 --- a/app/models/link_feed.rb +++ b/app/models/link_feed.rb @@ -19,6 +19,8 @@ class LinkFeed < PublicFeed scope.merge!(discoverable) scope.merge!(attached_to_preview_card) + scope.merge!(account_filters_scope) if account? + scope.merge!(language_scope) if account&.chosen_languages.present? scope.to_a_paginated_by_id(limit, max_id: max_id, since_id: since_id, min_id: min_id) end diff --git a/app/models/notification.rb b/app/models/notification.rb index 6b4a76c794..efae8f4f47 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -71,6 +71,9 @@ class Notification < ApplicationRecord moderation_warning: { filterable: false, }.freeze, + annual_report: { + filterable: false, + }.freeze, 'admin.sign_up': { filterable: false, }.freeze, @@ -107,6 +110,7 @@ class Notification < ApplicationRecord belongs_to :report, inverse_of: false belongs_to :account_relationship_severance_event, inverse_of: false belongs_to :account_warning, inverse_of: false + belongs_to :generated_annual_report, inverse_of: false end validates :type, inclusion: { in: TYPES } @@ -321,7 +325,7 @@ class Notification < ApplicationRecord self.from_account_id = activity&.status&.account_id when 'Account' self.from_account_id = activity&.id - when 'AccountRelationshipSeveranceEvent', 'AccountWarning' + when 'AccountRelationshipSeveranceEvent', 'AccountWarning', 'GeneratedAnnualReport' # These do not really have an originating account, but this is mandatory # in the data model, and the recipient's account will by definition # always exist diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb index b6aa4d309c..9331b9406f 100644 --- a/app/models/notification_group.rb +++ b/app/models/notification_group.rb @@ -51,6 +51,7 @@ class NotificationGroup < ActiveModelSerializers::Model :report, :account_relationship_severance_event, :account_warning, + :generated_annual_report, to: :notification, prefix: false class << self diff --git a/app/models/scheduled_status.rb b/app/models/scheduled_status.rb index 27f0cbd280..cb49e90705 100644 --- a/app/models/scheduled_status.rb +++ b/app/models/scheduled_status.rb @@ -15,6 +15,7 @@ class ScheduledStatus < ApplicationRecord TOTAL_LIMIT = 300 DAILY_LIMIT = 25 + MINIMUM_OFFSET = 5.minutes.freeze belongs_to :account, inverse_of: :scheduled_statuses has_many :media_attachments, inverse_of: :scheduled_status, dependent: :nullify @@ -26,7 +27,7 @@ class ScheduledStatus < ApplicationRecord private def validate_future_date - errors.add(:scheduled_at, I18n.t('scheduled_statuses.too_soon')) if scheduled_at.present? && scheduled_at <= Time.now.utc + PostStatusService::MIN_SCHEDULE_OFFSET + errors.add(:scheduled_at, I18n.t('scheduled_statuses.too_soon')) if scheduled_at.present? && scheduled_at <= Time.now.utc + MINIMUM_OFFSET end def validate_total_limit diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb index 8b8e533d30..d99ecf8adb 100644 --- a/app/models/session_activation.rb +++ b/app/models/session_activation.rb @@ -30,13 +30,15 @@ class SessionActivation < ApplicationRecord DEFAULT_SCOPES = %w(read write follow).freeze + scope :latest, -> { order(id: :desc) } + class << self def active?(id) id && exists?(session_id: id) end - def activate(**options) - activation = create!(**options) + def activate(**) + activation = create!(**) purge_old activation end @@ -48,7 +50,7 @@ class SessionActivation < ApplicationRecord end def purge_old - order('created_at desc').offset(Rails.configuration.x.max_session_activations).destroy_all + latest.offset(Rails.configuration.x.max_session_activations).destroy_all end def exclusive(id) diff --git a/app/models/status.rb b/app/models/status.rb index b31ba628b0..61a5fb946c 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -131,6 +131,7 @@ class Status < ApplicationRecord } scope :distributable_visibility, -> { where(visibility: %i(public unlisted)) } scope :list_eligible_visibility, -> { where(visibility: %i(public unlisted private)) } + scope :not_direct_visibility, -> { where.not(visibility: :direct) } scope :not_local_only, -> { where(local_only: [false, nil]) } @@ -321,12 +322,34 @@ class Status < ApplicationRecord status_stat&.favourites_count || 0 end + # Reblogs count received from an external instance + def untrusted_reblogs_count + status_stat&.untrusted_reblogs_count unless local? + end + + # Favourites count received from an external instance + def untrusted_favourites_count + status_stat&.untrusted_favourites_count unless local? + end + def increment_count!(key) - update_status_stat!(key => public_send(key) + 1) + if key == :favourites_count && !untrusted_favourites_count.nil? + update_status_stat!(favourites_count: favourites_count + 1, untrusted_favourites_count: untrusted_favourites_count + 1) + elsif key == :reblogs_count && !untrusted_reblogs_count.nil? + update_status_stat!(reblogs_count: reblogs_count + 1, untrusted_reblogs_count: untrusted_reblogs_count + 1) + else + update_status_stat!(key => public_send(key) + 1) + end end def decrement_count!(key) - update_status_stat!(key => [public_send(key) - 1, 0].max) + if key == :favourites_count && !untrusted_favourites_count.nil? + update_status_stat!(favourites_count: [favourites_count - 1, 0].max, untrusted_favourites_count: [untrusted_favourites_count - 1, 0].max) + elsif key == :reblogs_count && !untrusted_reblogs_count.nil? + update_status_stat!(reblogs_count: [reblogs_count - 1, 0].max, untrusted_reblogs_count: [untrusted_reblogs_count - 1, 0].max) + else + update_status_stat!(key => [public_send(key) - 1, 0].max) + end end def trendable? diff --git a/app/models/status_pin.rb b/app/models/status_pin.rb index dae4a5b4e6..83711dde42 100644 --- a/app/models/status_pin.rb +++ b/app/models/status_pin.rb @@ -17,11 +17,17 @@ class StatusPin < ApplicationRecord validates_with StatusPinValidator - after_destroy :invalidate_cleanup_info + after_destroy :invalidate_cleanup_info, if: %i(account_matches_status_account? account_local?) + + delegate :local?, to: :account, prefix: true + + private def invalidate_cleanup_info - return unless status&.account_id == account_id && account.local? - account.statuses_cleanup_policy&.invalidate_last_inspected(status, :unpin) end + + def account_matches_status_account? + status&.account_id == account_id + end end diff --git a/app/models/status_stat.rb b/app/models/status_stat.rb index 47aa144777..14a02071a7 100644 --- a/app/models/status_stat.rb +++ b/app/models/status_stat.rb @@ -4,18 +4,24 @@ # # Table name: status_stats # -# id :bigint(8) not null, primary key -# status_id :bigint(8) not null -# replies_count :bigint(8) default(0), not null -# reblogs_count :bigint(8) default(0), not null -# favourites_count :bigint(8) default(0), not null -# created_at :datetime not null -# updated_at :datetime not null +# id :bigint(8) not null, primary key +# status_id :bigint(8) not null +# replies_count :bigint(8) default(0), not null +# reblogs_count :bigint(8) default(0), not null +# favourites_count :bigint(8) default(0), not null +# created_at :datetime not null +# updated_at :datetime not null +# untrusted_favourites_count :bigint(8) +# untrusted_reblogs_count :bigint(8) # class StatusStat < ApplicationRecord belongs_to :status, inverse_of: :status_stat + before_validation :clamp_untrusted_counts + + MAX_UNTRUSTED_COUNT = 100_000_000 + def replies_count [attributes['replies_count'], 0].max end @@ -27,4 +33,11 @@ class StatusStat < ApplicationRecord def favourites_count [attributes['favourites_count'], 0].max end + + private + + def clamp_untrusted_counts + self.untrusted_favourites_count = untrusted_favourites_count.to_i.clamp(0, MAX_UNTRUSTED_COUNT) if untrusted_favourites_count.present? + self.untrusted_reblogs_count = untrusted_reblogs_count.to_i.clamp(0, MAX_UNTRUSTED_COUNT) if untrusted_reblogs_count.present? + end end diff --git a/app/models/tombstone.rb b/app/models/tombstone.rb index bf666c43ac..92eddfc626 100644 --- a/app/models/tombstone.rb +++ b/app/models/tombstone.rb @@ -14,4 +14,6 @@ class Tombstone < ApplicationRecord belongs_to :account + + validates :uri, presence: true end diff --git a/app/models/trends/links.rb b/app/models/trends/links.rb index 0650c4109d..9d721d25f8 100644 --- a/app/models/trends/links.rb +++ b/app/models/trends/links.rb @@ -85,7 +85,7 @@ class Trends::Links < Trends::Base end def request_review - PreviewCardTrend.pluck('distinct language').flat_map do |language| + PreviewCardTrend.locales.flat_map do |language| score_at_threshold = PreviewCardTrend.where(language: language).allowed.by_rank.ranked_below(options[:review_threshold]).first&.score || 0 preview_card_trends = PreviewCardTrend.where(language: language).not_allowed.joins(:preview_card) diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb index bbffc72fe6..0c1135ceb5 100644 --- a/app/models/trends/statuses.rb +++ b/app/models/trends/statuses.rb @@ -78,7 +78,7 @@ class Trends::Statuses < Trends::Base end def request_review - StatusTrend.pluck('distinct language').flat_map do |language| + StatusTrend.locales.flat_map do |language| score_at_threshold = StatusTrend.where(language: language, allowed: true).by_rank.ranked_below(options[:review_threshold]).first&.score || 0 status_trends = StatusTrend.where(language: language, allowed: false).joins(:status).includes(status: :account) diff --git a/app/models/user.rb b/app/models/user.rb index e685ce65d3..00596e3439 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -125,7 +125,7 @@ class User < ApplicationRecord scope :signed_in_recently, -> { where(current_sign_in_at: ACTIVE_DURATION.ago..) } scope :not_signed_in_recently, -> { where(current_sign_in_at: ...ACTIVE_DURATION.ago) } scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) } - scope :matches_ip, ->(value) { left_joins(:ips).where('user_ips.ip <<= ?', value).group('users.id') } + scope :matches_ip, ->(value) { left_joins(:ips).merge(IpBlock.contained_by(value)).group('users.id') } before_validation :sanitize_role before_create :set_approved @@ -340,7 +340,7 @@ class User < ApplicationRecord Doorkeeper::AccessGrant.by_resource_owner(self).update_all(revoked_at: Time.now.utc) Doorkeeper::AccessToken.by_resource_owner(self).in_batches do |batch| - batch.update_all(revoked_at: Time.now.utc) + batch.touch_all(:revoked_at) Web::PushSubscription.where(access_token_id: batch).delete_all # Revoke each access token for the Streaming API, since `update_all`` @@ -405,8 +405,8 @@ class User < ApplicationRecord @pending_devise_notifications ||= [] end - def render_and_send_devise_message(notification, *args, **kwargs) - devise_mailer.send(notification, self, *args, **kwargs).deliver_later + def render_and_send_devise_message(notification, *, **) + devise_mailer.send(notification, self, *, **).deliver_later end def set_approved @@ -444,7 +444,7 @@ class User < ApplicationRecord end def sign_up_from_ip_requires_approval? - sign_up_ip.present? && IpBlock.severity_sign_up_requires_approval.exists?(['ip >>= ?', sign_up_ip.to_s]) + sign_up_ip.present? && IpBlock.severity_sign_up_requires_approval.containing(sign_up_ip.to_s).exists? end def sign_up_email_requires_approval? diff --git a/app/models/user_ip.rb b/app/models/user_ip.rb index a6da2c0740..25aa81ccd4 100644 --- a/app/models/user_ip.rb +++ b/app/models/user_ip.rb @@ -11,6 +11,7 @@ class UserIp < ApplicationRecord include DatabaseViewRecord + include InetContainer self.primary_key = :user_id diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index 9d30881bf3..656040d2ce 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -29,6 +29,8 @@ class Web::PushSubscription < ApplicationRecord delegate :locale, to: :associated_user + generates_token_for :unsubscribe, expires_in: Web::PushNotificationWorker::TTL + def pushable?(notification) policy_allows_notification?(notification) && alert_enabled_for_notification_type?(notification) end diff --git a/app/presenters/oauth_metadata_presenter.rb b/app/presenters/oauth_metadata_presenter.rb index 1e4d25165c..7d75e8498a 100644 --- a/app/presenters/oauth_metadata_presenter.rb +++ b/app/presenters/oauth_metadata_presenter.rb @@ -26,6 +26,10 @@ class OauthMetadataPresenter < ActiveModelSerializers::Model oauth_token_url end + def userinfo_endpoint + oauth_userinfo_url + end + # As the api_v1_apps route doesn't technically conform to the specification # for OAuth 2.0 Dynamic Client Registration defined in RFC 7591 we use a # non-standard property for now to indicate the mastodon specific registration diff --git a/app/serializers/oauth_metadata_serializer.rb b/app/serializers/oauth_metadata_serializer.rb index 2afb4208fb..9c5f7365a4 100644 --- a/app/serializers/oauth_metadata_serializer.rb +++ b/app/serializers/oauth_metadata_serializer.rb @@ -2,7 +2,7 @@ class OauthMetadataSerializer < ActiveModel::Serializer attributes :issuer, :authorization_endpoint, :token_endpoint, - :revocation_endpoint, :scopes_supported, + :revocation_endpoint, :userinfo_endpoint, :scopes_supported, :response_types_supported, :response_modes_supported, :grant_types_supported, :token_endpoint_auth_methods_supported, :code_challenge_methods_supported, diff --git a/app/serializers/oauth_userinfo_serializer.rb b/app/serializers/oauth_userinfo_serializer.rb new file mode 100644 index 0000000000..e2f37ae02e --- /dev/null +++ b/app/serializers/oauth_userinfo_serializer.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class OauthUserinfoSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :iss, :sub, :name, :preferred_username, :profile, :picture + + def iss + root_url + end + + def sub + ActivityPub::TagManager.instance.uri_for(object) + end + + def name + object.display_name + end + + def preferred_username + object.username + end + + def profile + ActivityPub::TagManager.instance.url_for(object) + end + + def picture + full_asset_url(object.avatar_original_url) + end +end diff --git a/app/serializers/rest/annual_report_event_serializer.rb b/app/serializers/rest/annual_report_event_serializer.rb new file mode 100644 index 0000000000..555a596357 --- /dev/null +++ b/app/serializers/rest/annual_report_event_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class REST::AnnualReportEventSerializer < ActiveModel::Serializer + attributes :year + + def year + object.year.to_s + end +end diff --git a/app/serializers/rest/notification_group_serializer.rb b/app/serializers/rest/notification_group_serializer.rb index 7842230b6a..0ca9386a7a 100644 --- a/app/serializers/rest/notification_group_serializer.rb +++ b/app/serializers/rest/notification_group_serializer.rb @@ -13,6 +13,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer belongs_to :account_relationship_severance_event, key: :event, if: :relationship_severance_event?, serializer: REST::AccountRelationshipSeveranceEventSerializer belongs_to :account_warning, key: :moderation_warning, if: :moderation_warning_event?, serializer: REST::AccountWarningSerializer + belongs_to :generated_annual_report, key: :annual_report, if: :annual_report_event?, serializer: REST::AnnualReportEventSerializer def sample_account_ids object.sample_accounts.pluck(:id).map(&:to_s) @@ -38,6 +39,10 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer object.type == :moderation_warning end + def annual_report_event? + object.type == :annual_report + end + def page_min_id object.pagination_data[:min_id].to_s end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index e3e8fde3b0..a23ea56dbc 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -89,11 +89,11 @@ class REST::StatusSerializer < ActiveModel::Serializer end def reblogs_count - relationships&.attributes_map&.dig(object.id, :reblogs_count) || object.reblogs_count + object.untrusted_reblogs_count || relationships&.attributes_map&.dig(object.id, :reblogs_count) || object.reblogs_count end def favourites_count - relationships&.attributes_map&.dig(object.id, :favourites_count) || object.favourites_count + object.untrusted_favourites_count || relationships&.attributes_map&.dig(object.id, :favourites_count) || object.favourites_count end def favourited diff --git a/app/serializers/rest/v1/instance_serializer.rb b/app/serializers/rest/v1/instance_serializer.rb index 92cc71c1ba..b9aa6b86ce 100644 --- a/app/serializers/rest/v1/instance_serializer.rb +++ b/app/serializers/rest/v1/instance_serializer.rb @@ -61,14 +61,6 @@ class REST::V1::InstanceSerializer < ActiveModel::Serializer { streaming_api: Rails.configuration.x.streaming_api_base_url } end - def usage - { - users: { - active_month: instance_presenter.active_user_count(4), - }, - } - end - def configuration { accounts: { diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb index 141ad24e92..1c7584b769 100644 --- a/app/services/activitypub/process_status_update_service.rb +++ b/app/services/activitypub/process_status_update_service.rb @@ -43,6 +43,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService update_poll! update_immediate_attributes! update_metadata! + update_counts! create_edits! end @@ -62,6 +63,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService with_redis_lock("create:#{@uri}") do update_poll!(allow_significant_changes: false) queue_poll_notifications! + update_counts! end end @@ -239,6 +241,19 @@ class ActivityPub::ProcessStatusUpdateService < BaseService end end + def update_counts! + likes = @status_parser.favourites_count + shares = @status_parser.reblogs_count + return if likes.nil? && shares.nil? + + @status.status_stat.tap do |status_stat| + status_stat.untrusted_reblogs_count = shares unless shares.nil? + status_stat.untrusted_favourites_count = likes unless likes.nil? + + status_stat.save if status_stat.changed? + end + end + def expected_type? equals_or_includes_any?(@json['type'], %w(Note Question)) end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 9aebab787e..0cf56c5a24 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -3,7 +3,7 @@ class NotifyService < BaseService include Redisable - # TODO: the severed_relationships type probably warrants email notifications + # TODO: the severed_relationships and annual_report types probably warrants email notifications NON_EMAIL_TYPES = %i( admin.report admin.sign_up @@ -12,6 +12,7 @@ class NotifyService < BaseService status moderation_warning severed_relationships + annual_report ).freeze class BaseCondition @@ -25,6 +26,7 @@ class NotifyService < BaseService poll update account_warning + annual_report ).freeze def initialize(notification) @@ -100,7 +102,7 @@ class NotifyService < BaseService class DropCondition < BaseCondition def drop? blocked = @recipient.unavailable? - blocked ||= from_self? && %i(poll severed_relationships moderation_warning).exclude?(@notification.type) + blocked ||= from_self? && %i(poll severed_relationships moderation_warning annual_report).exclude?(@notification.type) return blocked if message? && from_staff? diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 427137545f..be6df69ab8 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -4,8 +4,6 @@ class PostStatusService < BaseService include Redisable include LanguagesHelper - MIN_SCHEDULE_OFFSET = 5.minutes.freeze - class UnexpectedMentionsError < StandardError attr_reader :accounts diff --git a/app/services/process_hashtags_service.rb b/app/services/process_hashtags_service.rb index 17c347b088..0baea0185c 100644 --- a/app/services/process_hashtags_service.rb +++ b/app/services/process_hashtags_service.rb @@ -33,7 +33,7 @@ class ProcessHashtagsService < BaseService unless removed_tags.empty? @account.featured_tags.where(tag_id: removed_tags.map(&:id)).find_each do |featured_tag| - featured_tag.decrement(@status.id) + featured_tag.decrement(@status) end end end diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb index 4e1849a098..3b7a1b8580 100644 --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@ -117,7 +117,7 @@ class RemoveStatusService < BaseService def remove_from_hashtags @account.featured_tags.where(tag_id: @status.tags.map(&:id)).find_each do |featured_tag| - featured_tag.decrement(@status.id) + featured_tag.decrement(@status) end return unless @status.public_visibility? diff --git a/app/services/translate_status_service.rb b/app/services/translate_status_service.rb index e2e076e21b..bcd4703beb 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 @@ class TranslateStatusService < BaseService 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/unallow_domain_service.rb b/app/services/unallow_domain_service.rb index bdc71b1c08..bbe9571450 100644 --- a/app/services/unallow_domain_service.rb +++ b/app/services/unallow_domain_service.rb @@ -12,7 +12,7 @@ class UnallowDomainService < BaseService private def suspend_accounts!(domain) - Account.where(domain: domain).in_batches.update_all(suspended_at: Time.now.utc) + Account.where(domain: domain).in_batches.touch_all(:suspended_at) AfterUnallowDomainWorker.perform_async(domain) end end diff --git a/app/views/admin/invites/_invite.html.haml b/app/views/admin/invites/_invite.html.haml index 53eac1d0cd..e3e5d32542 100644 --- a/app/views/admin/invites/_invite.html.haml +++ b/app/views/admin/invites/_invite.html.haml @@ -1,4 +1,4 @@ -%tr +%tr{ id: dom_id(invite) } %td .input-copy .input-copy__wrapper diff --git a/app/views/application/mailer/_hashtag.html.haml b/app/views/application/mailer/_hashtag.html.haml index b740ba31b9..0fe7117bc4 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/application/mailer/_heading.html.haml b/app/views/application/mailer/_heading.html.haml index 9fc5dc7471..8b1f3f9ffc 100644 --- a/app/views/application/mailer/_heading.html.haml +++ b/app/views/application/mailer/_heading.html.haml @@ -1,13 +1,13 @@ +-# locals: (title:, image_url: nil, subtitle: nil) %table.email-w-full.email-header-heading-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-header-heading-td %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr - - if defined?(heading_image_url) + - if image_url %td.email-header-heading-img-td - = image_tag heading_image_url, alt: '', width: 56, height: 56 + = image_tag image_url, alt: '', width: 56, height: 56 %td.email-header-heading-txt-td - - if defined?(heading_title) - %h1= heading_title - - if defined?(heading_subtitle) - %p= heading_subtitle + %h1= title + - if subtitle + %p= subtitle diff --git a/app/views/notification_mailer/favourite.html.haml b/app/views/notification_mailer/favourite.html.haml index 62c0a39abe..ec2a048ba7 100644 --- a/app/views/notification_mailer/favourite.html.haml +++ b/app/views/notification_mailer/favourite.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('notification_mailer.favourite.title'), heading_subtitle: t('notification_mailer.favourite.body', name: @account.pretty_acct), heading_image_url: frontend_asset_url('images/mailer-new/heading/favorite.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/favorite.png'), + subtitle: t('notification_mailer.favourite.body', name: @account.pretty_acct), + title: t('notification_mailer.favourite.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/notification_mailer/follow.html.haml b/app/views/notification_mailer/follow.html.haml index 8247aa5b44..4e23f7fae7 100644 --- a/app/views/notification_mailer/follow.html.haml +++ b/app/views/notification_mailer/follow.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('notification_mailer.follow.title'), heading_subtitle: t('notification_mailer.follow.body', name: @account.pretty_acct), heading_image_url: frontend_asset_url('images/mailer-new/heading/user.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/user.png'), + subtitle: t('notification_mailer.follow.body', name: @account.pretty_acct), + title: t('notification_mailer.follow.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/notification_mailer/follow_request.html.haml b/app/views/notification_mailer/follow_request.html.haml index 9344ef7eb3..13a5cf87e8 100644 --- a/app/views/notification_mailer/follow_request.html.haml +++ b/app/views/notification_mailer/follow_request.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('notification_mailer.follow_request.title'), heading_subtitle: t('notification_mailer.follow_request.body', name: @account.pretty_acct), heading_image_url: frontend_asset_url('images/mailer-new/heading/follow.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/follow.png'), + subtitle: t('notification_mailer.follow_request.body', name: @account.pretty_acct), + title: t('notification_mailer.follow_request.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/notification_mailer/mention.html.haml b/app/views/notification_mailer/mention.html.haml index 83fa5086a6..419d0b76ea 100644 --- a/app/views/notification_mailer/mention.html.haml +++ b/app/views/notification_mailer/mention.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('notification_mailer.mention.title'), heading_subtitle: t('notification_mailer.mention.body', name: @status.account.pretty_acct), heading_image_url: frontend_asset_url('images/mailer-new/heading/mention.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/mention.png'), + subtitle: t('notification_mailer.mention.body', name: @status.account.pretty_acct), + title: t('notification_mailer.mention.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/notification_mailer/reblog.html.haml b/app/views/notification_mailer/reblog.html.haml index f91c678cf5..f097211bc5 100644 --- a/app/views/notification_mailer/reblog.html.haml +++ b/app/views/notification_mailer/reblog.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('notification_mailer.reblog.title'), heading_subtitle: t('notification_mailer.reblog.body', name: @account.pretty_acct), heading_image_url: frontend_asset_url('images/mailer-new/heading/boost.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/boost.png'), + subtitle: t('notification_mailer.reblog.body', name: @account.pretty_acct), + title: t('notification_mailer.reblog.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/settings/verifications/show.html.haml b/app/views/settings/verifications/show.html.haml index 560807f27c..4def10e595 100644 --- a/app/views/settings/verifications/show.html.haml +++ b/app/views/settings/verifications/show.html.haml @@ -38,25 +38,34 @@ %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: 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)) }) + .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/user_mailer/appeal_approved.html.haml b/app/views/user_mailer/appeal_approved.html.haml index 54e9a94a54..2da3e0d3eb 100644 --- a/app/views/user_mailer/appeal_approved.html.haml +++ b/app/views/user_mailer/appeal_approved.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('user_mailer.appeal_approved.title'), heading_subtitle: t('user_mailer.appeal_approved.subtitle'), heading_image_url: frontend_asset_url('images/mailer-new/heading/appeal-approved.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/appeal-approved.png'), + subtitle: t('user_mailer.appeal_approved.subtitle'), + title: t('user_mailer.appeal_approved.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/appeal_rejected.html.haml b/app/views/user_mailer/appeal_rejected.html.haml index b493712b05..6f9282507b 100644 --- a/app/views/user_mailer/appeal_rejected.html.haml +++ b/app/views/user_mailer/appeal_rejected.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('user_mailer.appeal_rejected.title'), heading_subtitle: t('user_mailer.appeal_rejected.subtitle'), heading_image_url: frontend_asset_url('images/mailer-new/heading/appeal-rejected.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/appeal-rejected.png'), + subtitle: t('user_mailer.appeal_rejected.subtitle'), + title: t('user_mailer.appeal_rejected.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/backup_ready.html.haml b/app/views/user_mailer/backup_ready.html.haml index 99a48e7fdb..c25f0b45dd 100644 --- a/app/views/user_mailer/backup_ready.html.haml +++ b/app/views/user_mailer/backup_ready.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('user_mailer.backup_ready.title'), heading_subtitle: t('user_mailer.backup_ready.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/archive.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/archive.png'), + subtitle: t('user_mailer.backup_ready.explanation'), + title: t('user_mailer.backup_ready.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/confirmation_instructions.html.haml b/app/views/user_mailer/confirmation_instructions.html.haml index 13e68c722b..d3e3e8f930 100644 --- a/app/views/user_mailer/confirmation_instructions.html.haml +++ b/app/views/user_mailer/confirmation_instructions.html.haml @@ -1,5 +1,7 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.confirmation_instructions.title'), heading_image_url: frontend_asset_url('images/mailer-new/heading/email.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/email.png'), + title: t('devise.mailer.confirmation_instructions.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/email_changed.html.haml b/app/views/user_mailer/email_changed.html.haml index 71678ad029..33e35a314b 100644 --- a/app/views/user_mailer/email_changed.html.haml +++ b/app/views/user_mailer/email_changed.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.email_changed.title'), heading_subtitle: t('devise.mailer.email_changed.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/email.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/email.png'), + subtitle: t('devise.mailer.email_changed.explanation'), + title: t('devise.mailer.email_changed.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/failed_2fa.html.haml b/app/views/user_mailer/failed_2fa.html.haml index e1da35ce06..edac8ef63b 100644 --- a/app/views/user_mailer/failed_2fa.html.haml +++ b/app/views/user_mailer/failed_2fa.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('user_mailer.failed_2fa.title'), heading_subtitle: t('user_mailer.failed_2fa.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/login.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/login.png'), + subtitle: t('user_mailer.failed_2fa.explanation'), + title: t('user_mailer.failed_2fa.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/password_change.html.haml b/app/views/user_mailer/password_change.html.haml index 44c8c0dcaf..350f5bd996 100644 --- a/app/views/user_mailer/password_change.html.haml +++ b/app/views/user_mailer/password_change.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.password_change.title'), heading_subtitle: t('devise.mailer.password_change.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/password.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/password.png'), + subtitle: t('devise.mailer.password_change.explanation'), + title: t('devise.mailer.password_change.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/reconfirmation_instructions.html.haml b/app/views/user_mailer/reconfirmation_instructions.html.haml index 854887a7e0..6f6954f705 100644 --- a/app/views/user_mailer/reconfirmation_instructions.html.haml +++ b/app/views/user_mailer/reconfirmation_instructions.html.haml @@ -1,5 +1,7 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.reconfirmation_instructions.title'), heading_image_url: frontend_asset_url('images/mailer-new/heading/email.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/email.png'), + title: t('devise.mailer.reconfirmation_instructions.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/reset_password_instructions.html.haml b/app/views/user_mailer/reset_password_instructions.html.haml index a1384fcc27..5a1480867c 100644 --- a/app/views/user_mailer/reset_password_instructions.html.haml +++ b/app/views/user_mailer/reset_password_instructions.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.reset_password_instructions.title'), heading_subtitle: t('devise.mailer.reset_password_instructions.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/password.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/password.png'), + subtitle: t('devise.mailer.reset_password_instructions.explanation'), + title: t('devise.mailer.reset_password_instructions.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/suspicious_sign_in.html.haml b/app/views/user_mailer/suspicious_sign_in.html.haml index deee7a1ce1..890d883c44 100644 --- a/app/views/user_mailer/suspicious_sign_in.html.haml +++ b/app/views/user_mailer/suspicious_sign_in.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('user_mailer.suspicious_sign_in.title'), heading_subtitle: t('user_mailer.suspicious_sign_in.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/login.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/login.png'), + subtitle: t('user_mailer.suspicious_sign_in.explanation'), + title: t('user_mailer.suspicious_sign_in.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/two_factor_disabled.html.haml b/app/views/user_mailer/two_factor_disabled.html.haml index 28f6ca6600..4f1559d86c 100644 --- a/app/views/user_mailer/two_factor_disabled.html.haml +++ b/app/views/user_mailer/two_factor_disabled.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_disabled.title'), heading_subtitle: t('devise.mailer.two_factor_disabled.subtitle'), heading_image_url: frontend_asset_url('images/mailer-new/heading/2fa-disabled.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/2fa-disabled.png'), + subtitle: t('devise.mailer.two_factor_disabled.subtitle'), + title: t('devise.mailer.two_factor_disabled.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/two_factor_enabled.html.haml b/app/views/user_mailer/two_factor_enabled.html.haml index 691dc661a0..0ed57ea32b 100644 --- a/app/views/user_mailer/two_factor_enabled.html.haml +++ b/app/views/user_mailer/two_factor_enabled.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_enabled.title'), heading_subtitle: t('devise.mailer.two_factor_enabled.subtitle'), heading_image_url: frontend_asset_url('images/mailer-new/heading/2fa-enabled.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/2fa-enabled.png'), + subtitle: t('devise.mailer.two_factor_enabled.subtitle'), + title: t('devise.mailer.two_factor_enabled.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml b/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml index 2d063e4c76..cc4c21b83b 100644 --- a/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml +++ b/app/views/user_mailer/two_factor_recovery_codes_changed.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.two_factor_recovery_codes_changed.title'), heading_subtitle: t('devise.mailer.two_factor_recovery_codes_changed.subtitle'), heading_image_url: frontend_asset_url('images/mailer-new/heading/2fa-recovery.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/2fa-recovery.png'), + subtitle: t('devise.mailer.two_factor_recovery_codes_changed.subtitle'), + title: t('devise.mailer.two_factor_recovery_codes_changed.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/warning.html.haml b/app/views/user_mailer/warning.html.haml index 837cde550e..fe8db974ee 100644 --- a/app/views/user_mailer/warning.html.haml +++ b/app/views/user_mailer/warning.html.haml @@ -1,5 +1,7 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t("user_mailer.warning.title.#{@warning.action}"), heading_image_url: frontend_asset_url('images/mailer-new/heading/warning.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/warning.png'), + title: t("user_mailer.warning.title.#{@warning.action}") %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/webauthn_credential_added.html.haml b/app/views/user_mailer/webauthn_credential_added.html.haml index 3e16766238..9c5cbdd676 100644 --- a/app/views/user_mailer/webauthn_credential_added.html.haml +++ b/app/views/user_mailer/webauthn_credential_added.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_credential.added.title'), heading_subtitle: t('devise.mailer.webauthn_credential.added.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/key-added.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/key-added.png'), + subtitle: t('devise.mailer.webauthn_credential.added.explanation'), + title: t('devise.mailer.webauthn_credential.added.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/webauthn_credential_deleted.html.haml b/app/views/user_mailer/webauthn_credential_deleted.html.haml index 59dcb75d3a..decfc02c22 100644 --- a/app/views/user_mailer/webauthn_credential_deleted.html.haml +++ b/app/views/user_mailer/webauthn_credential_deleted.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_credential.deleted.title'), heading_subtitle: t('devise.mailer.webauthn_credential.deleted.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/key-deleted.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/key-deleted.png'), + subtitle: t('devise.mailer.webauthn_credential.deleted.explanation'), + title: t('devise.mailer.webauthn_credential.deleted.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/webauthn_disabled.html.haml b/app/views/user_mailer/webauthn_disabled.html.haml index 0f7c534bc4..232c951915 100644 --- a/app/views/user_mailer/webauthn_disabled.html.haml +++ b/app/views/user_mailer/webauthn_disabled.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_disabled.title'), heading_subtitle: t('devise.mailer.webauthn_disabled.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/key-disabled.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/key-disabled.png'), + subtitle: t('devise.mailer.webauthn_disabled.explanation'), + title: t('devise.mailer.webauthn_disabled.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/webauthn_enabled.html.haml b/app/views/user_mailer/webauthn_enabled.html.haml index cd11aa5a40..955a557de4 100644 --- a/app/views/user_mailer/webauthn_enabled.html.haml +++ b/app/views/user_mailer/webauthn_enabled.html.haml @@ -1,5 +1,8 @@ = content_for :heading do - = render 'application/mailer/heading', heading_title: t('devise.mailer.webauthn_enabled.title'), heading_subtitle: t('devise.mailer.webauthn_enabled.explanation'), heading_image_url: frontend_asset_url('images/mailer-new/heading/key-enabled.png') + = render 'application/mailer/heading', + image_url: frontend_asset_url('images/mailer-new/heading/key-enabled.png'), + subtitle: t('devise.mailer.webauthn_enabled.explanation'), + title: t('devise.mailer.webauthn_enabled.title') %table.email-w-full{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } %tr %td.email-body-padding-td diff --git a/app/views/user_mailer/welcome.html.haml b/app/views/user_mailer/welcome.html.haml index efc6cad393..c37104da79 100644 --- a/app/views/user_mailer/welcome.html.haml +++ b/app/views/user_mailer/welcome.html.haml @@ -1,7 +1,9 @@ = content_for :heading do .email-desktop-flex .email-header-left - = render 'application/mailer/heading', heading_title: t('user_mailer.welcome.title', name: @resource.account.username), heading_subtitle: t('user_mailer.welcome.explanation') + = render 'application/mailer/heading', + subtitle: t('user_mailer.welcome.explanation'), + title: t('user_mailer.welcome.title', name: @resource.account.username) .email-header-right .email-header-card %table.email-header-card-table{ cellspacing: 0, cellpadding: 0, border: 0, role: 'presentation' } diff --git a/app/views/user_mailer/welcome.text.erb b/app/views/user_mailer/welcome.text.erb index d9da2997da..144d44b842 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/scheduler/scheduled_statuses_scheduler.rb b/app/workers/scheduler/scheduled_statuses_scheduler.rb index 4e251780de..e2ccabf70f 100644 --- a/app/workers/scheduler/scheduled_statuses_scheduler.rb +++ b/app/workers/scheduler/scheduled_statuses_scheduler.rb @@ -20,7 +20,7 @@ class Scheduler::ScheduledStatusesScheduler end def due_statuses - ScheduledStatus.where(scheduled_at: ..Time.now.utc + PostStatusService::MIN_SCHEDULE_OFFSET) + ScheduledStatus.where(scheduled_at: ..time_due_at) end def publish_scheduled_announcements! @@ -30,7 +30,7 @@ class Scheduler::ScheduledStatusesScheduler end def due_announcements - Announcement.unpublished.where('scheduled_at IS NOT NULL AND scheduled_at <= ?', Time.now.utc + PostStatusService::MIN_SCHEDULE_OFFSET) + Announcement.unpublished.where('scheduled_at IS NOT NULL AND scheduled_at <= ?', time_due_at) end def unpublish_expired_announcements! @@ -40,4 +40,8 @@ class Scheduler::ScheduledStatusesScheduler def expired_announcements Announcement.published.where('ends_at IS NOT NULL AND ends_at <= ?', Time.now.utc) end + + def time_due_at + Time.now.utc + ScheduledStatus::MINIMUM_OFFSET + end end diff --git a/app/workers/web/push_notification_worker.rb b/app/workers/web/push_notification_worker.rb index e771928ef3..824e7b5940 100644 --- a/app/workers/web/push_notification_worker.rb +++ b/app/workers/web/push_notification_worker.rb @@ -2,10 +2,11 @@ class Web::PushNotificationWorker include Sidekiq::Worker + include RoutingHelper sidekiq_options queue: 'push', retry: 5 - TTL = 48.hours.to_s + TTL = 48.hours URGENCY = 'normal' def perform(subscription_id, notification_id) @@ -23,12 +24,13 @@ class Web::PushNotificationWorker request.add_headers( 'Content-Type' => 'application/octet-stream', - 'Ttl' => TTL, + 'Ttl' => TTL.to_s, 'Urgency' => URGENCY, 'Content-Encoding' => 'aesgcm', 'Encryption' => "salt=#{Webpush.encode64(payload.fetch(:salt)).delete('=')}", 'Crypto-Key' => "dh=#{Webpush.encode64(payload.fetch(:server_public_key)).delete('=')};#{web_push_request.crypto_key_header}", - 'Authorization' => web_push_request.authorization_header + 'Authorization' => web_push_request.authorization_header, + 'Unsubscribe-URL' => subscription_url ) request.perform do |response| @@ -72,4 +74,8 @@ class Web::PushNotificationWorker def request_pool RequestPool.current end + + def subscription_url + api_web_push_subscription_url(id: @subscription.generate_token_for(:unsubscribe)) + end end diff --git a/config.ru b/config.ru index afd13e2112..842bccc340 100644 --- a/config.ru +++ b/config.ru @@ -2,5 +2,6 @@ # This file is used by Rack-based servers to start the application. -require File.expand_path('config/environment', __dir__) +require_relative 'config/environment' + run Rails.application diff --git a/config/application.rb b/config/application.rb index 5e2f44453d..18a1b1a0fd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -52,8 +52,6 @@ require_relative '../lib/action_dispatch/remote_ip_extensions' require_relative '../lib/stoplight/redis_data_store_extensions' require_relative '../lib/active_record/database_tasks_extensions' require_relative '../lib/active_record/batches' -require_relative '../lib/active_record/with_recursive' -require_relative '../lib/arel/union_parenthesizing' require_relative '../lib/simple_navigation/item_extensions' Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true' @@ -61,10 +59,7 @@ Bundler.require(:pam_authentication) if ENV['PAM_ENABLED'] == 'true' module Mastodon class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 7.1 - - # Explicitly set the cache format version to align with Rails version - config.active_support.cache_format_version = 7.1 + config.load_defaults 7.2 # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. @@ -109,6 +104,9 @@ module Mastodon end end + config.x.captcha = config_for(:captcha) + config.x.translation = config_for(:translation) + config.to_prepare do Doorkeeper::AuthorizationsController.layout 'modal' Doorkeeper::AuthorizedApplicationsController.layout 'admin' diff --git a/config/captcha.yml b/config/captcha.yml new file mode 100644 index 0000000000..a9f54588c7 --- /dev/null +++ b/config/captcha.yml @@ -0,0 +1,3 @@ +shared: + secret_key: <%= ENV.fetch('HCAPTCHA_SECRET_KEY', nil) %> + site_key: <%= ENV.fetch('HCAPTCHA_SITE_KEY', nil) %> diff --git a/config/environments/development.rb b/config/environments/development.rb index 74f0913da2..8533935a88 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -16,7 +16,7 @@ Rails.application.configure do # Show full error reports. config.consider_all_requests_local = true - # Enable server timing + # Enable server timing. config.server_timing = true # Enable/disable caching. By default caching is disabled. @@ -37,11 +37,6 @@ Rails.application.configure do config.action_controller.forgery_protection_origin_check = ENV['DISABLE_FORGERY_REQUEST_PROTECTION'].nil? - ActiveSupport::Logger.new($stdout).tap do |logger| - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - # Generate random VAPID keys Webpush.generate_key.tap do |vapid_key| config.x.vapid_private_key = vapid_key.private_key @@ -51,6 +46,8 @@ Rails.application.configure do # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Print deprecation notices to the Rails logger. @@ -77,9 +74,6 @@ Rails.application.configure do # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Uncomment if you wish to allow Action Cable access from any origin. - # config.action_cable.disable_request_forgery_protection = true - config.action_mailer.default_options = { from: 'notifications@localhost' } # If using a Heroku, Vagrant or generic remote development environment, @@ -90,8 +84,11 @@ Rails.application.configure do # TODO: Remove once devise-two-factor data migration complete config.x.otp_secret = ENV.fetch('OTP_SECRET', '1fc2b87989afa6351912abeebe31ffc5c476ead9bf8b3d74cbc4a302c7b69a45b40b1bbef3506ddad73e942e15ed5ca4b402bf9a66423626051104f4b5f05109') - # Raise error when a before_action's only/except options reference missing actions + # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = true + + # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. + config.generators.apply_rubocop_autocorrect_after_generate! end Redis.raise_deprecations = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 4a27310dc0..f37a1ebc98 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -15,22 +15,21 @@ Rails.application.configure do config.eager_load = true # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true - config.action_controller.asset_host = ENV['CDN_HOST'] if ENV['CDN_HOST'].present? # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). # config.require_master_key = true - # Compress CSS using a preprocessor. - # config.assets.css_compressor = :sass - # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false + # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. + # config.public_file_server.enabled = false + # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.asset_host = "http://assets.example.com" + config.asset_host = ENV['CDN_HOST'] if ENV['CDN_HOST'].present? # Specifies the header that your server uses for sending files. config.action_dispatch.x_sendfile_header = ENV['SENDFILE_HEADER'] if ENV['SENDFILE_HEADER'].present? @@ -40,29 +39,41 @@ Rails.application.configure do # Allow to specify public IP of reverse proxy if it's needed config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split(/(?:\s*,\s*|\s+)/).map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present? + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. config.force_ssl = true + # Skip http-to-https redirect for the default health check endpoint. config.ssl_options = { redirect: { exclude: ->(request) { request.path.start_with?('/health') || request.headers['Host'].end_with?('.onion') || request.headers['Host'].end_with?('.i2p') }, }, } - # Info include generic and useful information about system operation, but avoids logging too much - # information to avoid inadvertent exposure of personally identifiable information (PII). If you - # want to log everything, set the level to "debug". - config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym + # Log to STDOUT by default + config.logger = ActiveSupport::Logger.new($stdout) + .tap { |logger| logger.formatter = ::Logger::Formatter.new } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. config.log_tags = [:request_id] + # "info" includes generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info') + # Use a different cache store in production. config.cache_store = :redis_cache_store, REDIS_CONFIGURATION.cache # Use a real queuing backend for Active Job (and separate queues per environment). - # config.active_job.queue_adapter = :resque + # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "mastodon_production" + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -70,7 +81,7 @@ Rails.application.configure do # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # English when a translation cannot be found). + # the I18n.default_locale when a translation cannot be found). # This setting would typically be `true` to use the `I18n.default_locale`. # Some locales are missing translation entries and would have errors: # https://github.com/mastodon/mastodon/pull/24727 @@ -89,18 +100,8 @@ Rails.application.configure do { key: controller.signature_key_id } if controller.respond_to?(:signed_request?) && controller.signed_request? end - # Use a different logger for distributed setups. - # require "syslog/logger" - # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") - - # Log to STDOUT by default - config.logger = ActiveSupport::Logger.new($stdout) - .tap { |logger| logger.formatter = ::Logger::Formatter.new } - .then { |logger| ActiveSupport::TaggedLogging.new(logger) } - # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - config.action_mailer.perform_caching = false # E-mails diff --git a/config/environments/test.rb b/config/environments/test.rb index 716bf8d31f..5406eac9ec 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -19,19 +19,19 @@ Rails.application.configure do # loading is working properly before deploying your code. config.eager_load = ENV['CI'].present? - config.assets_digest = false - # Show full error reports and disable caching. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false config.cache_store = :memory_store - # Raise exceptions instead of rendering exception templates. + # Render exception templates for rescuable exceptions and raise for other exceptions. config.action_dispatch.show_exceptions = :rescuable # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false config.action_mailer.default_options = { from: 'notifications@localhost' } @@ -41,6 +41,10 @@ Rails.application.configure do # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test + # Unlike controllers, the mailer instance doesn't have any context about the + # incoming request so you'll need to provide the :host parameter yourself. + config.action_mailer.default_url_options = { host: 'www.example.com' } + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr @@ -58,7 +62,6 @@ Rails.application.configure do # Raise exceptions for disallowed deprecations. config.active_support.disallowed_deprecation = :raise - config.i18n.default_locale = :en config.i18n.fallbacks = true # Tell Active Support which deprecation messages to disallow. @@ -70,7 +73,7 @@ Rails.application.configure do # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true - # Raise error when a before_action's only/except options reference missing actions + # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/initializers/active_record_encryption.rb b/config/initializers/active_record_encryption.rb index c53f16d4d1..9ae28e401b 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: diff --git a/config/initializers/cookie_rotator.rb b/config/initializers/cookie_rotator.rb deleted file mode 100644 index ccc2c6b21f..0000000000 --- a/config/initializers/cookie_rotator.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -# TODO: remove this file some time after 4.3.0 - -Rails.application.config.after_initialize do - Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| - authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt - signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt - - secret_key_base = Rails.application.secret_key_base - - key_generator = ActiveSupport::KeyGenerator.new( - secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 - ) - key_len = ActiveSupport::MessageEncryptor.key_len - - old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len) - old_signed_secret = key_generator.generate_key(signed_cookie_salt) - - cookies.rotate :encrypted, old_encrypted_secret - cookies.rotate :signed, old_signed_secret - end -end diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb index c530693a3f..476f1fb07a 100644 --- a/config/initializers/cors.rb +++ b/config/initializers/cors.rb @@ -23,6 +23,7 @@ Rails.application.config.middleware.insert_before 0, Rack::Cors do methods: %i(post put delete get patch options) resource '/oauth/token', methods: [:post] resource '/oauth/revoke', methods: [:post] + resource '/oauth/userinfo', methods: [:get, :post] end end end diff --git a/config/initializers/httplog.rb b/config/initializers/httplog.rb index 02fcef4120..7a009e84d1 100644 --- a/config/initializers/httplog.rb +++ b/config/initializers/httplog.rb @@ -1,7 +1,12 @@ # frozen_string_literal: true -HttpLog.configure do |config| - config.logger = Rails.logger - config.color = { color: :yellow } - config.compact_log = true +# Disable httplog in production unless log_level is `debug` +if !Rails.env.production? || Rails.configuration.log_level == :debug + require 'httplog' + + HttpLog.configure do |config| + config.logger = Rails.logger + config.color = { color: :yellow } + config.compact_log = true + end end diff --git a/config/locales-glitch/ru.yml b/config/locales-glitch/ru.yml index ddc9d1e32c..f6f52ae104 100644 --- a/config/locales-glitch/ru.yml +++ b/config/locales-glitch/ru.yml @@ -1 +1,19 @@ +--- ru: + admin: + custom_emojis: + batch_error: 'Произошла ошибка: %{message}' + settings: + flavour_and_skin: + title: Стиль и цвета + hide_followers_count: + title: Скрыть количество подписчиков + other: + preamble: Настройки glitch-soc, которые не могут быть отнесены к другим категориям. + title: Прочее + appearance: + localization: + glitch_guide_link: https://crowdin.com/project/glitch-soc + glitch_guide_link_text: И для glitch-soc тоже! + settings: + flavours: Стили diff --git a/config/locales-glitch/simple_form.ru.yml b/config/locales-glitch/simple_form.ru.yml index ddc9d1e32c..179f7c1050 100644 --- a/config/locales-glitch/simple_form.ru.yml +++ b/config/locales-glitch/simple_form.ru.yml @@ -1 +1,20 @@ +--- ru: + simple_form: + glitch_only: glitch-soc + hints: + defaults: + setting_skin: Меняет оформление выбранного стиля Mastodon + labels: + defaults: + setting_default_content_type: Формат постов по умолчанию + setting_default_content_type_html: HTML + setting_default_content_type_markdown: Markdown + setting_default_content_type_plain: Простой текст + setting_favourite_modal: Всегда спрашивать перед добавлением в избранное (применяется только к стилю Glitch) + setting_skin: Тема + setting_system_emoji_font: Использовать системный шрифт эмодзи по умолчанию (применяется только к стилю Glitch) + notification_emails: + trending_link: Новая актуальная ссылка требует проверки + trending_status: Новый актуальный пост требует проверки + trending_tag: Новый актуальный хештег требует проверки diff --git a/config/locales/activerecord.eo.yml b/config/locales/activerecord.eo.yml index f99f726e23..45149cd117 100644 --- a/config/locales/activerecord.eo.yml +++ b/config/locales/activerecord.eo.yml @@ -25,7 +25,7 @@ eo: 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.fa.yml b/config/locales/activerecord.fa.yml index 3d1e8012bf..81e54ed3a9 100644 --- a/config/locales/activerecord.fa.yml +++ b/config/locales/activerecord.fa.yml @@ -15,6 +15,12 @@ fa: 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.ia.yml b/config/locales/activerecord.ia.yml index bccfb96602..809b8fd582 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.ja.yml b/config/locales/activerecord.ja.yml index 468df9b12b..21be8aa345 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 31e0223cca..8fd23b53fe 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 8b20ee34b3..90c5b38ad5 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.zh-TW.yml b/config/locales/activerecord.zh-TW.yml index 7422550660..113d881ae5 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/ast.yml b/config/locales/ast.yml index 72c5d9d752..a3310f0d46 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 @@ -778,6 +780,7 @@ ast: 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/ca.yml b/config/locales/ca.yml index cc2da496a6..9d861fa30c 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1166,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 diff --git a/config/locales/cy.yml b/config/locales/cy.yml index d57ef38696..2d6a0eb38d 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: @@ -1062,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 @@ -1126,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 @@ -1237,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 @@ -1367,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. @@ -1465,6 +1468,92 @@ cy: merge_long: Cadw'r cofnodion presennol ac ychwanegu rhai newydd overwrite: Trosysgrifio overwrite_long: Amnewid y cofnodion cyfredol gyda'r rhai newydd + overwrite_preambles: + 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: + 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: @@ -1547,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: @@ -1569,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. @@ -1584,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: diff --git a/config/locales/da.yml b/config/locales/da.yml index 923102c11f..6447afb493 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -1166,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 diff --git a/config/locales/de.yml b/config/locales/de.yml index cfd0d6510e..323579f25f 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1166,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 @@ -1967,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 43aef271f9..754fa01550 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. @@ -53,12 +53,14 @@ eo: subtitle: Dupaŝa aŭtentigo por via konto estas malŝaltita. title: 2FA estas malŝaltita two_factor_enabled: + explanation: Tokeno generita de la parigita TOTP-aplikaĵo estos necesa por ensaluti. 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. subject: 'Mastodon: Reakiraj kodoj de dufaktora aŭtentigo rekreitaj' + subtitle: La antaŭaj restarigaj kodoj estis malvalidigitaj kaj novaj estis generitaj. title: Reakiraj kodoj de 2FA estas ŝanĝitaj unlock_instructions: subject: 'Mastodon: Instrukcioj por malŝlosi' diff --git a/config/locales/doorkeeper.ast.yml b/config/locales/doorkeeper.ast.yml index c9c831f7f5..3df18d6f7a 100644 --- a/config/locales/doorkeeper.ast.yml +++ b/config/locales/doorkeeper.ast.yml @@ -50,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.eo.yml b/config/locales/doorkeeper.eo.yml index 12e120f8be..36a5ed1974 100644 --- a/config/locales/doorkeeper.eo.yml +++ b/config/locales/doorkeeper.eo.yml @@ -60,6 +60,7 @@ eo: error: title: Eraro okazis new: + prompt_html: "%{client_name} ŝatus permeson aliri vian konton. Nur aprobu ĉi tiun peton se vi rekonas kaj fidas ĉi tiun fonton." review_permissions: Revizu permesojn title: Rajtigo bezonata show: @@ -82,6 +83,7 @@ eo: access_denied: La posedanto de la rimedo aŭ de la rajtiga servilo rifuzis vian peton. credential_flow_not_configured: La sendado de la identigiloj de la posedanto de la rimedo malsukcesis ĉar Doorkeeper.configure.resource_owner_from_credentials ne estis agordita. invalid_client: Klienta aŭtentigo malsukcesa pro nekonata kliento, neniu klienta aŭtentigo inkluzivita, aŭ nesubtenata aŭtentiga metodo. + invalid_code_challenge_method: La koda defia metodo devas esti S256, ebenaĵo estas nesubtenata. invalid_grant: La rajtiga konsento ne estas valida, ne plu estas valida, estis forigita, ne kongruas kun la plusenda URI uzita en la aŭtentiga peto, aŭ estis sendita al alia kliento. invalid_redirect_uri: La plusenda URI uzita ne estas valida. invalid_request: @@ -134,6 +136,7 @@ eo: media: Plurmediaj aldonaĵoj mutes: Silentigitaj notifications: Sciigoj + profile: Via Mastodon-profilo push: Puŝsciigoj reports: Raportoj search: Serĉi @@ -164,6 +167,7 @@ eo: admin:write:reports: plenumi agojn de kontrolo sur signaloj crypto: uzi fin-al-finan ĉifradon follow: ŝanĝi rilatojn al aliaj kontoj + profile: legu nur la profilinformojn de via konto push: ricevi viajn puŝ-sciigojn read: legi ĉiujn datumojn de via konto read:accounts: vidi la informojn de la kontoj diff --git a/config/locales/doorkeeper.es-MX.yml b/config/locales/doorkeeper.es-MX.yml index e119d71f4e..eaf1bf69fb 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: 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. + 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.et.yml b/config/locales/doorkeeper.et.yml index ebfaf5c710..fb135b1f96 100644 --- a/config/locales/doorkeeper.et.yml +++ b/config/locales/doorkeeper.et.yml @@ -60,6 +60,7 @@ et: error: title: Ilmnes viga new: + 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.fa.yml b/config/locales/doorkeeper.fa.yml index 4ff03950b5..8e2bc864a2 100644 --- a/config/locales/doorkeeper.fa.yml +++ b/config/locales/doorkeeper.fa.yml @@ -130,7 +130,7 @@ fa: favourites: برگزیده‌ها filters: پالایه‌ها follow: پی‌گیری، خموشی و مسدودی‌ها - follows: پی‌گرفتگان + follows: پی‌گرفتن‌ها lists: سیاهه‌ها media: پیوست‌های رسانه‌ای mutes: خموش‌ها diff --git a/config/locales/doorkeeper.is.yml b/config/locales/doorkeeper.is.yml index 05f2415eea..1fabd1b55f 100644 --- a/config/locales/doorkeeper.is.yml +++ b/config/locales/doorkeeper.is.yml @@ -60,6 +60,7 @@ is: error: title: Villa kom upp new: + 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.ja.yml b/config/locales/doorkeeper.ja.yml index 7cfddf50a1..d44451c746 100644 --- a/config/locales/doorkeeper.ja.yml +++ b/config/locales/doorkeeper.ja.yml @@ -60,6 +60,7 @@ ja: error: title: エラーが発生しました new: + prompt_html: "%{client_name} があなたのアカウントにアクセスするための許可を求めています。このリクエストを承認するのは、信頼できる相手であると認識している場合のみです。" review_permissions: アクセス許可を確認 title: 認証が必要です show: diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml index 55e288a9d6..af892d79fa 100644 --- a/config/locales/doorkeeper.lv.yml +++ b/config/locales/doorkeeper.lv.yml @@ -60,6 +60,7 @@ lv: error: title: Radās kļūda new: + prompt_html: "%{client_name} vēlas atļauju piekļūt Tavam kontam. Apstiprini šo pieprasījumu tikai tad, ja atpazīsti un uzticies šim avotam!" review_permissions: Pārskatīt atļaujas title: Nepieciešama autorizācija show: @@ -119,9 +120,9 @@ lv: write: Tikai rakstīšanas piekļuve title: accounts: Konti - admin/accounts: Kontu administrēšana + admin/accounts: Kontu pārvaldīšana admin/all: Visas administrēšanas funkcijas - admin/reports: Ziņojumu administrēšana + admin/reports: Ziņojumu pārvaldīšana all: Pilna piekļuve tavam Mastodon kontam blocks: Bloķētie bookmarks: Grāmatzīmes @@ -157,13 +158,13 @@ lv: admin:read:ip_blocks: lasīt sensitīvu informāciju par visiem IP blokiem admin:read:reports: lasīt sensitīvu informāciju no visiem pārskatiem un kontiem, par kuriem ziņots admin:write: modificēt visus datus uz servera - admin:write:accounts: veikt moderācijas darbības kontos - admin:write:canonical_email_blocks: veikt regulēšanas darbības kanoniskajos e-pasta blokos - admin:write:domain_allows: veikt moderēšanas darbības domēna atļaujā - admin:write:domain_blocks: veikt moderēšanas darbības domēna blokos - admin:write:email_domain_blocks: veikt moderēšanas darbības e-pasta domēna blokos - admin:write:ip_blocks: veikt moderēšanas darbības IP blokos - admin:write:reports: veikt moderācijas darbības pārskatos + admin:write:accounts: veikt satura pārraudzības darbības kontos + admin:write:canonical_email_blocks: veikt satura pārraudzības darbības kanoniskajos e-pasta blokos + admin:write:domain_allows: veikt satura pārraudzības darbības domēna atļaujā + admin:write:domain_blocks: veikt satura pārraudzības darbības domēna blokos + admin:write:email_domain_blocks: veikt satura pārraudzības darbības e-pasta domēna blokos + admin:write:ip_blocks: veikt satura pārraudzības darbības IP blokos + admin:write:reports: veikt satura pārraudzības darbības pārskatos crypto: lieto pilnīgu šifrēšanu follow: mainīt konta attiecības profile: lasīt tikai Tava konta profila informāciju diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml index 1dcb2093d5..c7ea94c2e3 100644 --- a/config/locales/doorkeeper.ru.yml +++ b/config/locales/doorkeeper.ru.yml @@ -60,6 +60,7 @@ ru: 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 9f646fd3e4..ca8271ebf1 100644 --- a/config/locales/doorkeeper.sv.yml +++ b/config/locales/doorkeeper.sv.yml @@ -60,6 +60,7 @@ sv: error: title: Ett fel har uppstått new: + 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: @@ -132,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 e7ed0ba8a3..3b52e170ea 100644 --- a/config/locales/doorkeeper.th.yml +++ b/config/locales/doorkeeper.th.yml @@ -60,6 +60,7 @@ th: error: title: เกิดข้อผิดพลาด new: + prompt_html: "%{client_name} ต้องการสิทธิอนุญาตเพื่อเข้าถึงบัญชีของคุณ อนุมัติคำขอนี้เฉพาะหากคุณรู้จักและเชื่อถือแหล่งที่มานี้เท่านั้น" review_permissions: ตรวจทานสิทธิอนุญาต title: ต้องการการอนุญาต show: diff --git a/config/locales/doorkeeper.vi.yml b/config/locales/doorkeeper.vi.yml index 6687c0339d..2219599c57 100644 --- a/config/locales/doorkeeper.vi.yml +++ b/config/locales/doorkeeper.vi.yml @@ -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ả 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 46253d01b3..08f9885894 100644 --- a/config/locales/doorkeeper.zh-CN.yml +++ b/config/locales/doorkeeper.zh-CN.yml @@ -167,7 +167,7 @@ zh-CN: admin:write:reports: 对举报执行管理操作 crypto: 使用端到端加密 follow: 关注或屏蔽用户 - profile: 仅读取你账户中的个人资料信息 + profile: 仅读取你账号的个人资料信息 push: 接收你的账户的推送通知 read: 读取你的账户数据 read:accounts: 查看账号信息 diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 65b2e6f71a..fb284479f2 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -1165,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 diff --git a/config/locales/en.yml b/config/locales/en.yml index c88ef3fa20..e9c8822d5a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1166,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 diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 1e683b1725..12cae075f0 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -19,7 +19,7 @@ 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: @@ -61,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 @@ -69,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 @@ -81,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 @@ -133,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: @@ -173,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 @@ -231,6 +239,7 @@ eo: 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_canonical_email_block_html: "%{name} blokis retpoŝtadreson per krado %{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}" @@ -240,6 +249,7 @@ eo: create_user_role_html: "%{name} kreis rolon de %{target}" demote_user_html: "%{name} degradis uzanton %{target}" destroy_announcement_html: "%{name} forigis anoncon %{target}" + destroy_canonical_email_block_html: "%{name} malblokis retpoŝtadreson per krado %{target}" 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}" @@ -274,6 +284,7 @@ eo: update_custom_emoji_html: "%{name} ĝisdatigis la emoĝion %{target}" update_domain_block_html: "%{name} ĝisdatigis domajnblokon por %{target}" update_ip_block_html: "%{name} ŝanĝis regulon por IP %{target}" + update_report_html: "%{name} ĝisdatigis la raporton %{target}" update_status_html: "%{name} ĝisdatigis afiŝon de %{target}" update_user_role_html: "%{name} ŝanĝis la rolon %{target}" deleted_account: forigita konto @@ -431,6 +442,7 @@ eo: 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 @@ -522,6 +534,7 @@ eo: total_reported: Signaloj pri ili total_storage: Aŭdovidaj kunsendaĵoj totals_time_period_hint_html: Sumo montritas malsupre inkluzivas datumo ekde komenco. + unknown_instance: Nuntempe ne ekzistas registro pri ĉi tiu domajno sur ĉi tiu servilo. invites: deactivate_all: Malaktivigi ĉion filter: @@ -583,6 +596,9 @@ eo: 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 @@ -731,6 +747,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: @@ -750,6 +767,7 @@ eo: disabled: Al neniu users: Al salutintaj lokaj uzantoj registrations: + moderation_recommandation: Bonvolu certigi, ke vi havas taŭgan kaj reaktivan moderigan teamon antaŭ ol vi malfermas registriĝojn al ĉiuj! preamble: Regi kiu povas krei konton ĉe via servilo. title: Registriĝoj registrations_mode: @@ -759,6 +777,7 @@ eo: open: Iu povas aliĝi security: authorized_fetch: Devigi aŭtentigon de frataraj serviloj + authorized_fetch_overridden_hint: Vi nuntempe ne povas ŝanĝi ĉi tiun agordon ĉar ĝi estas anstataŭita de mediovariablo. title: Agordoj de la servilo site_uploads: delete: Forigi elŝutitan dosieron @@ -772,6 +791,7 @@ eo: types: major: Ĉefa eldono minor: Neĉefa eldono + patch: Eldono de flikaĵo — korektoj de eraroj kaj facile apliki ŝanĝojn version: Versio statuses: account: Skribanto @@ -828,9 +848,11 @@ eo: 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: @@ -841,10 +863,17 @@ eo: message_html: "Via objektostokado estas misagordita. La privateco de viaj uzantoj estas en risko." tags: moderation: + not_usable: Ne uzebla + review_requested: Revizio petita + reviewed: Reviziita title: Stato + unreviewed: Nereviziita + usable: Uzebla name: Nomo newest: Plej novaj oldest: Plej malnovaj + open: Vidu publike + reset: Restartigi review: La statuso de la recenzo search: Serĉi title: Kradvortoj @@ -860,7 +889,9 @@ eo: 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 @@ -918,6 +949,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 @@ -957,6 +989,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}) @@ -966,6 +1000,7 @@ eo: 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: @@ -1013,8 +1048,10 @@ 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: + awaiting_review_title: Via registriĝo estas reviziita clicking_this_link: alklakante ĉi tiun ligilon login_link: ensaluti registration_complete: Via registriĝo sur %{domain} nun finiĝis! @@ -1063,6 +1100,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. @@ -1072,6 +1110,7 @@ eo: title: Ni pretigu vin ĉe %{domain}. status: account_status: Statuso de la konto + confirming: Atendante ke retpoŝta konfirmo estos kompletigita. functional: Via konto estas tute funkcia. redirecting_to: Via konto estas neaktiva ĉar ĝi nun alidirektas al %{acct}. view_strikes: Vidi antauaj admonoj kontra via konto @@ -1079,8 +1118,11 @@ eo: use_security_key: Uzi sekurecan ŝlosilon author_attribution: example_title: Ekzempla teksto + hint_html: Ĉu vi skribas novaĵojn aŭ blogartikolojn ekster Mastodon? Kontrolu kiel vi estas kreditita kiam ili estas kunhavataj ĉe Mastodon. + instructions: 'Certigu, ke ĉi tiu kodo estas en la HTML de via artikolo:' more_from_html: Pli de %{name} s_blog: Blogo de %{name} + then_instructions: Poste, aldonu la domajnan nomon de la publikigado en la suba kampo. title: Atribuo de aŭtoro challenge: confirm: Daŭrigi @@ -1118,6 +1160,8 @@ eo: before: 'Antau ol dauri, legu ĉi tiujn notojn zorgeme:' caches: Enhavo kiu kaŝmemorigitas de aliaj serviloj eble restas data_removal: Viaj afiŝoj kaj aliaj informoj estos forigita por eterne + email_change_html: Vi povas ŝanĝi vian retadreson sen forigi vian konton + email_contact_html: Se ĝi ankoraŭ ne alvenas, vi povas retpoŝti al %{email} por helpo irreversible: Vi ne povas regajni au reaktivigi vian konton more_details_html: Por pli da detaloj, vidi la privatecan politikon. username_available: Via uzantnomo iĝos denove disponebla @@ -1281,6 +1325,7 @@ eo: states: finished: Finita in_progress: Farata + scheduled: Planitaj unconfirmed: Nekonfirmita status: Stato success: Viaj datumoj estis sukcese alŝutitaj kaj estos traktitaj kiel planite @@ -1476,6 +1521,9 @@ 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. + title: Vi foriras %{instance}. relationships: activity: Konta aktiveco confirm_follow_selected_followers: Ĉu vi certas ke vi volas sekvi la elektitajn sekvantojn? @@ -1570,10 +1618,12 @@ eo: delete: Konta forigo development: Evoluigado edit_profile: Redakti profilon + 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 @@ -1582,6 +1632,9 @@ eo: 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: @@ -1666,6 +1719,7 @@ eo: contrast: Mastodon (Forta kontrasto) default: Mastodon (Malhela) mastodon-light: Mastodon (Hela) + system: Aŭtomata (uzu sisteman temon) time: formats: default: "%Y.%b.%d, %H:%M" @@ -1704,6 +1758,10 @@ eo: extra: Estas nun preta por elŝuto! subject: Via arkivo estas preta por elŝutado title: Arkiva elŝuto + failed_2fa: + explanation: Iu provis ensaluti al via konto sed provizis nevalidan duan aŭtentikigfaktoron. + further_actions_html: Se ĉi tio ne estis vi, ni rekomendas ke vi %{action} tuj ĉar ĝi povas esti endanĝerigita. + subject: Malsukceso dum la dua aŭtentikigfaktoro suspicious_sign_in: change_password: ŝanĝi vian pasvorton details: 'Ĉi-sube estas detaloj pri la saluto:' @@ -1743,6 +1801,8 @@ eo: silence: Konto limigita suspend: Konto suspendita welcome: + apps_android_action: Akiru ĝin ĉe Google Play + apps_ios_action: Elŝutu ĉe la App Store apps_step: Elŝutu niajn oficialajn aplikaĵojn. apps_title: Aplikaĵoj de Mastodon edit_profile_action: Agordi @@ -1750,11 +1810,22 @@ eo: explanation: Jen kelkaj konsiloj por helpi vin komenci feature_action: Lerni pli follow_action: Sekvi + follow_step: Sekvi interesajn homojn estas pri kio Mastodon temas. + follows_subtitle: Sekvu konatajn kontojn + follows_title: Kiun sekvi + follows_view_more: Rigardu pli da homoj por sekvi + hashtags_recent_count: + one: "%{people} homo en la pasintaj 2 tagoj" + other: "%{people} homoj en la pasintaj 2 tagoj" + hashtags_subtitle: Esploru kio estas tendenco ekde 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}! @@ -1772,6 +1843,7 @@ eo: instructions_html: Kopiu kaj algluu la jenan kodon en la HTML de via retejo. Poste aldonu la adreson de via retejo en unu el la kromaj kampoj de via profilo en la langeto "Redakti profilon" kaj konservu la ŝanĝojn. verification: Kontrolo verified_links: Via kontrolitaj ligiloj + website_verification: Reteja konfirmo webauthn_credentials: add: Aldoni novan sekurecan ŝlosilon create: diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index 04ff7880a1..79bfdfbdbf 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -1166,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: "¿Escribís artículos de noticias o de blog fuera de Mastodon? Controlá cómo se te acredita cuando se comparten en Mastodon." + instructions: 'Asegurate 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: Luego, agregá el nombre de dominio de la publicación en el campo de abajo. title: Atribución del autor challenge: confirm: Continuar diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 2c18465a26..fef805680a 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -241,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}" @@ -251,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}" @@ -263,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}" @@ -274,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" @@ -605,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 @@ -802,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 @@ -1166,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 @@ -1557,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: @@ -1771,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 @@ -1787,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 @@ -1814,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 @@ -1922,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 47d32c62c8..8690c1cdfb 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1166,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 diff --git a/config/locales/et.yml b/config/locales/et.yml index 4372a92843..3be9add91c 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,9 +1166,11 @@ et: use_security_key: Kasuta turvavõtit author_attribution: example_title: Näidistekst - hint_html: Määra, kuidas sind krediteeritakse, kui linke Mastodonis jagatakse. + hint_html: Kirjutad uudiseid või blogisid Mastodonist väljapool? Määra, kuidas sinule viidatakse, kui neid lehti jagatakse Mastodonis. + instructions: 'Vaata, et artikli HTML sisus oleks see kood sees:' more_from_html: Rohkem kasutajalt %{name} s_blog: Kasutaja %{name} blogi + then_instructions: Siis lisa avaldaja domeeninimi allolevasse välja. title: Autori tunnustamine challenge: confirm: Jätka @@ -1362,6 +1368,44 @@ et: merge_long: Hoia olemasolevad andmed ja lisa uusi overwrite: Kirjuta üle overwrite_long: Vaheta praegused andmed uute vastu + overwrite_preambles: + 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: + 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: @@ -1678,6 +1722,7 @@ et: delete: Konto kustutamine development: Arendus edit_profile: Muuda profiili + export: Eksport featured_tags: Esile toodud sildid import: Impordi import_and_export: Import / eksport diff --git a/config/locales/fa.yml b/config/locales/fa.yml index e7d932de11..603cfe8de1 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -190,9 +190,11 @@ fa: create_user_role: ایجاد نقش demote_user: تنزل کاربر destroy_announcement: حذف اعلامیه + destroy_canonical_email_block: حذف انسداد رایانامه destroy_custom_emoji: حذف اموجی سفارشی destroy_domain_allow: حذف اجازهٔ دامنه destroy_domain_block: حذف انسداد دامنه + destroy_email_domain_block: حذف انسداد دامنهٔ رایانامه destroy_instance: پاکسازی دامنه destroy_ip_block: حذف قاعدهٔ آی‌پی destroy_status: حذف وضعیت @@ -200,8 +202,10 @@ fa: destroy_user_role: نابودی نقش disable_2fa_user: از کار انداختن ورود دومرحله‌ای disable_custom_emoji: از کار انداختن اموجی سفارشی + disable_sign_in_token_auth_user: از کار انداختن تأیید هویت ژتون رایانامه‌ای برای کاربر disable_user: از کار انداختن کاربر enable_custom_emoji: به کار انداختن اموجی سفارشی + enable_sign_in_token_auth_user: به کار انداختن تأیید هویت ژتون رایانامه‌ای برای کاربر enable_user: به کار انداختن کاربر memorialize_account: یادسپاری حساب promote_user: ترفیع کاربر @@ -231,20 +235,26 @@ fa: approve_appeal_html: "%{name} درخواست تجدیدنظر تصمیم مدیر را از %{target} پذیرفت" approve_user_html: "%{name} ثبت نام %{target} را تایید کرد" assigned_to_self_report_html: "%{name} رسیدگی به گزارش %{target} را به عهده گرفت" + change_email_user_html: "%{name} نشانی رایانامهٔ کاربر %{target} را عوض کرد" change_role_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_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_ip_block_html: "%{name} برای آی‌پی %{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_custom_emoji_html: "%{name} شکلک %{target} را حذف کرد" destroy_domain_allow_html: "%{name} دامنهٔ %{target} را از فهرست مجاز برداشت" destroy_domain_block_html: "%{name} انسداد دامنهٔ %{target} را رفع کرد" + destroy_email_domain_block_html: "%{name} انسداد دامنهٔ رایانامهٔ %{target} را برداشت" destroy_instance_html: "%{name} دامنه %{target} را پاکسازی کرد" destroy_ip_block_html: "%{name} قاعدهٔ آی‌پی %{target} را حذف کرد" destroy_status_html: "%{name} وضعیت %{target} را برداشت" @@ -252,8 +262,10 @@ fa: destroy_user_role_html: "%{name} نقش %{target} را حذف کرد" disable_2fa_user_html: "%{name} ضرورت ورود دو مرحله‌ای را برای کاربر %{target} غیر فعال کرد" disable_custom_emoji_html: "%{name} شکلک %{target} را غیرفعال کرد" + disable_sign_in_token_auth_user_html: "%{name}، احراز هویت با توکن رایانامه را برای %{target} غیرفعال کرد" disable_user_html: "%{name} ورود را برای کاربر %{target} غیرفعال کرد" enable_custom_emoji_html: "%{name} شکلک %{target} را فعال کرد" + enable_sign_in_token_auth_user_html: "%{name}، احراز هویت با توکن رایانامه را برای %{target} فعال کرد" enable_user_html: "%{name} ورود را برای کاربر %{target} فعال کرد" memorialize_account_html: "%{name} حساب %{target} را تبدیل به صفحهٔ یادمان کرد" promote_user_html: "%{name} کاربر %{target} را ترفیع داد" @@ -478,6 +490,7 @@ fa: instance_followers_measure: پی‌گیرندگانمان در آن‌جا instance_follows_measure: پی‌گیرندگانشان در این‌جا instance_languages_dimension: زبان‌های برتر + instance_media_attachments_measure: پیوست‌های رسانه‌ای ذخیره شده instance_reports_measure: گزارش‌ها درباره‌شان instance_statuses_measure: فرسته‌های ذخیره شده delivery: @@ -565,6 +578,9 @@ fa: other_description_html: دیدن انتخاب های بیشتر برای کنترل رفتار حساب و سفارشی سازی ارتباط با حساب گزارش شده. resolve_description_html: هیچ کنشی علیه حساب گزارش شده انجام نخواهد شد. هیچ شکایتی ضبط نشده و گزارش بسته خواهد شد. add_to_report: افزودن بیش‌تر به گزارش + already_suspended_badges: + local: از پیش روی این کارساز معلّق شده + remote: از پیش روی کارسازشان معلّق شده are_you_sure: مطمئنید؟ assign_to_self: به عهدهٔ من بگذار assigned: مدیر عهده‌دار @@ -574,6 +590,7 @@ fa: comment: none: هیچ confirm: تأیید + confirm_action: تأیید کنش مدیریتی برای ‪@%{acct}‬ created_at: گزارش‌شده delete_and_resolve: حذف فرسته‌ها forwarded: هدایت شده @@ -594,6 +611,7 @@ fa: report: 'گزارش #%{id}' reported_account: حساب گزارش‌شده reported_by: گزارش از طرف + reported_with_application: گزارش شده با برنامه resolved: حل‌شده resolved_msg: گزارش با موفقیت حل شد! skip_to_actions: پرش به کنش‌ها @@ -665,6 +683,8 @@ fa: title: ظاهر branding: title: ویژندگی + content_retention: + danger_zone: منطقهٔ خطر default_noindex: title: درخواست خروج از اندیس‌گذاری پیش‌گزیدهٔ موتور جست‌وجو discovery: @@ -752,6 +772,9 @@ fa: message_html: هیچ قانون کارسازی تعریف نکرده‌اید. sidekiq_process_check: message_html: صف(های) %{value} فاقد هیچونه فرایند Sidekiq هستند. لطفا تنظیمات Sidekiq خود را بازبینی کنید + software_version_check: + action: دیدن به‌روز رسانی‌های موجود + message_html: به‌روز رسانی ماستودون موجود است. software_version_critical_check: action: مشاهده به‌روزرسانی‌های موجود message_html: یک به‌روزرسانی حیاتی ماستودون موجود است، لطفا در اسرع وقت به‌روزرسانی کنید. @@ -775,16 +798,27 @@ fa: trendable: قابل داغ شدن unreviewed: بررسی نشده usable: قابل استفاده + name: نام + newest: جدیدترین + oldest: قدیمی‌ترین + open: دیدن عمومی + reset: بازنشانی review: وضعیت بازبینی + search: جست‌وجو + title: برچسب‌ها updated_msg: تنظیمات برچسب‌ها با موفقیت به‌روز شد title: مدیریت trends: allow: اجازه approved: تأیید شده + confirm_allow: مطمئنید که می‌خواهید برچسب‌های گزیده را مجاز کنید؟ + confirm_disallow: مطمئنید که می‌خواهید برچسب‌های گزیده را ممنوع کنید؟ disallow: اجازه ندادن links: allow: اجازه به پیوند allow_provider: اجازه به ناشر + confirm_allow: مطمئنید که می‌خواهید پیوندهای گزیده را مجاز کنید؟ + confirm_allow_provider: مطمئنید که می‌خواهید فراهم‌کننده‌های گزیده را مجاز کنید؟ confirm_disallow: مطمئنید که می خواهید پیوندهای گزیده را ممنوع کنید؟ confirm_disallow_provider: مطمئنید که می خواهید فراهم کننده‌های گزیده را ممنوع کنید؟ disallow: اجازه ندادن به پیوند @@ -792,18 +826,32 @@ fa: no_link_selected: هیچ پیوندی تغییر نکرد زیرا هیچ‌کدام از آن‌ها انتخاب نشده بودند publishers: no_publisher_selected: هیچ ناشری تغییر نکرد زیرا هیچ‌کدام از آن‌ها انتخاب نشده بودند + shared_by_over_week: + one: هم‌رسانده به دست یک نفر در هفتهٔ گذشته + other: هم‌رسانده به دست %{count} نفر در هفتهٔ گذشته title: پیوندهای داغ + usage_comparison: امروز %{today} بار هم‌رسانی شده. در مقایسه با %{yesterday} بار دیروز not_allowed_to_trend: اجازهٔ داغ شدن ندارد + only_allowed: فقط مجازها pending_review: بازبینی منتظر preview_card_providers: + allowed: پیوندها از این ناشر می‌توانند داغ شوند + rejected: پیوندها از این ناشر داغ نخواهند شد title: ناشران rejected: رد شده statuses: allow: اجازه به فرسته allow_account: اجازه به نگارنده + confirm_allow: مطمئنید که می‌خواهید وضعیت‌های گزیده را مجاز کنید؟ + confirm_allow_account: مطمئنید که می‌خواهید حساب‌های گزیده را مجاز کنید؟ + confirm_disallow: مطمئنید که می‌خواهید وضعیت‌های گزیده را ممنوع کنید؟ + confirm_disallow_account: مطمئنید که می‌خواهید حساب‌های گزیده را ممنوع کنید؟ disallow: ممنوع کردن فرسته disallow_account: ممنوع کردن نگارنده no_status_selected: هیچ فرستهٔ داغی تغییری نکرد زیرا هیچ‌کدام از آن‌ها انتخاب نشده بودند + shared_by: + one: یک بار برگزیده یا هم‌رسانی شده + other: "%{friendly_count} بار برگزیده یا هم‌رسانی شده" title: فرسته‌های داغ tags: current_score: امتیاز کنونی %{score} @@ -812,8 +860,9 @@ fa: tag_languages_dimension: زبان‌های برتر tag_servers_dimension: کارسازهای برتر tag_servers_measure: کارسازهای گوناگون - tag_uses_measure: کل استفاده‌ّا + tag_uses_measure: کل استفاده‌ها listable: می‌تواند پیشنهاد شود + no_tag_selected: هیچ برچسبی تغییر نکرد زیرا هیچ‌کدام گزیده نبودند not_listable: پیشنهاد نخواهد شد not_usable: غیر قابل استفاده title: برچسب‌های پرطرفدار @@ -908,7 +957,9 @@ fa: title: بررسی های امنیتی confirmations: awaiting_review_title: ثبت‌نامتان دارد بررسی می‌شود + clicking_this_link: زدن این پیوند login_link: ورود + proceed_to_login_html: می‌توانید به %{login_link} ادامه دهید. welcome_title: خوش آمدید، %{name}! delete_account: پاک‌کردن حساب delete_account_html: اگر می‌خواهید حساب خود را پاک کنید، از این‌جا پیش بروید. از شما درخواست تأیید خواهد شد. @@ -930,6 +981,7 @@ fa: or_log_in_with: یا ورود به وسیلهٔ privacy_policy_agreement_html: سیاست محرمانگی را خوانده و پذیرفته‌ام progress: + confirm: تأیید رایانامه details: جزئیات شما review: بررسی ما rules: پذیرش قوانین @@ -943,6 +995,7 @@ fa: rules: accept: پذیرفتن back: بازگشت + invited_by: 'با سپاس از دعوتی از این فرد دریافت کرده‌اید می‌توانید به %{domain} بپیوندید:' title_invited: شما دعوت شده اید. security: امنیت set_new_password: تعین گذرواژه جدید @@ -952,17 +1005,24 @@ fa: title: صندوق ورودیتان را بررسی کنید sign_in: title: ورود به %{domain} + sign_up: + title: بیایید روی %{domain} برپایتان کنیم. status: account_status: وضعیت حساب + confirming: منتظر کامل شدن تأیید رایانامه. functional: حسابتان کاملاً قابل استفاده است. + pending: درخواستتان منتظر بازبینی مسئولان است. ممکن است کمی طول بکشد. اگر درخواستتان پذیرفته شود رایانامه‌ای خواهید گرفت. redirecting_to: حساب شما غیرفعال است زیرا هم‌اکنون به %{acct} منتقل شده است. view_strikes: دیدن شکایت‌های گذشته از حسابتان too_fast: فرم با سرعت بسیار زیادی فرستاده شد، دوباره تلاش کنید. use_security_key: استفاده از کلید امنیتی author_attribution: example_title: متن نمونه + instructions: 'مطمئن شوید این کد در HTML مقاله‌تان وجود دارد:' more_from_html: بیش‌تر از %{name} s_blog: بلاگ %{name} + then_instructions: سپس نام دامنهٔ مقاله را در زمینهٔ زیر بیفزایید. + title: اعتباردهی به نگارنده challenge: confirm: ادامه hint_html: "نکته: ما در یک ساعت آینده گذرواژه‌تان را از شما نخواهیم پرسید." @@ -999,6 +1059,9 @@ fa: before: 'پیش از ادامه،‌ لطفاً نکته‌های زیر را به دقت بخوانید:' caches: ممکن است محتواهایی که دیگر کارسازها ذخیره کرده‌اند، همچنان باقی بماند data_removal: نوشته‌ها و داده‌های شما برای همیشه پاک خواهند شد + email_change_html: می‌توانید بدون حذف حسابتان نشانی رایانامه‌تان را تغییر دهید + email_contact_html: اگر هنوز نرسیده، می‌توانید برای راهنمایی به %{email} رایانامه دهید + email_reconfirmation_html: اگر رایانامهٔ تأیید را نگرفته‌اید، می‌توانید دوباره درخواستش دهید irreversible: شما نخواهید توانست حساب خود را بازیابی یا فعال‌سازی کنید more_details_html: برای اطلاعات بیشتر سیاست رازداری را ببینید. username_available: نام کاربری شما دوباره در دسترس خواهد بود @@ -1091,8 +1154,10 @@ fa: deprecated_api_multiple_keywords: این پارامترها نمی‌توانند از این برنامه تغییر یابند؛ چرا که به بیش از یک کلیدواژهٔ پالایه اعمال می‌شود. از برنامه‌ای جدیدتر یا میانای وب استفاده کنید. invalid_context: زمینه‌ای موجود نیست یا نامعتبر است index: + contexts: پالایه‌ها در %{contexts} delete: پاک‌کردن empty: هیچ پالایه‌ای ندارید. + expires_in: در %{distance} منقضی می شود expires_on: در %{date} منقضی می شود keywords: one: "%{count} کلیدواژه" @@ -1115,6 +1180,9 @@ fa: title: فرسته‌های پالوده generic: all: همه + all_items_on_page_selected_html: + one: "%{count} مورد در این صفحه گزیده شده." + other: همهٔ %{count} مورد این صفحه گزیده شده‌اند. all_matching_items_selected_html: one: "%{count} مورد مطابق با جست‌وجویتان گزیده شده." other: "%{count} مورد مطابق با جست‌وجویتان گزیده شدند." @@ -1136,6 +1204,9 @@ fa: other: یک چیزی هنوز درست نیست! لطفاً %{count} خطای زیر را ببینید imports: errors: + empty: پروندهٔ خالی CSV + incompatible_type: ناسازگار با گونهٔ درون‌ریزی گزیده + invalid_csv_file: 'پروندهٔ CSV نامعتبر. خطا: %{error}' over_rows_processing_limit: دارای بیش از %{count} ردیف too_large: حجم فایل خیلی بزرگ است failures: شکست‌ها @@ -1213,7 +1284,15 @@ fa: title: تاریخچهٔ تأیید هویت mail_subscriptions: unsubscribe: + action: بله. لغو اشتراک complete: لغو اشتراک شد + emails: + notification_emails: + favourite: رایانامه‌های آگاهی برگزیدن + follow: رایانامه‌های آگاهی پی‌گیری + follow_request: رایانامه‌های درخواست پی‌گیری + mention: رایانامه‌های آگاهی اشاره + reblog: رایانامه‌های آگاهی تقویت title: لغو اشتراک media_attachments: validations: @@ -1294,6 +1373,8 @@ fa: update: subject: "%{name} فرسته‌ای را ویرایست" notifications: + administration_emails: آگاهی‌های رایانامه‌ای مدیر + email_events: رویدادها برای آگاهی‌های رایانامه‌ای email_events_hint: 'گزینش رویدادهایی که می‌خواهید برایشان آگاهی دریافت کنید:' number: human: @@ -1338,6 +1419,7 @@ fa: privacy: hint_html: "شخصی‌سازی چگونگی پیدا شدن فرسته‌ها و نمایه‌تان. ویژگی‌های متعدّدی در ماستودون می‌توانند هنگام به کار افتادن در رسیدن به مخاطبینی گسترده‌تر یاریتان کنند. کمی وقت برای بازبینی این تنظیمات گذاشته تا مطمئن شوید برایتان مناسبند." privacy: محرمانگی + privacy_hint_html: واپایش میزان باز شدن به نفع دیگران. افراد نمایه‌های جالب و کاره‌های باحال را با مرور پی‌گرفتگان دیگران و دیدن کاره‌هایی که از آن‌ها می‌فرستند پیدا می‌کنند. با این حال شاید بخواهید پنهان نگهشان دارید. reach: دسترسی reach_hint_html: واپایش این که می‌خواهید به دست افراد جدید قابل کشف و پی‌گیری باشید یا نه. می‌خواهید فرسته‌هایتان روی صفحهٔ کشف ظاهر شوند؟ می‌خواهید دیگر افراد در پیشنهادهای پی‌گیریشان ببینندتان؟ می‌خواهید پی‌گیران جدید را به طور خودکار بپذیرید یا روی هرکدامشان واپایش داشته باشید؟ search: جست‌وجو @@ -1349,12 +1431,16 @@ fa: errors: limit_reached: تجاوز از کران واکنش‌های مختلف unrecognized_emoji: شکلک شناخته‌شده‌ای نیست + redirects: + prompt: اگر به این پویند اطمینان دارید برای ادامه بزنید. + title: دارید %{instance} را ترک می‌کنید. relationships: activity: فعالیت حساب confirm_follow_selected_followers: آیا مطمئنید که می خواهید دنبال کننده های انتخابی را دنبال کنید؟ confirm_remove_selected_followers: آیا شما واقعا می خواهید دنبال کننده های انتخابی را حذف کنید؟ confirm_remove_selected_follows: آیا شما واقعا می خواهید دنبال شده های انتخابی را حذف کنید؟ dormant: غیرفعال + follow_failure: نتوانست برخی از حساب‌های گزیده را پی بگیرد. follow_selected_followers: پیگیری پیگیران انتخاب شده followers: پی‌گیران following: پی می‌گیرد @@ -1438,6 +1524,7 @@ fa: delete: پاک‌کردن حساب development: فرابری edit_profile: ویرایش نمایه + export: برون‌ریزی featured_tags: برچسب‌های برگزیده import: درون‌ریزی import_and_export: درون‌ریزی و برون‌بری @@ -1446,12 +1533,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: @@ -1535,6 +1631,7 @@ fa: contrast: ماستودون (سایه‌روشن بالا) default: ماستودون (تیره) mastodon-light: ماستودون (روشن) + system: خودکار (استفاده از زمینهٔ سامانه) time: formats: default: "%d %b %Y, %H:%M" @@ -1557,16 +1654,23 @@ fa: webauthn: کلیدهای امنیتی user_mailer: appeal_approved: + action: تنظیمات حساب explanation: درخواست تجدیدنظر اخطار علیه حساب شما در %{strike_date} که در %{appeal_date} ارسال کرده‌اید، پذیرفته شده است. حساب شما بار دیگر در وضعیت خوبی قرار دارد. subject: درخواست تجدیدنظر شما در %{date} پذیرفته شد + subtitle: حسابتان دوباره در وضعیت مناسب است. title: درخواست تجدیدنظر پذیرفته شد appeal_rejected: explanation: درخواست تجدیدنظر اخطار علیه حساب شما در %{strike_date} که در %{appeal_date} ارسال کرده‌اید، رد شده است. subject: درخواست تجدیدنظر شما در %{date} رد شده است + subtitle: درخواست تجدیدنظرتان رد شد. title: درخواست تجدیدنظر رد شد backup_ready: + explanation: درخواست پشتیبانی کامل از حساب ماستودونتان کردید. + extra: اکنون آمادهٔ بارگیری است! subject: بایگانی شما آمادهٔ دریافت است title: گرفتن بایگانی + failed_2fa: + details: 'جزییات تلاش‌ها برای ورد:' suspicious_sign_in: change_password: تغییر گذرواژه‌تان details: 'جزییات ورود:' @@ -1578,8 +1682,11 @@ fa: spam: هرزنامه reason: 'دلیل:' subject: + delete_statuses: فرسته‌هایتان روی %{acct} برداشته شده‌اند disable: حساب %{acct} شما متوقف شده است + mark_statuses_as_sensitive: فرسته‌هایتان روی %{acct} به عنوان حسّاس علامت خورده‌اند none: هشدار برای %{acct} + sensitive: فرسته‌هایتان روی %{acct} از اکنون به عنوان حسّاس علامت خواهند خورد silence: حساب %{acct} شما محدود شده است suspend: حساب %{acct} شما معلق شده است title: @@ -1595,11 +1702,39 @@ fa: apps_ios_action: بارگیری روی فروشگاه کاره apps_step: بارگیری کارهٔ رسمیمان. apps_title: کاره‌های ماستودون + checklist_subtitle: 'بیایید روی این مرز اجتماعی جدید راهتان بیندازیم:' + checklist_title: سیاههٔ بررسی خوش‌آمد edit_profile_action: شخصی سازی + edit_profile_step: تقویت تعامل‌هایتان با داشتن نمایه‌ای جامع. + edit_profile_title: شخصی سازی نمایه‌تان explanation: نکته‌هایی که برای آغاز کار به شما کمک می‌کنند + feature_action: دانشتن بیش‌تر + feature_audience: ماستودون بدون حضور فرد میانی، فرصتی منحصربه‌فرد برای مدیریت مخاطبان ارائه می‌کند. ماستودونی که روی زیرساخت خودتان استقرار یافته باشد، می‌گذارد بدون بودن زیر واپایش کسی غیر از خودتان، دیگر کارسازهای برخط ماستودون را دنبال کرده و به دست آن‌ها دنبال شوید. + feature_audience_title: مخاطبان‌تان را با اطمینان بسازید + feature_control: شما بهتر از هر کسی دیگری می‌دونید که چه می‌خواهید ببینید. هیچ الگوریتم یا تبلیغی وقت شما را تلف نمی‌کند. تنها با یک حساب، هر کسی را روی هر کارساز ماستودون دیگری دنبال کرده و فرسته‌هایشان را به ترتیب زمانی دریافت کنید. گوشهٔ دنج اینترنتی خودتان را بیشتر شبیه خودتان کنید. + feature_control_title: کنترل خط زمانی‌تان را به دست بگیرید + feature_creativity: ماستودون از فرسته‌های تصویری، ویدئویی و شنیداری، توضیحات دسترس‌پذیری، نظرسنجی، هشدار محتوا، تصاویر نمایهٔ پویا، شکلک‌های سفارشی، کنترل برش تصاویر بندانگشتی و بسیاری موارد دیگر پشتیبانی می‌کند تا به شما برای ابزار کردن خود در فضای برخط کمک کند. چه بخواهید یک اثر هنری، موسیقی یا پادکست منتشر کنید، ماستودون در خدمت شماست. + feature_creativity_title: خلاقیت بی‌همتا + feature_moderation: ماستودن، تصمیم‌گیری را به شما باز می‌گرداند. هر کارساز قوانین و شرایط استفاده خاص خودش را وضع می‌کند که فقط به صورت محلی اعمال می‌شود و نه به صورت از بالا به پایین در سکوهای اجتماعی شرکتی. این موضوع باعث افزایش انعطاف در پاسخ‌گویی به نیازهای گروه‌های مختلف می‌شود. به کارسازی با قوانین مورد پسندتان بپیوندید، و یا نمونه خود را میزبانی کنید. + feature_moderation_title: نظارت به شکلی که باید باشد follow_action: پی‌گیری + follow_step: You curate your own feed. Lets fill it with interesting people. + follow_title: شخصی سازی خوراک خانگیتان + follows_subtitle: پی گرفتن حساب‌های شناخته شده + follows_title: افرادی برای پی‌گیری + follows_view_more: دیدن افرادی بیش‌تر برای پی‌گیری + hashtags_recent_count: + one: "%{people} نفر در ۲ روز اخیر" + other: "%{people} نفر در ۲ روز اخیر" + hashtags_subtitle: کشف گرایه‌ها در ۲ روز گذشته + hashtags_title: برچسب‌های داغ + hashtags_view_more: دیدن برچسب‌های داغ بیش‌تر post_action: ایجاد + post_step: سلام کردن به جهان با متن، عکس، ویدیو یا نظرسنجی. + post_title: ساخت نخستین نظرسنجیتان share_action: هم‌رسانی + share_step: بگذارید دوستانتان بدانند چگونه روی ماستودون بیابندتان. + share_title: هم‌رسانی نمایهٔ ماستودونتان sign_in_action: ورود subject: به ماستودون خوش آمدید title: خوش آمدید، کاربر %{name}! @@ -1608,6 +1743,8 @@ fa: go_to_sso_account_settings: به تنظیمات حساب فراهمگر هوبتتان بروید invalid_otp_token: کد ورود دومرحله‌ای نامعتبر است otp_lost_help_html: اگر شما دسترسی به هیچ‌کدامشان ندارید، باید با ایمیل %{email} تماس بگیرید + rate_limited: تلاش ّای هویت‌سنجی بیش از حد. لطفاً بعداً دوباره تلاش کنید. + seamless_external_login: با خدمتی خارجی وارد شده‌اید، برای همین تنظیمات رایانامه و گذرواژه در دسترس نیستند. signed_in_as: 'واردشده به نام:' verification: extra_instructions_html: نکته: پیوند روی پایگاه وبتان می‌تواند نامرئی باشد. بخش مهم rel="me" است که از جعل هویت روی پایگاه‌هایی با محتوای تولید شده به دست کاربر جلوگیری می‌کند. حتا می‌توانید به جای برچسب a از برچسب link در سرایند صفحه استفاده کنید؛ ولی HTML باید بدون اجرای جاوااسکریپت در دسترس باشد. @@ -1616,6 +1753,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 52ea0b374c..2f9a76c80d 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -1166,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 @@ -1965,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 fcf3eb031e..1060ee1609 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -1166,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 á @@ -1366,6 +1368,44 @@ 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: + one: Tú ert í ferð við at útskifta blokeringslistan hjá tær við upp til %{count} kontu frá %{filename}. + other: Tú ert í ferð við at útskifta blokeringslistan hjá tær við upp til %{count} kontum frá %{filename}. + bookmarks_html: + one: Tú ert í ferð við at útskifta tíni bókamerki við upp til %{count} posti frá %{filename}. + other: Tú ert í ferð við at útskifta tíni bókamerki við upp til %{count} postum frá %{filename}. + domain_blocking_html: + one: Tú ert í ferð við at útskifta navnaøkisblokeringslistan hjá tær við upp til %{count} navnaøki frá %{filename}. + other: Tú ert í ferð við at útskifta navnaøkisblokeringslistan hjá tær við upp til %{count} navnaøkjum frá %{filename}. + following_html: + one: Tú ert í ferð við at fylgja upp til %{count} kontu frá %{filename} og at gevast at fylgja øðrum. + other: Tú ert í ferð við at fylgja upp til %{count} kontum frá %{filename} og at gevast at fylgja øðrum. + lists_html: + one: Tú ert í ferð við at skifta listarnar hjá tær út við tað, sum er í %{filename}. Upp til %{count} konta verður løgd afturat nýggjum listum. + other: Tú ert í ferð við at skifta listarnar hjá tær út við tað, sum er í %{filename}. Upp til %{count} kontur verða lagdar afturat nýggjum listum. + muting_html: + one: Tú ert í ferð við at útskifta listan hjá tær við doyvdum kontum við upp til %{count} kontu frá %{filename}. + other: Tú ert í ferð við at útskifta listan hjá tær við doyvdum kontum við upp til %{count} kontum frá %{filename}. + preambles: + blocking_html: + one: Tú ert í ferð við at blokera upp til %{count} kontu frá %{filename}. + other: Tú ert í ferð við at blokera upp til %{count} kontur frá %{filename}. + bookmarks_html: + one: Tú ert í ferð við at leggja upp til %{count} post frá %{filename} afturat tínum bókamerkjum. + other: Tú ert í ferð við at leggja upp til %{count} postar frá %{filename} afturat tínum bókamerkjum. + domain_blocking_html: + one: Tú ert í ferð við at blokera upp til %{count} navnaøki frá %{filename}. + other: Tú ert í ferð við at blokera upp til %{count} navnaøki frá %{filename}. + following_html: + one: Tú ert í ferð við at fylgja upp til %{count} kontu frá %{filename}. + other: Tú ert í ferð við at fylgja upp til %{count} kontur frá %{filename}. + lists_html: + one: Tú ert í ferð við at leggja upp til %{count} kontu frá %{filename} afturat tínum listum. Nýggir listar verða stovnaðir, um eingin listi er at leggja afturat. + other: Tú ert í ferð við at leggja upp til %{count} kontur frá %{filename} afturat tínum listum. Nýggir listar verða stovnaðir, um eingin listi er at leggja afturat. + muting_html: + one: Tú ert í ferð við at doyva upp til %{count} kontu frá %{filename}. + other: Tú ert í ferð við at doyva upp til %{count} 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: diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index 01463edacb..3c771d4c64 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 @@ -1168,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 @@ -1368,6 +1368,44 @@ fr-CA: merge_long: Garder les enregistrements existants et ajouter les nouveaux overwrite: Écraser overwrite_long: Remplacer les enregistrements actuels par les nouveaux + overwrite_preambles: + 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: + 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: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c3ce66c397..58fc63fc1b 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 @@ -1168,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 @@ -1368,6 +1368,44 @@ fr: merge_long: Garder les enregistrements existants et ajouter les nouveaux overwrite: Écraser overwrite_long: Remplacer les enregistrements actuels par les nouveaux + overwrite_preambles: + 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: + 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: diff --git a/config/locales/fy.yml b/config/locales/fy.yml index d63d2ac2aa..a6656f91b8 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -21,6 +21,7 @@ fy: one: Toot other: Berjochten posts_tab_heading: Berjochten + self_follow_error: It folgjen fan dyn eigen account is net tastien admin: account_actions: action: Aksje útfiere @@ -1165,9 +1166,11 @@ fy: use_security_key: Befeiligingskaai brûke author_attribution: example_title: Faorbyldtekst - hint_html: Bepaal hoe’t wy jo fermelde, wannear’t jo keppelingen op Mastodon dield wurde. + hint_html: Skriuwe jo nijs- of blogartikelen bûten Mastodon? Bepaal hoe’t jo oahelle wurde as dizze dield wurde op Mastodon. + instructions: 'Soargj derfoar dat dizze koade yn de HTML fan jo artikel sit:' more_from_html: Mear fan %{name} s_blog: Weblog fan %{name} + then_instructions: Foegje dernei de domeinnamme fan de publikaasje yn it ûndersteande fjild ta. title: Auteur-attribúsje challenge: confirm: Trochgean diff --git a/config/locales/ga.yml b/config/locales/ga.yml index a201b73325..5e5ecb238e 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 @@ -1219,9 +1220,11 @@ 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. + hint_html: An bhfuil tú ag scríobh altanna nuachta nó blag lasmuigh de Mastodon? Rialú conas a gheobhaidh tú creidmheas nuair a roinntear iad ar Mastodon. + instructions: 'Cinntigh go bhfuil an cód seo i HTML d''alt:' more_from_html: Tuilleadh ó %{name} s_blog: Blag %{name} + then_instructions: Ansin, cuir ainm fearainn an fhoilseacháin sa réimse thíos. title: Leithdháil an údair challenge: confirm: Lean ar aghaidh @@ -1440,6 +1443,80 @@ ga: merge_long: Coinnigh taifid atá ann cheana féin agus cuir cinn nua leis overwrite: Forscríobh overwrite_long: Cuir na cinn nua in ionad na dtaifead reatha + overwrite_preambles: + 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: + 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: diff --git a/config/locales/gd.yml b/config/locales/gd.yml index cb7c6254bc..c804f42523 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 @@ -261,7 +262,7 @@ gd: destroy_domain_allow_html: Dì-cheadaich %{name} co-nasgadh leis an àrainn %{target} destroy_domain_block_html: Dì-bhac %{name} an àrainn %{target} destroy_email_domain_block_html: Dì-bhac %{name} an àrainn puist-d %{target} - destroy_instance_html: Purgaidich %{name} an àrainn %{target} + destroy_instance_html: Phurgaidich %{name} an àrainn %{target} destroy_ip_block_html: Sguab %{name} às riaghailt dhan IP %{target} destroy_status_html: Thug %{name} post aig %{target} air falbh destroy_unavailable_domain_html: Lean %{name} air adhart leis an lìbhrigeadh dhan àrainn %{target} @@ -1201,9 +1202,11 @@ 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. + hint_html: An sgrìobh thu naidheachdan no bloga taobh a-muigh Mhastodon? Stiùirich mar a thèid iomradh a thoirt ort nuair a bhios na h-artaigilean agad ’gan co-roinneadh air Mastodon. + instructions: 'Dèan cinnteach gu bheil an còd seo am broinn HTML an artaigil agad:' more_from_html: Barrachd o %{name} s_blog: Bloga aig %{name} + then_instructions: An uair sin, cuir ainm àrainn an fhoillseachaidh ris an raon gu h-ìosal. title: Aithris air an ùghdar challenge: confirm: Lean air adhart @@ -1415,6 +1418,68 @@ gd: merge_long: Cùm na reacordan a tha ann is cuir feadhainn ùr ris overwrite: Sgrìobh thairis air overwrite_long: Cuir na reacordan ùra an àite na feadhna a tha ann + overwrite_preambles: + 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: + 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: diff --git a/config/locales/gl.yml b/config/locales/gl.yml index cdc9421324..a4f63a50e0 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1166,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 @@ -1785,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 54b6b6f38d..10b4611b9a 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1202,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: המשך diff --git a/config/locales/hu.yml b/config/locales/hu.yml index 15c632adc9..47bd24fccf 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 @@ -1165,9 +1166,11 @@ 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. + hint_html: Mastodonon kívül írsz híreket vagy blogbejegyzéseket? Szabályozd, hogyan tüntethetnek fel szerzőként, amikor Mastodonon osztják meg őket. + instructions: 'Győződj meg róla, hogy ez a kód a cikked HTML-jében van:' more_from_html: 'Több tőle: %{name}' s_blog: "%{name} blogja" + then_instructions: Aztán add meg a publikáció domain-nevét az alábbi mezőben. title: Szerző forrásmegjelölése challenge: confirm: Folytatás diff --git a/config/locales/ia.yml b/config/locales/ia.yml index 4d9148674d..843e8724b9 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." @@ -1346,6 +1365,44 @@ ia: merge_long: Conservar le registros existente e adder noves overwrite: Superscriber overwrite_long: Reimplaciar registros actual con le noves + overwrite_preambles: + 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: + 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: @@ -1430,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: @@ -1661,6 +1719,7 @@ ia: delete: Deletion de conto development: Disveloppamento edit_profile: Modificar profilo + export: Exportar featured_tags: Hashtags in evidentia import: Importar import_and_export: Importar e exportar diff --git a/config/locales/is.yml b/config/locales/is.yml index f181470e49..c50b3dd20d 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -1170,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 @@ -1370,6 +1372,44 @@ is: merge_long: Halda fyrirliggjandi færslum og bæta við nýjum overwrite: Skrifa yfir overwrite_long: Skipta út fyrirliggjandi færslum með þeim nýju + overwrite_preambles: + 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: + 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: diff --git a/config/locales/it.yml b/config/locales/it.yml index 91b67c2b4d..e18cb0e8f6 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 @@ -1167,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 diff --git a/config/locales/ja.yml b/config/locales/ja.yml index bda5b2d8f6..a70ae680e4 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -46,6 +46,7 @@ ja: title: "%{username}さんのメールアドレスを変更" change_role: changed_msg: ロールを変更しました! + edit_roles: ユーザーのロールを管理 label: ロールを変更 no_role: ロールがありません title: "%{username}さんのロールを変更" @@ -232,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}のブロックを外しました" @@ -270,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}さんのメディアを閲覧注意にマークしました" @@ -285,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: 削除されたアカウント @@ -861,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アップデートがあります。速やかに適用してください。 @@ -1144,7 +1148,12 @@ ja: use_security_key: セキュリティキーを使用 author_attribution: example_title: サンプルテキスト + hint_html: Mastodonの外でニュースやブログなどを執筆しているユーザーは、Mastodonで自分の記事が共有されたときに著者情報を表示させることができます。 + instructions: 以下のコードを自分の記事のHTMLに貼り付けます。 + more_from_html: "%{name} のその他の情報" s_blog: "%{name} のブログ" + then_instructions: その後、記事の公開に使用しているドメイン名を以下の入力欄に追加してください。 + title: 著者の帰属 challenge: confirm: 続ける hint_html: 以後1時間はパスワードの再入力を求めません @@ -1334,6 +1343,32 @@ ja: merge_long: 現在のレコードを保持したまま新しいものを追加します overwrite: 上書き overwrite_long: 現在のレコードを新しいもので置き換えます + overwrite_preambles: + 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: + 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/locales/ko.yml b/config/locales/ko.yml index 8b64ea2a03..5be3c6cfb2 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -193,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: 사용 불가능한 도메인 제거 @@ -526,7 +526,7 @@ ko: title: 중재 private_comment: 비공개 주석 public_comment: 공개 주석 - purge: 제거 + purge: 퍼지 purge_description_html: 이 도메인이 영구적으로 오프라인 상태라고 생각되면, 스토리지에서 이 도메인의 모든 계정 레코드와 관련 데이터를 삭제할 수 있습니다. 이 작업은 시간이 좀 걸릴 수 있습니다. title: 연합 total_blocked_by_us: 우리에게 차단 됨 @@ -1150,9 +1150,11 @@ ko: 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: 계속 @@ -1707,7 +1709,7 @@ ko: lost_followers: 잃은 팔로워 lost_follows: 잃은 팔로우 preamble: 내가 도메인을 차단하거나 중재진이 다른 서버를 정지하기로 결정했다면 내 팔로우와 팔로워를 잃게 됩니다. 그런 일이 일어났다면 그로 인해 단절된 관계들의 목록을 다운로드 받아 확인하고 다른 서버에서 불러올 수 있습니다. - purged: 이 서버에 대한 정보는 관리자에 의해 삭제되었습니다. + purged: 이 서버의 정보는 관리자가 퍼지하였습니다. type: 이벤트 statuses: attached: diff --git a/config/locales/lad.yml b/config/locales/lad.yml index 97fcf75180..ad241856a4 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. @@ -875,11 +883,14 @@ lad: 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 @@ -1118,6 +1129,7 @@ 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}. @@ -1638,6 +1650,7 @@ lad: delete: Efasa kuento development: Dezvelopamiento edit_profile: Edita profil + export: Eksporto featured_tags: Etiketas avaliadas import: Importo import_and_export: Importo i eksporto @@ -1876,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 3b63ba6dcf..8ba3bad070 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -817,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." diff --git a/config/locales/lv.yml b/config/locales/lv.yml index 5f90b575e7..9e95155110 100644 --- a/config/locales/lv.yml +++ b/config/locales/lv.yml @@ -23,16 +23,17 @@ 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 already_silenced: Šis konts jau ir ierobežots. already_suspended: Šis konts jau ir aizturēts. - title: Veikt moderācijas darbību %{acct} + title: Veikt satura pārraudzības darbību %{acct} account_moderation_notes: create: Atstāt piezīmi - created_msg: Moderācijas piezīme ir veiksmīgi izveidota! - destroyed_msg: Moderācijas piezīme ir veiksmīgi iznīcināta! + created_msg: Satura pārraudzības piezīme ir veiksmīgi izveidota. + destroyed_msg: Satura pārraudzības piezīme ir veiksmīgi iznīcināta. accounts: add_email_domain_block: Liegt e-pasta domēnu approve: Apstiprināt @@ -95,12 +96,12 @@ lv: moderation: active: Aktīvie all: Visi - disabled: Atspējots + disabled: Atspējota pending: Gaida - silenced: Ierobežotie - suspended: Apturētie - title: Moderācija - moderation_notes: Moderācijas piezīmes + silenced: Ierobežoti + suspended: Apturēti + title: Satura pārraudzība + moderation_notes: Satura pārraudzības piezīmes most_recent_activity: Pati pēdējā darbība most_recent_ip: Pati pēdējā IP no_account_selected: Neviens konts netika mainīts, jo neviens netika atlasīts @@ -205,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 @@ -233,7 +236,7 @@ lv: update_status: Atjaunināt ziņu update_user_role: Atjaunināt lomu actions: - approve_appeal_html: "%{name} apstiprināja moderācijas lēmuma apelāciju no %{target}" + approve_appeal_html: "%{name} apstiprināja satura pārraudzības lēmuma iebildumu no %{target}" approve_user_html: "%{name} apstiprināja reģistrēšanos no %{target}" assigned_to_self_report_html: "%{name} piešķīra pārskatu %{target} sev" change_email_user_html: "%{name} nomainīja lietotāja %{target} e-pasta adresi" @@ -264,7 +267,7 @@ lv: enable_user_html: "%{name} iespējoja pieteikšanos lietotājam %{target}" memorialize_account_html: "%{name} pārvērta %{target} kontu par atmiņas lapu" promote_user_html: "%{name} paaugstināja lietotāju %{target}" - reject_appeal_html: "%{name} noraidīja moderācijas lēmuma apelāciju no %{target}" + reject_appeal_html: "%{name} noraidīja satura pārraudzības lēmuma iebildumu no %{target}" reject_user_html: "%{name} noraidīja reģistrēšanos no %{target}" remove_avatar_user_html: "%{name} noņēma %{target} profila attēlu" reopen_report_html: "%{name} atkārtoti atvēra ziņojumu %{target}" @@ -359,9 +362,9 @@ lv: other: "%{count}ziņojumi gaida" zero: "%{count}ziņojumi gaida" pending_tags_html: - one: "%{count}tēmturis gaida" - other: "%{count}tēmturi gaida" - zero: "%{count}tēmturi gaida" + one: "%{count} tēmturis rindā" + other: "%{count} tēmturi rindā" + zero: "%{count} tēmturu rindā" pending_users_html: one: "%{count}lietotājs gaida" other: "%{count}lietotāji gaida" @@ -406,7 +409,7 @@ lv: import: Importēt new: create: Izveodot bloku - hint: Domēna bloķēšana netraucēs izveidot kontu ierakstus datu bāzē, bet ar atpakaļejošu datumu un automātiski tiks piemērotas noteiktas moderēšanas metodes šajos kontos. + hint: Domēna aizturēšana netraucēs izveidot kontu ierakstus datubāzē, bet šajos kontos ar atpakaļejošu datumu un automātiski tiks piemērotas noteikti satura pārraudzības veidi. severity: desc_html: "Ierobežojums padarīs ziņas no šī domēna kontiem neredzamas ikvienam, kas tiem neseko. Apturēšana no tava servera noņems visu šī domēna kontu saturu, multividi un profila datus. Izmanto Nav, ja vēlies vienkārši noraidīt multivides failus." noop: Neviens @@ -529,7 +532,7 @@ lv: moderation: all: Visas limited: Ierobežotās - title: Moderācija + title: Satura pārraudzība private_comment: Privāts komentārs public_comment: Publisks komentārs purge: Iztīrīt @@ -616,7 +619,7 @@ lv: none: Neviens comment_description_html: 'Lai sniegtu vairāk informācijas, %{name} rakstīja:' confirm: Apstiprināt - confirm_action: Apstipriniet regulēšanas darbību pret @%{acct} + confirm_action: Apstiprināt satura pārraudzības darbību pret @%{acct} created_at: Ziņoti delete_and_resolve: Izdzēst rakstus forwarded: Pārsūtīti @@ -664,7 +667,7 @@ lv: delete_data_html: Dzēsiet lietotāja @%{acct} profilu un saturu pēc 30 dienām, ja vien to darbība pa šo laiku netiks atcelta preview_preamble_html: "@%{acct} saņems brīdinājumu ar šādu saturu:" record_strike_html: Ierakstiet brīdinājumu pret @%{acct}, lai palīdzētu jums izvērst turpmākus pārkāpumus no šī konta - warning_placeholder: Izvēles papildu pamatojums regulēšanas darbībai. + warning_placeholder: Izvēles papildu pamatojums satura pārraudzības darbībai. target_origin: Ziņotā konta izcelsme title: Ziņojumi unassign: Atsaukt @@ -679,10 +682,10 @@ lv: other: "%{count} lietotāji" zero: "%{count} lietotāju" categories: - administration: Administrēšana + administration: Pārvaldība devops: DevOps invites: Uzaicinājumi - moderation: Moderācija + moderation: Satura pārraudzība special: Īpašās delete: Dzēst description_html: Izmantojot lietotāju lomas, vari pielāgot, kurām Mastodon funkcijām un apgabaliem var piekļūt tavi lietotāji. @@ -703,7 +706,7 @@ lv: manage_announcements: Pārvaldīt Paziņojumus manage_announcements_description: Ļauj lietotājiem pārvaldīt paziņojumus serverī manage_appeals: Pārvaldīt Pārsūdzības - manage_appeals_description: Ļauj lietotājiem izskatīt apelācijas pret regulēšanas darbībām + manage_appeals_description: Ļauj lietotājiem pārskatīt iebildumus pret satura pārraudzības darbībām manage_blocks: Pārvaldīt Bloķus manage_custom_emojis: Pārvaldīt Pielāgotās Emocijzīmes manage_custom_emojis_description: Ļauj lietotājiem pārvaldīt pielāgotās emocijzīmes serverī @@ -712,7 +715,7 @@ lv: manage_invites: Pārvaldīt Uzaicinājumus manage_invites_description: Ļauj lietotājiem pārlūkot un deaktivizēt uzaicinājuma saites manage_reports: Pārvaldīt Pārskatus - manage_reports_description: Ļauj lietotājiem pārskatīt pārskatus un veikt pret tiem regulēšanas darbības + manage_reports_description: Ļauj lietotājiem pārskatīt ziņojumus un veikt pret tiem satura pārraudzības darbības manage_roles: Pārvaldīt Lomas manage_roles_description: Ļauj lietotājiem pārvaldīt un piešķirt lomas, kas ir zemākas par viņu lomu manage_rules: Pārvaldīt Noteikumus @@ -720,10 +723,10 @@ lv: manage_settings: Pārvaldīt Iestatījumus manage_settings_description: Ļauj lietotājiem mainīt vietnes iestatījumus manage_taxonomies: Pārvaldīt Taksonomijas - manage_taxonomies_description: Ļauj lietotājiem pārskatīt aktuālāko saturu un atjaunināt atsauces iestatījumus + manage_taxonomies_description: Ļauj lietotājiem pārskatīt aktuālāko saturu un atjaunināt tēmturu iestatījumus manage_user_access: Pārvaldīt Lietotāju Piekļuves manage_users: Pārvaldīt Lietotājus - manage_users_description: Ļauj lietotājiem skatīt citu lietotāju informāciju un veikt pret viņiem regulēšanas darbības + manage_users_description: Ļauj lietotājiem skatīt citu lietotāju informāciju un veikt pret viņiem satura pārraudzības darbības manage_webhooks: Pārvaldīt Tīmekļa Aizķeres manage_webhooks_description: Ļauj lietotājiem iestatīt tīmekļa aizķeres administratīviem pasākumiem view_audit_log: Skatīt Audita Žurnālu @@ -776,6 +779,7 @@ lv: disabled: Nevienam users: Vietējiem reģistrētiem lietotājiem registrations: + moderation_recommandation: Lūgums nodrošināt, ka Tev ir pieņemama un atsaucīga satura pārraudzības komanda, pirms padari reģistrēšanos visiem pieejamu. preamble: Kontrolē, kurš var izveidot kontu tavā serverī. title: Reģistrācijas registrations_mode: @@ -783,6 +787,7 @@ lv: approved: Reģistrācijai nepieciešams apstiprinājums none: Neviens nevar reģistrēties open: Jebkurš var reģistrēties + warning_hint: Mēs iesakām izmantot "Nepieciešams reģistrēšanās apstiprinājums", izņemot, ja esi pārliecināts, ka Tava satura pārraudzības komanda var laicīgi apstrādāt mēstules un ļaunprātīgas reģistrācijas. security: authorized_fetch: Pieprasīt autentifikāciju no federētajiem serveriem authorized_fetch_hint: Pieprasot autentifikāciju no federētajiem serveriem, tiek nodrošināta stingrāka gan lietotāja līmeņa, gan servera līmeņa bloku izpilde. Tomēr tas ir saistīts ar izpildes sodu, samazina tavu atbilžu sasniedzamību un var radīt saderības problēmas ar dažiem federētajiem pakalpojumiem. Turklāt tas netraucēs īpašiem dalībniekiem ienest tavas publiskās ziņas un kontus. @@ -886,6 +891,8 @@ lv: review_requested: Pieprasīta pārskatīšana reviewed: Pārskatīts title: Stāvoklis + unreviewed: Nepārskatīts + usable: Izmantojams name: Nosaukums newest: Jaunākie oldest: Vecākie @@ -894,7 +901,7 @@ lv: search: Meklēt title: Tēmturi updated_msg: Tēmtura iestatījumi ir veiksmīgi atjaunināti - title: Administrēšana + title: Pārvaldība trends: allow: Atļaut approved: Apstiprināts @@ -998,9 +1005,9 @@ lv: sensitive: lai atzīmētu viņu kontu kā sensitīvu silence: lai ierobežotu viņu kontu suspend: lai apturētu viņu kontu - body: "%{target} pārsūdzēja %{action_taken_by} moderēšanas lēmumu no %{date}, kas bija %{type}. Viņi rakstīja:" - next_steps: Varat apstiprināt apelāciju, lai atsauktu regulēšanas lēmumu, vai ignorēt to. - subject: "%{username} pārsūdz moderēšanas lēmumu par %{instance}" + body: "%{target} iebilst %{action_taken_by} satura pārraudzības lēmumam no %{date}, kas bija %{type}. Viņi rakstīja:" + next_steps: Vari apstiprināt iebildumu, lai atsauktu satura pārraudzības lēmumu, vai neņemt to vērā. + subject: "%{username} iebilst satura pārraudzības lēmumam par %{instance}" new_critical_software_updates: body: Ir izlaistas jaunas Mastodon svarīgās versijas, iespējams, vēlēsies to atjaunināt pēc iespējas ātrāk! subject: "%{instance} ir pieejami svarīgi Mastodon atjauninājumi!" @@ -1453,7 +1460,7 @@ lv: other_data: Nekādi citi dati netiks automātiski pārvietoti redirect: Tava pašreizējā konta profils tiks atjaunināts ar novirzīšanas paziņojumu un tiks izslēgts no meklēšanas moderation: - title: Moderācija + title: Satura pārraudzība move_handler: carry_blocks_over_text: Šis lietotājs pārcēlās no %{acct}, kuru tu biji bloķējis. carry_mutes_over_text: Šis lietotājs pārcēlās no %{acct}, kuru tu biji apklusinājis. @@ -1495,6 +1502,7 @@ lv: update: subject: "%{name} laboja ierakstu" notifications: + administration_emails: Pārvaldītāju e-pasta paziņojumi email_events_hint: 'Atlasi notikumus, par kuriem vēlies saņemt paziņojumus:' number: human: @@ -1543,7 +1551,7 @@ lv: reach: Sasniedzamība reach_hint_html: Kontrolē, vai vēlies, lai tevi atklātu un sekotu jauni cilvēki. Vai vēlies, lai tavas ziņas tiktu parādītas ekrānā Izpēte? Vai vēlies, lai citi cilvēki tevi redzētu savos ieteikumos? Vai vēlies automātiski pieņemt visus jaunos sekotājus vai arī tev ir pilnīga kontrole pār katru? search: Meklēt - search_hint_html: Kontrolē, kā vēlies tikt atrasts. Vai vēlies, lai cilvēki tevi atrod pēc tā, ko esi publiski publicējis? Vai vēlies, lai cilvēki ārpus Mastodon atrastu tavu profilu, meklējot tīmeklī? Lūdzu, ņem vērā, ka nevar garantēt publiskas informācijas pilnīgu izslēgšanu no visām meklētājprogrammām. + search_hint_html: Nosaki, kā vēlies tikt atrasts! Vai vēlies, lai cilvēki Tevi atrod pēc tā, par ko esi veicis visiem redzamus ierakstus? Vai vēlies, lai cilvēki ārpus Mastodon atrastu Tavu profilu, meklējot tīmeklī? Lūdzu, ņem vērā, ka nevar nodrošināt visiem redzamas informācijas pilnīgu izslēgšanu no visām meklētājiem! title: Privātums un sasniedzamība privacy_policy: title: Privātuma Politika @@ -1580,8 +1588,8 @@ lv: rss: content_warning: 'Satura brīdinājums:' descriptions: - account: Publiskas ziņas no @%{acct} - tag: 'Publiskas ziņas ar atzīmi #%{hashtag}' + account: Visiem redzami ieraksti no @%{acct} + tag: 'Visiem redzami ieraksti ar tēmturi #%{hashtag}' scheduled_statuses: over_daily_limit: Tu esi pārsniedzis šodien ieplānoto %{limit} ziņu ierobežojumu over_total_limit: Tu esi pārsniedzis ieplānoto %{limit} ziņu ierobežojumu @@ -1655,7 +1663,7 @@ lv: 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 + strikes: Satura pārraudzības aizrādījumi two_factor_authentication: Divpakāpju autentifikācija webauthn_authentication: Drošības atslēgas severed_relationships: @@ -1684,7 +1692,7 @@ lv: disallowed_hashtags: one: 'saturēja neatļautu tēmturi: %{tags}' other: 'saturēja neatļautus tēmturus: %{tags}' - zero: 'neatļauti tēmturi: %{tags}' + zero: 'saturēja neatļautus tēmturus: %{tags}' edited_at_html: Labots %{date} errors: in_reply_not_found: Šķiet, ka ziņa, uz kuru tu mēģini atbildēt, nepastāv. @@ -1702,7 +1710,7 @@ lv: public: Publisks public_long: Visi var redzēt unlisted: Nerindota - unlisted_long: Redzama visiem, bet nav iekļauta publiskajās ziņu lentās + unlisted_long: Redzams visiem, bet nav uzskaitīts visiem pieejamās laika joslās statuses_cleanup: enabled: Automātiski dzēst vecās ziņas enabled_hint: Automātiski izdzēš tavas ziņas, tiklīdz tās sasniedz noteiktu vecuma slieksni, ja vien tās neatbilst kādam no tālāk norādītajiem izņēmumiem @@ -1835,7 +1843,8 @@ lv: explanation: Šeit ir daži padomi, kā sākt darbu feature_action: Uzzināt vairāk feature_creativity: Mastodon nodrošina skaņas, video un attēlu ierakstus, pieejamības aprakstus, aptaujas, satura brīdinājumus, animētus profila attēlus, pielāgotas emocijzīmes, sīktēlu apgriešanas vadīklas un vēl, lai palīdzētu Tev sevi izpaust tiešsaistē. Vai Tu izplati savu mākslu, mūziku vai aplādes, Mastodon ir šeit ar Tevi. - feature_moderation_title: Moderēšana, kādai tai būtu jābūt + feature_moderation: Mastodon nodod lēmumu pieņemšanu atpakaļ Tavās rokās. Katrs serveris izveido savus noteikumus un nosacījumus, kas tiek nodrošināti vietēji, ne kā lieliem uzņēmumiem piederošos sabiedriskajos medijiem, padarot katru serveri par vispielāgojamāko un visatsaucīgāko dažādu cilvēku kopu vajadzībām. Pievienojies serverim, kura noteikumiem Tu piekrīti, vai izvieto savu! + feature_moderation_title: Satura pārraudzība, kādai tai būtu jābūt follow_action: Sekot follow_step: Sekošana aizraujošiem cilvēkiem ir viss, par ko ir Mastodon. follow_title: Pielāgo savu mājas barotni @@ -1846,7 +1855,7 @@ lv: one: "%{people} cilvēks pēdējās 2 dienās" other: "%{people} cilvēki pēdējās 2 dienās" zero: "%{people} cilvēku pēdējās divās dienās" - hashtags_subtitle: Izpēti, kas pēdējās divās dienāš ir piesasitījis cilvēku uzmanību + hashtags_subtitle: Izpēti, kas pēdējās divās dienās ir piesasitījis cilvēku uzmanību hashtags_title: Izplatīti tēmturi hashtags_view_more: Skatīt vairāk izplatītu tēmturu post_action: Rakstīt diff --git a/config/locales/ml.yml b/config/locales/ml.yml index bdc0475a6f..c27e5e5467 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/nl.yml b/config/locales/nl.yml index 968dcc3e7c..1af30bca98 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -1166,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 diff --git a/config/locales/nn.yml b/config/locales/nn.yml index b28cf30162..9ec4f29f42 100644 --- a/config/locales/nn.yml +++ b/config/locales/nn.yml @@ -690,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" @@ -719,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 @@ -738,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 @@ -1166,9 +1166,11 @@ 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. + hint_html: Skriv du nyhende eller blogginnlegg utanfor Mastodon? Her kan du kontrollera korleis du blir kreditert når artiklane dine blir delte på Mastodon. + instructions: 'Sjå til at denne koden er i HTML-koden i artikkelen din:' more_from_html: Meir frå %{name} s_blog: Bloggen til %{name} + then_instructions: Så legg du til domenenamnet for publikasjonen i feltet under. title: Forfattarkreditering challenge: confirm: Hald fram @@ -1370,6 +1372,37 @@ nn: 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}. + bookmarks_html: + one: Du skal til å byta ut bokmerka dine med opp til %{count} innlegg frå %{filename}. + other: Du skal til å byta ut bokmerka dine med opp til %{count} innlegg frå %{filename}. + domain_blocking_html: + one: Du skal til å byta ut domeneblokkeringslista di med opp til %{count} domene frå %{filename}. + other: Du skal til å byta ut domeneblokkeringslista di med opp til %{count} domene frå %{filename}. + following_html: + one: Du skal til å fylgja opp til %{count} brukarkonto frå %{filename} og slutta å fylgja alle andre. + other: Du skal til å fylgja opp til %{count} brukarkontoar frå %{filename} og slutta å fylgja alle andre. + muting_html: + one: Du skal til å byta ut lista di over dempa brukarkontoar med opp til %{count} brukarkonto frå %{filename}. + other: Du skal til å byta ut lista di over dempa brukarkontoar med opp til %{count} brukarkontoar frå %{filename}. + preambles: + blocking_html: + one: Du skal til å blokkera opp til %{count} brukarkonto frå %{filename}. + other: Du skal til å blokkera opp til %{count} brukarkontoar frå %{filename}. + bookmarks_html: + one: Du er i ferd med å leggja til opp til %{count} innlegg frå %{filename} til bokmerka dine. + other: Du er i ferd med å leggja til opp til %{count} innlegg frå %{filename} til bokmerka dine. + domain_blocking_html: + one: Du skal til å blokkera opp til %{count} domene frå %{filename}. + other: Du skal til å blokkera opp til %{count} domene frå %{filename}. + following_html: + one: Du er i ferd med å fylgja opp til %{count} brukarkonto frå %{filename}. + other: Du er i ferd med å fylgja opp til %{count} brukarkontoar frå %{filename}. + lists_html: + one: Du er i ferd med å leggja til opptil %{count} konto frå %{filename} til i listene dine. Nye lister vil blir oppretta om ingen lister finst frå før. + other: Du er i ferd med å leggja til opptil %{count} kontoar frå %{filename} til i listene dine. Nye lister vil blir oppretta om ingen lister finst frå før. + muting_html: + one: Du er i ferd med å dempa opp til %{count} brukarkonto frå %{filename}. + other: Du er i ferd med å dempa 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: @@ -1417,7 +1450,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 diff --git a/config/locales/pl.yml b/config/locales/pl.yml index ba1f4812e9..d50a042a22 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -1202,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 diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 8e806f670c..8b2feb5193 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -1166,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 diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml index 68217113d2..1761ec3f0c 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 diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 25ca703732..831f68b24b 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -25,6 +25,7 @@ ru: one: Пост other: статусов posts_tab_heading: Посты + self_follow_error: Нельзя подписаться на самого себя admin: account_actions: action: Выполнить действие @@ -64,7 +65,7 @@ ru: demote: Разжаловать destroyed_msg: Данные %{username} поставлены в очередь на удаление disable: Заморозка - disable_sign_in_token_auth: Отключите аутентификацию с помощью маркера электронной почты + disable_sign_in_token_auth: Отключить аутентификацию по e-mail кодам disable_two_factor_authentication: Отключить 2FA disabled: Отключено display_name: Отображаемое имя @@ -73,7 +74,7 @@ ru: email: E-mail email_status: Статус e-mail enable: Включить - enable_sign_in_token_auth: Включите аутентификацию с помощью маркера электронной почты + enable_sign_in_token_auth: Включить аутентификацию по e-mail кодам enabled: Включен enabled_msg: Учётная запись %{username} успешно разморожена followers: Подписчики @@ -146,8 +147,8 @@ ru: security_measures: only_password: Только пароль password_and_2fa: Пароль и 2FA - sensitive: Отметить как «деликатного содержания» - sensitized: отмечено как «деликатного характера» + sensitive: Деликатный + sensitized: отмечено как деликатный контент shared_inbox_url: URL общих входящих show: created_reports: Жалобы, отправленные с этой учётной записи @@ -165,7 +166,7 @@ ru: unblock_email: Разблокировать e-mail адрес unblocked_email_msg: E-mail адрес %{username} разблокирован unconfirmed_email: Неподтверждённый e-mail - undo_sensitized: Убрать отметку «деликатного содержания» + undo_sensitized: Снять отметку "деликатный" undo_silenced: Отменить скрытие undo_suspension: Снять блокировку unsilenced_msg: Ограничения с учётной записи %{username} сняты успешно @@ -462,6 +463,7 @@ ru: title: Блокировка нового почтового домена no_email_domain_block_selected: Блоки почтовых доменов не были изменены, так как ни один из них не был выбран not_permitted: Не разрешено + resolved_dns_records_hint_html: Доменное имя указывает на следующие MX-домены, которые в конечном итоге отвечают за прием электронной почты. Блокировка MX-домена будет блокировать регистрации с любого адреса электронной почты, который использует тот же MX-домен, даже если видимое доменное имя отличается от него. Будьте осторожны, чтобы не заблокировать основных провайдеров электронной почты resolved_through_html: Разрешено через %{domain} title: Заблокированные e-mail домены export_domain_allows: @@ -625,6 +627,7 @@ ru: resolve_description_html: Никаких действий не будет выполнено относительно доложенного содержимого. Жалоба будет закрыта. silence_description_html: Учетная запись будет видна только тем пользователям, которые уже подписаны на неё, либо открыли его вручную. Это действие можно отменить в любой момент, и отменяет все жалобы против аккаунта. suspend_description_html: Аккаунт и все его содержимое будут недоступны и в конечном итоге удалены, и взаимодействие с ним будет невозможно. Это действие можно отменить в течение 30 дней. Отменяет все жалобы против этого аккаунта. + actions_description_html: Выберите действие, чтобы разрешить данную жалобу. Если вы примете меры модерации против аккаунта, его владелец получит уведомление по электронной почте, кроме тех случаев, когда выбрана категория Спам. actions_description_remote_html: Решите вопрос о том, какие меры необходимо принять для урегулирования этой жалобы. Это повлияет только на то, как ваш сервер взаимодействует с этим удаленным аккаунтом и обрабатывает его содержимое. actions_no_posts: У этого отчета нет связанных с ним сообщений для удаления add_to_report: Прикрепить ещё @@ -901,6 +904,9 @@ ru: 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, пожалуйста, обновитесь как можно скорее. @@ -1196,9 +1202,11 @@ ru: use_security_key: Использовать ключ безопасности author_attribution: example_title: Образец текста - hint_html: Контролируйте, как вы будете отмечены при обмене ссылками на Mastodon. + hint_html: Публикуете ли вы свои статьи где-либо ещё кроме Mastodon? Если да, то ваше авторство может быть упомянуто, когда ими делятся в Mastodon. + instructions: 'Добавьте код ниже в HTML ваших статей:' more_from_html: Больше от %{name} s_blog: "%{name}'S Блог" + then_instructions: Затем добавьте доменное имя сайта, где вы публикуетесь, в поле ниже. title: Авторская атрибуция challenge: confirm: Продолжить @@ -1308,7 +1316,7 @@ ru: csv: CSV domain_blocks: Доменные блокировки lists: Списки - mutes: Ваши игнорируете + mutes: Ваши игнорируемые storage: Ваши файлы featured_tags: add_new: Добавить @@ -1410,6 +1418,68 @@ ru: merge_long: Сохранить имеющиеся данные и добавить новые. overwrite: Перезаписать overwrite_long: Перезаписать имеющиеся данные новыми. + overwrite_preambles: + blocking_html: + few: Вы собираетесь заменить свой список блокировки, в котором сейчас %{count} аккаунта, из файла %{filename}. + many: Вы собираетесь заменить свой список блокировки, в котором сейчас %{count} аккаунов, из файла %{filename}. + one: Вы собираетесь заменить свой список блокировки, в котором сейчас %{count} аккаунт, из файла %{filename}. + other: Вы собираетесь заменить свой список блокировки, в котором сейчас %{count} аккаунтов, из файла %{filename}. + bookmarks_html: + few: Вы собираетесь заменить свои закладки, в которых сейчас %{count} поста, из файла %{filename}. + many: Вы собираетесь заменить свои закладки, в которых сейчас %{count} постов, из файла %{filename}. + one: Вы собираетесь заменить свои закладки, в которых сейчас %{count} пост, из файла %{filename}. + other: Вы собираетесь заменить свои закладки, в которых сейчас %{count} постов, из файла %{filename}. + domain_blocking_html: + few: Вы собираетесь заменить свой список доменных блокировок, в котором сейчас %{count} домена, из файла %{filename}. + many: Вы собираетесь заменить свой список доменных блокировок, в котором сейчас %{count} доменов, из файла %{filename}. + one: Вы собираетесь заменить свой список доменных блокировок, в котором сейчас %{count} домен, из файла %{filename}. + other: Вы собираетесь заменить свой список доменных блокировок, в котором сейчас %{count} доменов, из файла %{filename}. + following_html: + few: Вы собираетесь подписаться на %{count} аккаунта из файла %{filename} и отписаться от всех прочих. + many: Вы собираетесь подписаться на %{count} аккаунтов из файла %{filename} и отписаться от всех прочих. + one: Вы собираетесь подписаться на %{count} аккаунт из файла %{filename} и отписаться от всех прочих. + other: Вы собираетесь подписаться на %{count} аккаунтов из файла %{filename} и отписаться от всех прочих. + lists_html: + few: Вы собираетесь заменить свои списки содержимым файла %{filename}. В новые списки будут добавлены %{count} аккаунта. + many: Вы собираетесь заменить свои списки содержимым файла %{filename}. В новые списки будут добавлены %{count} аккаунтов. + one: Вы собираетесь заменить свои списки содержимым файла %{filename}. В новые списки будет добавлен %{count} аккаунт. + other: Вы собираетесь заменить свои списки содержимым файла %{filename}. В новые списки будут добавлены %{count} аккаунтов. + muting_html: + few: Вы собираетесь заменить свой список игнорируемых пользователей списком из %{count} аккаунтов из файла %{filename}. + many: Вы собираетесь заменить свой список игнорируемых пользователей списком из %{count} аккаунтов из файла %{filename}. + one: Вы собираетесь заменить свой список игнорируемых пользователей списком из %{count} аккаунта из файла %{filename}. + other: Вы собираетесь заменить свой список игнорируемых пользователей списком из %{count} аккаунтов из файла %{filename}. + preambles: + blocking_html: + few: Вы собираетесь заблокировать %{count} аккаунта из файла %{filename}. + many: Вы собираетесь заблокировать %{count} аккаунтов из файла %{filename}. + one: Вы собираетесь заблокировать %{count} аккаунт из файла %{filename}. + other: Вы собираетесь заблокировать %{count} аккаунтов из файла %{filename}. + bookmarks_html: + few: Вы собираетесь добавить %{count} поста из файла %{filename} в свои закладки. + many: Вы собираетесь добавить %{count} постов из файла %{filename} в свои закладки. + one: Вы собираетесь добавить %{count} пост из файла %{filename} в свои закладки. + other: Вы собираетесь добавить %{count} постов из файла %{filename} в свои закладки. + domain_blocking_html: + few: Вы собираетесь заблокировать %{count} домена из файла %{filename}. + many: Вы собираетесь заблокировать %{count} доменов из файла %{filename}. + one: Вы собираетесь заблокировать %{count} домен из файла %{filename}. + other: Вы собираетесь заблокировать %{count} доменов из файла %{filename}. + following_html: + few: Вы собираетесь подписаться на %{count} аккаунта из файла %{filename}. + many: Вы собираетесь подписаться на %{count} аккаунтов из файла %{filename}. + one: Вы собираетесь подписаться на %{count} аккаунт из файла %{filename}. + other: Вы собираетесь подписаться на %{count} аккаунтов из файла %{filename}. + lists_html: + few: Вы собираетесь добавить %{count} аккаунта из файла %{filename} в свои списки. Если соответствующих списков нет, они будут созданы. + many: Вы собираетесь добавить %{count} аккаунтов из файла %{filename} в свои списки. Если соответствующих списков нет, они будут созданы. + one: Вы собираетесь добавить %{count} аккаунт из файла %{filename} в свои списки. Если соответствующих списков нет, они будут созданы. + other: Вы собираетесь добавить %{count} аккаунтов из файла %{filename} в свои списки. Если соответствующих списков нет, они будут созданы. + muting_html: + few: Вы собираетесь начать игнорировать %{count} аккаунта из файла %{filename}. + many: Вы собираетесь начать игнорировать %{count} аккаунтов из файла %{filename}. + one: Вы собираетесь начать игнорировать %{count} аккаунт из файла %{filename}. + other: Вы собираетесь начать игнорировать %{count} аккаунтов из файла %{filename}. preface: Вы можете загрузить некоторые данные, например, списки людей, на которых Вы подписаны или которых блокируете, в Вашу учётную запись на этом узле из файлов, экспортированных с другого узла. recent_imports: Недавно импортированное states: @@ -1482,6 +1552,7 @@ ru: unsubscribe: action: Да, отписаться complete: Подписка отменена + confirmation_html: Вы точно желаете отписаться от всех уведомления типа «%{type}», доставляемых из сервера Mastodon %{domain} на ваш адрес электронной почты %{email}? Вы всегда сможете подписаться снова в настройках e-mail уведомлений. emails: notification_emails: favourite: любимые электронные письма с уведомлениями @@ -1727,6 +1798,7 @@ ru: 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 b591cdca57..0a665fb784 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 5e3f1af89a..00617c4e3c 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 7b7d92995b..2690f07141 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -3,7 +3,6 @@ bg: simple_form: hints: account: - attribution_domains_as_text: Защитава от фалшиви атрибути. discoverable: Вашите публични публикации и профил може да се представят или препоръчват в различни области на Mastodon и вашия профил може да се предлага на други потребители. display_name: Вашето пълно име или псевдоним. fields: Вашата начална страница, местоимения, години, всичко що искате. @@ -144,7 +143,6 @@ bg: url: До къде ще се изпращат събитията labels: account: - attribution_domains_as_text: Позволяване само на особени уебсайтове discoverable: Включване на профил и публикации в алгоритмите за откриване fields: name: Етикет diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index 7b651470bf..c628bebaad 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 56d1f873dc..dedd50504b 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 e7b8fe337a..25cf670ea9 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 f7e55f1a7b..08d5331151 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 d46e764a44..9dcac5c160 100644 --- a/config/locales/simple_form.el.yml +++ b/config/locales/simple_form.el.yml @@ -3,7 +3,6 @@ el: simple_form: hints: account: - attribution_domains_as_text: Προστατεύει από ψευδείς ιδιότητες. discoverable: Οι δημόσιες δημοσιεύσεις και το προφίλ σου μπορεί να εμφανίζονται ή να συνιστώνται σε διάφορους τομείς του Mastodon και το προφίλ σου μπορεί να προτείνεται σε άλλους χρήστες. display_name: Το πλήρες ή το αστείο σου όνομα. fields: Η αρχική σου σελίδα, αντωνυμίες, ηλικία, ό,τι θες. @@ -144,7 +143,6 @@ el: url: Πού θα σταλούν τα γεγονότα labels: account: - attribution_domains_as_text: Να επιτρέπονται μόνο συγκεκριμένες ιστοσελίδες discoverable: Παροχή προφίλ και αναρτήσεων σε αλγορίθμους ανακάλυψης fields: name: Περιγραφή diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index b802fd532f..e20249e6bc 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 8f6137c8c1..25de9f5910 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. @@ -144,7 +144,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 cb4a9041e8..f8a5776835 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -3,7 +3,7 @@ eo: simple_form: hints: account: - attribution_domains_as_text: Protektas kontraŭ falsaj atribuoj. + attribution_domains_as_text: Unu por linio. Protektas kontraŭ falsaj atribuoj. discoverable: Viaj publikaj afiŝoj kaj profilo povas esti prezentitaj aŭ rekomenditaj en diversaj lokoj de Mastodon kaj via profilo povas esti proponita al aliaj uzantoj. display_name: Via plena nomo aŭ via kromnomo. fields: Via retpaĝo, pronomoj, aĝo, ĉio, kion vi volas. @@ -40,12 +40,14 @@ eo: text: Oni povas apelaci strikin nur unufoje defaults: autofollow: Homoj, kiuj registriĝos per la invito aŭtomate sekvos vin + avatar: WEBP, PNG, GIF aŭ JPG. Maksimume %{size}. Malgrandiĝos al %{dimensions}px bot: Tiu konto ĉefe faras aŭtomatajn agojn, kaj povas esti ne kontrolata context: Unu ol pluraj kuntekstoj kie la filtrilo devus agi current_password: Pro sekuraj kialoj, bonvolu enigi la pasvorton de la nuna konto current_username: Por konfirmi, bonvolu enigi la uzantnomon de la nuna konto digest: Sendita nur post longa tempo de neaktiveco, kaj nur se vi ricevis personan mesaĝon en via foresto email: Vi ricevos konfirman retpoŝton + header: WEBP, PNG, GIF aŭ JPG. Maksimume %{size}. Malgrandiĝos al %{dimensions}px inbox_url: Kopiu la URL de la ĉefpaĝo de la ripetilo, kiun vi volas uzi irreversible: La filtritaj mesaĝoj malaperos por eterne, eĉ se la filtrilo poste estas forigita locale: La lingvo de la fasado, retpoŝtaĵoj, kaj sciigoj @@ -76,11 +78,15 @@ 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 + app_icon: WEBP, PNG, GIF aŭ JPG. Anstataŭigas la defaŭltan aplikaĵan bildsimbolon sur porteblaj aparatoj kun propra bildsimbolo. + 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 + content_cache_retention_period: Ĉiuj afiŝoj de aliaj serviloj (inkluzive de diskonigoj kaj respondoj) estos forigitaj post la specifita nombro da tagoj, sen konsidero al iu ajn loka uzantinterago kun tiuj afiŝoj. Ĉi tio inkluzivas afiŝojn, kie loka uzanto markis ĝin kiel legosignojn aŭ ŝatatajn. Privataj mencioj inter uzantoj de malsamaj nodoj ankaŭ estos perditaj kaj neeble restaŭreblaj. Uzo de ĉi tiu agordo estas celita por specialcelaj okazoj kaj rompas multajn uzantajn atendojn kiam efektivigita por ĝenerala uzo. 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. + media_cache_retention_period: Amaskomunikilaj dosieroj de afiŝoj faritaj de foraj uzantoj estas konservitaj en kaŝmemoro en via servilo. Kiam agordita al pozitiva valoro, amaskomunikilaro estos forigita post la specifita nombro da tagoj. Se la amaskomunikilaro-datumoj estas petitaj post kiam ĝi estas forigita, ĝi estos re-elŝutita, se la fonta enhavo ankoraŭ disponeblas. Pro limigoj pri kiom ofte ligaj antaŭrigardaj kartoj enketas retejojn de ekstera liveranto, oni rekomendas agordi ĉi tiun valoron al almenaŭ 14 tagoj, aŭ ligaj antaŭrigardaj kartoj ne estos ĝisdatigitaj laŭpostule antaŭ tiu tempo. 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. require_invite_text: Kiam registroj bezonas permanan aprobon, igi la "Kial vi volas aliĝi?" tekstoenigon deviga anstau nedeviga @@ -138,7 +144,7 @@ eo: url: Kien eventoj sendotas labels: account: - attribution_domains_as_text: Permesi nur specifajn retejojn + attribution_domains_as_text: Retejoj permesitaj krediti vin discoverable: Elstarigi profilon kaj afiŝojn en eltrovantaj algoritmoj fields: name: Etikedo @@ -243,6 +249,7 @@ 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 diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index d06d09761a..98254c5e99 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 8c84e35a4d..2b5d22aee8 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: Uno por línea. Protege contra atribuciones falsas. 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. @@ -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 diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index b22701aae7..8bc2c5f65c 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 8d045cfcfe..a2ebf63b11 100644 --- a/config/locales/simple_form.et.yml +++ b/config/locales/simple_form.et.yml @@ -3,7 +3,7 @@ et: simple_form: hints: account: - attribution_domains_as_text: Kaitseb valede omistuste eest. + attribution_domains_as_text: Üks rea peal. See kaitseb pahatahtlike viidete 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 +144,7 @@ et: url: Kuhu sündmused saadetakse labels: account: - attribution_domains_as_text: Luba vaid kindlad veebilehed + attribution_domains_as_text: Sinule viidata lubatud 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 bbb0523b17..f51a4ce8bf 100644 --- a/config/locales/simple_form.fa.yml +++ b/config/locales/simple_form.fa.yml @@ -3,6 +3,7 @@ fa: simple_form: hints: account: + attribution_domains_as_text: یکی در هر خط. محافظت از اعتباردهی‌های اشتباه. discoverable: ممکن است نمایه و فرسته‌های عمومیتان در جاهای مختلف ماستودون نمایانده و توصیه شود و نمایه‌تان به دیگر کاربران پیشنهاد شود. display_name: نام کامل یا باحالتان. fields: صفحهٔ خانگی، تلفّظ، سن و هرچیزی که دوست دارید. @@ -39,12 +40,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: زبان واسط کاربری، رایانامه‌ها و آگاهی‌های ارسالی @@ -88,6 +91,7 @@ fa: site_short_description: شرحی کوتاه برای کمک به شناسایی یکتای کارسازتان. چه‌کسی می‌گرداندش و برای چه کسیست؟ site_terms: از سیاست محرمانگی خوتان استفاده کرده یا برای استفاده از سیاست پیش‌گزیده خالی بگذارید. می‌تواند در قالب مارک‌دون باشد. site_title: چگونه مردم ممکن است به کارساز شما علاوه بر نام دامنه آن مراجعه کنند. + theme: زمینه‌ای که بینندگان خارج شده و کاربران جدید می‌بینند. form_challenge: current_password: شما در حال ورود به یک منطقهٔ‌ حفاظت‌شده هستید imports: @@ -120,6 +124,7 @@ fa: url: جایی که رویدادها فرستاده می‌شوند labels: account: + attribution_domains_as_text: پابگاه‌های وبی که اجازهٔ اعتبار دهی به شما را دارند discoverable: معرّفی نمایه و فرسته‌ها در الگوریتم‌های کشف fields: name: برچسب @@ -225,6 +230,7 @@ fa: bootstrap_timeline_accounts: پیشنهاد همیشگی این حساب‌ها به کاربران جدید closed_registrations_message: پیام سفارشی هنگام در دسترس نبودن ثبت‌نام‌ها custom_css: سبک CSS سفارشی + favicon: نمادک mascot: نشان سفارشی (قدیمی) media_cache_retention_period: دورهٔ نگه‌داری انبارهٔ رسانه peers_api_enabled: انتشار سیاههٔ کارسازهای کشف شده در API diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index 5c85367dbb..8c914295fe 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 afcd3b39ac..e45183df99 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 90a268f411..d2ce30ec8e 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 370f5c1e46..626032600a 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 11b56bd50d..c840342db5 100644 --- a/config/locales/simple_form.fy.yml +++ b/config/locales/simple_form.fy.yml @@ -3,7 +3,7 @@ fy: simple_form: hints: account: - attribution_domains_as_text: Beskermet tsjin net korrekte attribúsjes. + attribution_domains_as_text: Ien per rigel. Beskermet tsjin falske attribúsjes. discoverable: Jo iepenbiere berjochten kinne útljochte wurde op ferskate plakken binnen Mastodon en jo account kin oanrekommandearre wurde oan oare brûkers. display_name: Jo folsleine namme of in aardige bynamme. fields: Jo website, persoanlike foarnammewurden, leeftiid, alles wat jo mar kwyt wolle. @@ -144,7 +144,7 @@ fy: url: Wêr’t eveneminten nei ta stjoerd wurde labels: account: - attribution_domains_as_text: Allinnich bepaalde websites tastean + attribution_domains_as_text: Websites dy’t jo wurdearring jaan meie discoverable: Profyl en bydragen yn sykalgoritmen opnimme litte fields: name: Label diff --git a/config/locales/simple_form.ga.yml b/config/locales/simple_form.ga.yml index 772f996ca6..f8257a9da9 100644 --- a/config/locales/simple_form.ga.yml +++ b/config/locales/simple_form.ga.yml @@ -3,7 +3,7 @@ ga: simple_form: hints: account: - attribution_domains_as_text: Cosnaíonn sé ó sannadh bréagach. + attribution_domains_as_text: Ceann in aghaidh an líne. 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 +144,7 @@ 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 + attribution_domains_as_text: Tá cead ag suíomhanna Gréasáin creidmheas a thabhairt duit 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 de585c7a21..af1f06a316 100644 --- a/config/locales/simple_form.gd.yml +++ b/config/locales/simple_form.gd.yml @@ -3,7 +3,7 @@ gd: simple_form: hints: account: - attribution_domains_as_text: Dìonadh seo o bhuaidh-aithrisean cearra. + attribution_domains_as_text: Loidhne fa leth do gach fear. Dìonaidh seo o iomraidhean meallta. 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 +144,7 @@ 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 + attribution_domains_as_text: Na làraichean-lìn a dh’fhaodas iomradh a thoirt ort 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 cddeae5cee..b29a071e80 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 1feebb0d69..d8d6af5e99 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 383bdd0760..230965fe87 100644 --- a/config/locales/simple_form.hu.yml +++ b/config/locales/simple_form.hu.yml @@ -144,7 +144,7 @@ hu: url: Ahová az eseményket küldjük labels: account: - attribution_domains_as_text: Csak meghatározott weboldalak engedélyezése + attribution_domains_as_text: Weboldalak, melyek szerzőként tüntethetnek fel 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 dc5aad57ae..85fa74f1ed 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 5cbbd9d06e..1df5008195 100644 --- a/config/locales/simple_form.io.yml +++ b/config/locales/simple_form.io.yml @@ -3,7 +3,6 @@ io: simple_form: hints: account: - attribution_domains_as_text: Protektas de falsa akreditaji. discoverable: Vua publika posti e profilo povas remarkesar o rekomendesar en diferanta parti di Mastodon e vua profilo povas sugestesar ad altra uzanti. display_name: Vua tota nomo o vua gaya nomo. fields: Vua retsituo, pronomi, evo, irgo quan vu volas. @@ -144,7 +143,6 @@ io: url: Ibe eventi sendesos labels: account: - attribution_domains_as_text: Nur permisas specifika retsitui discoverable: Inkluzar profilo e posti en trovado-algoritmi fields: name: Etiketo diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index 6f3a4fe8a5..40ae267a06 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 7ed4c0d004..c36fce36f7 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 2c1bd6a084..27e98341cb 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -3,6 +3,7 @@ ja: simple_form: hints: account: + attribution_domains_as_text: 1行につき1つずつ入力してください。この設定は関わりのないwebサイトに対して虚偽の帰属表示が行われることを防止する役割があります。 discoverable: プロフィールと公開投稿をMastodonのおすすめやハイライトとしてほかのユーザーに表示することを許可します。 display_name: フルネーム、ハンドルネームなど fields: ホームページ、代名詞、年齢など何でも構いません。 @@ -130,6 +131,7 @@ ja: name: 視認性向上などのためにアルファベット大文字小文字の変更のみ行うことができます user: chosen_languages: 選択すると、選択した言語の投稿のみが公開タイムラインに表示されるようになります + role: そのロールは、ユーザーが持つ権限を制御します。 user_role: color: UI 全体でロールの表示に使用される色(16進数RGB形式) highlighted: これによりロールが公開されます。 @@ -142,6 +144,7 @@ ja: url: イベントの送信先 labels: account: + attribution_domains_as_text: あなたの著者表示を許可するwebサイト discoverable: アカウントを見つけやすくする fields: name: ラベル diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index a649b4ec5a..b2ebf5666d 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -3,7 +3,7 @@ ko: simple_form: hints: account: - attribution_domains_as_text: 가짜 기여로부터 보호합니다. + attribution_domains_as_text: 한 줄에 하나씩. 가짜 기여로부터 보호합니다. discoverable: 내 공개 게시물과 프로필이 마스토돈의 다양한 추천 기능에 나타날 수 있고 프로필이 다른 사용자에게 제안될 수 있습니다 display_name: 진짜 이름 또는 재미난 이름. fields: 홈페이지, 호칭, 나이, 뭐든지 적고 싶은 것들. @@ -32,9 +32,9 @@ ko: warning_preset_id: 선택사항. 틀의 마지막에 임의의 텍스트를 추가 할 수 있습니다 announcement: all_day: 체크 되었을 경우, 그 시간에 속한 날짜들에만 표시됩니다 - ends_at: 옵션입니다. 공지사항이 이 시간에 자동으로 발행 중지 됩니다 + ends_at: 선택사항. 공지사항이 이 시간에 자동으로 발행 중지 됩니다 scheduled_at: 공백으로 두면 공지사항이 곧바로 발행 됩니다 - starts_at: 공지사항이 특정한 시간에 종속 될 때를 위한 옵션입니다 + starts_at: 선택사항. 공지사항이 특정한 시간에 종속 될 때를 위한 옵션입니다 text: 게시물 문법을 사용할 수 있습니다. 공지사항은 사용자의 화면 상단 공간을 차지한다는 것을 명심하세요 appeal: text: 처벌에 대해 단 한 번만 이의제기를 할 수 있습니다 @@ -110,7 +110,7 @@ ko: invite_request: text: 이 정보는 신청을 검토하는데 도움을 줄 수 있습니다. ip_block: - comment: 필수 아님. 왜 이 규칙을 추가했는지 기억하세요. + comment: 선택사항. 왜 이 규칙을 추가했는지 기억하세요. expires_in: IP 주소는 한정된 자원입니다, 이것들은 가끔 공유 되거나 자주 소유자가 바뀌기도 합니다. 이런 이유로 인해, IP 차단을 영구히 유지하는 것은 추천하지 않습니다. ip: IPv4 또는 IPv6 주소를 입력하세요. CIDR 문법을 사용해서 모든 범위를 차단할 수도 있습니다. 자기 자신을 잠가버리지 않도록 주의하세요! severities: @@ -119,7 +119,7 @@ ko: sign_up_requires_approval: 새 가입이 승인을 필요로 하도록 합니다 severity: 해당 IP로부터의 요청에 대해 무엇이 일어나게 할 지 고르세요 rule: - hint: 옵션사항. 규칙에 대한 더 상세한 정보를 제공하세요 + hint: 선택사항. 규칙에 대한 더 상세한 정보를 제공하세요 text: 이 서버 사용자들이 지켜야 할 규칙과 요구사항을 설명해주세요. 짧고 간단하게 작성해주세요 sessions: otp: '휴대전화에서 생성된 이중 인증 코드를 입력하거나, 복구 코드 중 하나를 사용하세요:' @@ -144,7 +144,7 @@ ko: url: 이벤트가 어디로 전송될 지 labels: account: - attribution_domains_as_text: 특정 웹사이트만 허용하기 + attribution_domains_as_text: 나를 기여자로 올릴 수 있도록 허용된 웹사이트들 discoverable: 발견하기 알고리즘에 프로필과 게시물을 추천하기 fields: name: 라벨 diff --git a/config/locales/simple_form.lad.yml b/config/locales/simple_form.lad.yml index 94e387107a..de37005312 100644 --- a/config/locales/simple_form.lad.yml +++ b/config/locales/simple_form.lad.yml @@ -307,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 5d3a02993b..de3dd2f31c 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 523e9a5fcc..106e29d2de 100644 --- a/config/locales/simple_form.lv.yml +++ b/config/locales/simple_form.lv.yml @@ -3,7 +3,7 @@ lv: simple_form: hints: account: - attribution_domains_as_text: Aizsargā no nepatiesa attiecinājuma. + attribution_domains_as_text: Viens katrā līnijā. 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. @@ -19,7 +19,7 @@ lv: text: Vari izmantot ziņu sintaksi, piemēram, URL, atsauces un pieminējumus title: Neobligāts. Saņēmējam nav redzams admin_account_action: - include_statuses: Lietotājs redzēs, kuras ziņas izraisījušas moderācijas darbību vai brīdinājumu + include_statuses: Lietotājs redzēs, kuras ziņas izraisījušas satura pārraudzības darbību vai brīdinājumu send_email_notification: Lietotājs saņems paskaidrojumu par to, kas notika ar viņa kontu text_html: Neobligāts. Tu vari lietot ziņu sintaksi. Lai ietaupītu laiku, tu vari pievienot brīdinājuma sākotnējos iestatījumus type_html: Izvēlies, ko darīt ar %{acct} @@ -61,7 +61,7 @@ lv: setting_display_media_hide_all: Vienmēr slēpt multividi setting_display_media_show_all: Vienmēr rādīt multividi setting_use_blurhash: Pāreju pamatā ir paslēpto uzskatāmo līdzekļu krāsas, bet saturs tiek padarīts neskaidrs - setting_use_pending_items: Paslēpt laika skalas atjauninājumus aiz klikšķa, nevis automātiski ritini plūsmu + setting_use_pending_items: Paslēpt laika skalas atjauninājumus aiz klikšķa, nevis ar automātisku plūsmas ritināšanu username: Tu vari lietot burtus, ciparus un zemsvītras whole_word: Ja atslēgvārds vai frāze ir tikai burtciparu, tas tiks lietots tikai tad, ja tas atbilst visam vārdam domain_allow: @@ -144,7 +144,7 @@ lv: url: Kur notikumi tiks nosūtīti labels: account: - attribution_domains_as_text: Ļaut tikai noteiktas tīmekļvietnes + attribution_domains_as_text: Tīmekļvietnes, kurām ir tiesības uzskaitīt Tevi 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 bf30cdb1bf..5318059f4a 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 toeschrijvingen. 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 @@ -213,7 +213,7 @@ nl: setting_default_privacy: Zichtbaarheid van nieuwe berichten setting_default_sensitive: Media altijd als gevoelig markeren setting_delete_modal: Vraag voor het verwijderen van een bericht een bevestiging - setting_disable_hover_cards: Profielvoorbeelden door eroverheen te zweven uitschakelen + setting_disable_hover_cards: Hover-kaarten met profielvoorbeelden uitschakelen setting_disable_swiping: Swipebewegingen uitschakelen setting_display_media: Mediaweergave setting_display_media_default: Standaard diff --git a/config/locales/simple_form.nn.yml b/config/locales/simple_form.nn.yml index ddd5ed8995..46b7af4bdb 100644 --- a/config/locales/simple_form.nn.yml +++ b/config/locales/simple_form.nn.yml @@ -3,7 +3,7 @@ nn: simple_form: hints: account: - attribution_domains_as_text: Vernar mot falske krediteringar. + attribution_domains_as_text: Ein per line. 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 +137,14 @@ 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 + attribution_domains_as_text: Nettstader som har lov å kreditera deg 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 bb404e56c9..c5ff55c15d 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 96bc219e8e..16d7cfe445 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 3ff746451b..37626ff9fd 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -3,7 +3,7 @@ ru: simple_form: hints: account: - attribution_domains_as_text: Защищает от ложных атрибуций. + attribution_domains_as_text: По одному на строку. Защищает от ложных атрибуций. discoverable: Ваши публичные сообщения и профиль могут быть показаны или рекомендованы в различных разделах Mastodon, и ваш профиль может быть предложен другим пользователям. display_name: Ваше полное имя или псевдоним. fields: Ваша домашняя страница, местоимения, возраст - все, что угодно. @@ -144,7 +144,7 @@ ru: url: Куда события будут отправляться labels: account: - attribution_domains_as_text: Разрешить только определенные сайты + attribution_domains_as_text: Веб-сайты, которым разрешено ссылаться на вас discoverable: Профиль и сообщения в алгоритмах обнаружения fields: name: Пункт diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index 169f4a02de..1ca9037e63 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -3,7 +3,7 @@ sq: simple_form: hints: account: - attribution_domains_as_text: Mbron nga atribuime të rreme. + attribution_domains_as_text: Një për rresht. Kjo 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 +144,7 @@ sq: url: Ku do të dërgohen aktet labels: account: - attribution_domains_as_text: Lejo vetëm sajte specifikë + attribution_domains_as_text: Sajte të lejuar t’ju japin hakë discoverable: Profilin dhe postimet bëji objekt të algoritmeve të zbulimit fields: name: Etiketë diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml index 297e96a2bd..72c3f000f6 100644 --- a/config/locales/simple_form.sv.yml +++ b/config/locales/simple_form.sv.yml @@ -3,6 +3,7 @@ sv: simple_form: hints: account: + attribution_domains_as_text: En per rad. Skyddar mot falska attributioner. discoverable: Dina offentliga inlägg och din profil kan komma att presenteras eller rekommenderas inom olika områden av Mastodon och din profil kan komma att föreslås till andra användare. display_name: Ditt fullständiga namn eller ditt roliga namn. fields: Din hemsida, ditt pronomen, din ålder, vadhelst du vill. @@ -73,7 +74,7 @@ sv: filters: action: Välj vilken åtgärd som ska utföras när ett inlägg matchar filtret actions: - hide: Dölj det filtrerade innehållet helt (beter sig som om det inte fanns) + hide: Dölj det filtrerade innehållet helt, beter sig som om det inte fanns warn: Dölj det filtrerade innehållet bakom en varning som visar filtrets rubrik form_admin_settings: activity_api_enabled: Antalet lokalt publicerade inlägg, aktiva användare och nya registrerade konton per vecka @@ -143,6 +144,7 @@ sv: url: Dit händelser kommer skickas labels: account: + attribution_domains_as_text: Webbplatser som får kreditera dig discoverable: Presentera profil och inlägg med upptäcktsalgoritmer fields: name: Etikett diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index 1ecd672a97..f8f4d3f119 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -3,7 +3,7 @@ th: simple_form: hints: account: - attribution_domains_as_text: ปกป้องจากการระบุแหล่งที่มาที่ผิด + attribution_domains_as_text: หนึ่งรายการต่อบรรทัด ปกป้องจากการระบุแหล่งที่มาที่ผิด discoverable: อาจแสดงหรือแนะนำโพสต์และโปรไฟล์สาธารณะของคุณในพื้นที่ต่าง ๆ ของ Mastodon และอาจเสนอแนะโปรไฟล์ของคุณให้กับผู้ใช้อื่น ๆ display_name: ชื่อเต็มของคุณหรือชื่อแบบสนุกสนานของคุณ fields: หน้าแรก, สรรพนาม, อายุของคุณ สิ่งใดก็ตามที่คุณต้องการ @@ -144,7 +144,7 @@ th: url: ที่ซึ่งจะส่งเหตุการณ์ไปยัง labels: account: - attribution_domains_as_text: อนุญาตเฉพาะเว็บไซต์ที่เฉพาะเจาะจงเท่านั้น + attribution_domains_as_text: เว็บไซต์ที่ได้รับอนุญาตให้ให้เครดิตคุณ discoverable: แสดงโปรไฟล์และโพสต์ในอัลกอริทึมการค้นพบ fields: name: ป้ายชื่อ diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index d90b97bf9b..5aed566626 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 b584a6cada..74dcd3f908 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -3,7 +3,7 @@ uk: simple_form: hints: account: - attribution_domains_as_text: Захищає від фальшивих атрибутів. + attribution_domains_as_text: Один на рядок. Захищає від фальшивих атрибутів. discoverable: Ваші дописи та профіль можуть бути рекомендовані в різних частинах Mastodon і ваш профіль може бути запропонований іншим користувачам. display_name: Ваше повне ім'я або ваш псевдонім. fields: Ваша домашня сторінка, займенники, вік, все, що вам заманеться. @@ -144,7 +144,7 @@ uk: url: Куди надсилатимуться події labels: account: - attribution_domains_as_text: Дозволити лише на певних вебсайтах + attribution_domains_as_text: Сайти дозволяють вам вказувати ваше авторство discoverable: Функції профілю та дописів у алгоритмах виявлення fields: name: Мітка diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index 010bb262ad..2b1d84f595 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -3,7 +3,7 @@ vi: simple_form: hints: account: - attribution_domains_as_text: Bảo vệ khỏi những sự gán ghép sai. + 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ì. @@ -43,7 +43,7 @@ vi: 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 những nơi mà bộ lọc sẽ áp dụng - current_password: Vì mục đích bảo mật, vui lòng nhập mật khẩu của tài khoản hiện tại + current_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 @@ -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 @@ -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 diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 419cb99abb..6586c372ef 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 a5bc683634..289a24f122 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 399ecc061a..6ef78a8f21 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -49,6 +49,7 @@ sk: title: Zmeň email pre %{username} change_role: changed_msg: Postavenie úspešne zmenené! + edit_roles: Spravuj role užívateľov label: Zmeň pozíciu no_role: Žiadna pozícia title: Zmeň pozíciu pre %{username} @@ -61,6 +62,7 @@ sk: demote: Degraduj destroyed_msg: "%{username} je teraz zaradený do fronty na okamžité vymazanie" disable: Zablokuj + disable_sign_in_token_auth: Vypni overovanie e-mailovým tokenom disable_two_factor_authentication: Vypni dvoj-faktorové overovanie disabled: Blokovaný display_name: Ukáž meno @@ -69,6 +71,7 @@ sk: email: Email email_status: Stav emailu enable: Povoľ + enable_sign_in_token_auth: Povoľ overovania e-mailovým tokenom enabled: Povolený enabled_msg: Úspešne rozmrazené konto %{username} followers: Sledujúci @@ -822,6 +825,7 @@ sk: prefix_invited_by_user: "@%{name} ťa pozýva na tento Mastodon server!" prefix_sign_up: Zaregistruj sa na Mastodone už dnes! suffix: S účtom budeš môcť nasledovať ľudí, posielať príspevky, a vymieňať si správy s užívateľmi z hocijakého Mastodon servera a viac! + didnt_get_confirmation: Neobdržal/a si odkaz na potvrdenie? dont_have_your_security_key: Nemáš svoj bezpečnostný kľúč? forgot_password: Zabudnuté heslo? invalid_reset_password_token: Token na obnovu hesla vypršal. Prosím vypítaj si nový. @@ -832,6 +836,7 @@ sk: migrate_account_html: Ak si želáš presmerovať tento účet na nejaký iný, môžeš si to nastaviť tu. or_log_in_with: Alebo prihlás s progress: + confirm: Potvrď email details: Tvoje údaje rules: Súhlas s pravidlami register: Zaregistruj sa diff --git a/config/locales/sq.yml b/config/locales/sq.yml index 0b276393a6..980eff1aa5 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 @@ -1158,9 +1159,11 @@ 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. + hint_html: Shkruani lajme, apo artikuj blogu jashtë Mastodon-it? Kontrolloni se si ju jepet hakë, kur ndahen me të tjerët në Mastodon. + instructions: 'Sigurohuni që ky kod të jetë në HTML-në e artikullit tuaj:' more_from_html: Më tepër nga %{name} s_blog: Blogu i %{name} + then_instructions: Mandej, shtoni te fusha më poshtë emrin e përkatësisë së botimit. title: Atribuim autorësh challenge: confirm: Vazhdo diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 0d19d17c3b..bd33e837bd 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 @@ -57,7 +59,7 @@ sv: delete: Radera data deleted: Raderad demote: Degradera - destroyed_msg: "%{username}'s data har nu lagts till kön för att raderas omedelbart" + destroyed_msg: "%{username}s data har nu lagts till kön för att raderas omedelbart" disable: inaktivera disable_sign_in_token_auth: Inaktivera autentisering med pollett via e-post disable_two_factor_authentication: Inaktivera 2FA @@ -70,7 +72,7 @@ sv: enable: Aktivera enable_sign_in_token_auth: Aktivera autentisering med pollett via e-post enabled: Aktiverad - enabled_msg: Uppfrysningen av %{username}'s konto lyckades + enabled_msg: Uppfrysningen av %{username}s konto lyckades followers: Följare follows: Följs header: Rubrik @@ -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,23 +263,26 @@ 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" + memorialize_account_html: "%{name} gjorde %{target}s konto till en minnessida" promote_user_html: "%{name} befordrade användaren %{target}" reject_appeal_html: "%{name} avvisade överklagande av modereringsbeslut från %{target}" reject_user_html: "%{name} avvisade registrering från %{target}" - remove_avatar_user_html: "%{name} tog bort %{target}'s avatar" + 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" - silence_account_html: "%{name} begränsade %{target}'s konto" + sensitive_account_html: "%{name} markerade %{target}s media som känsligt" + silence_account_html: "%{name} begränsade %{target}s konto" suspend_account_html: "%{name} stängde av %{target}s konto" unassigned_report_html: "%{name} tog bort tilldelning av rapporten %{target}" unblock_email_account_html: "%{name} avblockerade %{target}s e-postadress" - unsensitive_account_html: "%{name} avmarkerade %{target}'s media som känsligt" + unsensitive_account_html: "%{name} avmarkerade %{target}s media som känsligt" unsilence_account_html: "%{name} tog bort begränsning av %{target}s konto" unsuspend_account_html: "%{name} ångrade avstängningen av %{target}s konto" update_announcement_html: "%{name} uppdaterade kungörelsen %{target}" @@ -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 @@ -532,7 +542,7 @@ sv: total_followed_by_them: Följs av dem total_followed_by_us: Följs av oss total_reported: Rapporter om dem - total_storage: Media-bilagor + total_storage: Mediebilagor totals_time_period_hint_html: Totalsummorna som visas nedan inkluderar data för all tid. unknown_instance: Det finns för närvarande inga uppgifter om denna domän på denna server. invites: @@ -559,7 +569,7 @@ sv: no_ip_block_selected: Inga IP-regler ändrades då inga var valda title: IP-regler relationships: - title: "%{acct}'s relationer" + title: "%{acct}s relationer" relays: add_new: Lägg till nytt relä delete: Radera @@ -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 @@ -861,6 +877,7 @@ sv: 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 @@ -876,22 +893,38 @@ sv: message_html: "Din objektlagring är felkonfigurerad. Sekretessen för dina användare är i riskzonen." tags: moderation: + not_trendable: Kan inte trenda + not_usable: Inte användbar + pending_review: Väntar på granskning + review_requested: Granskning begärd reviewed: Granskat title: Status - trendable: + trendable: Kan trenda + unreviewed: Ogranskad + usable: Användbar name: Namn + newest: Nyaste + oldest: Äldsta + open: Visa offentligt 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 @@ -915,6 +948,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 @@ -1034,6 +1071,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 @@ -1053,6 +1091,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 @@ -1060,6 +1099,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: @@ -1080,6 +1120,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 @@ -1101,8 +1142,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. @@ -1113,6 +1156,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}. @@ -1122,6 +1166,12 @@ sv: use_security_key: Använd säkerhetsnyckel author_attribution: example_title: Exempeltext + hint_html: Skriver du nyheter eller bloggartiklar utanför Mastodon? Kontrollera hur du får krediteras när de delas på Mastodon. + instructions: 'Se till att den här koden finns i din artikels HTML:' + more_from_html: Mer från %{name} + s_blog: "%{name}s blogg" + then_instructions: Lägg sedan till domännamnet för publikationen i fältet nedan. + title: Författarattribution challenge: confirm: Fortsätt hint_html: "Tips: Vi frågar dig inte efter ditt lösenord igen under nästkommande timme." @@ -1318,6 +1368,44 @@ sv: merge_long: Behåll befintliga uppgifter och lägg till nya overwrite: Skriv över overwrite_long: Ersätt de nuvarande uppgifterna med de nya + overwrite_preambles: + blocking_html: + one: Du är på väg att ersätta din blockeringslista med upp till %{count} konto från %{filename}. + other: Du är på väg att ersätta din blockeringslista med upp till %{count} 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}. + domain_blocking_html: + one: Du är på väg att ersätta din blockeringslista med upp till %{count} domän från %{filename}. + other: Du är på väg att ersätta din blockeringslista med upp till %{count} domäner från %{filename}. + following_html: + one: Du är på väg till följ upp till %{count} konto från %{filename} och sluta följa någon annan. + other: Du är på väg till följ upp till %{count} konton från %{filename} och sluta följa någon annan. + lists_html: + one: Du är på väg att ersätta dina listor med innehållet i %{filename}. Upp till %{count} konto kommer att läggas till i nya listor. + other: Du är på väg att ersätta dina listor med innehållet i %{filename}. Upp till %{count} konton kommer att läggas till i nya listor. + muting_html: + one: Du är på väg att ersätta din lista med tystade konton med upp till %{count} konto från %{filename}. + other: Du är på väg att ersätta din lista med tystade konton med upp till %{count} konton från %{filename}. + preambles: + blocking_html: + one: Du är på väg att blockera med upp till %{count} konto från %{filename}. + other: Du är på väg att blockera med upp till %{count} konton från %{filename}. + bookmarks_html: + one: Du håller på att lägga upp till %{count} inlägg från %{filename} till dina bokmärken. + other: Du håller på att lägga upp till %{count} inlägg från %{filename} till dina bokmärken. + domain_blocking_html: + one: Du är på väg att blockera upp till %{count} domän från %{filename}. + other: Du är på väg att blockera upp till %{count} domäner från %{filename}. + following_html: + one: Du är på väg att följa upp till %{count} konto från %{filename}. + other: Du är på väg att följa upp till %{count} konton från %{filename}. + lists_html: + one: Du håller på att lägga upp till %{count} konto från %{filename} till dina listor. Nya listor kommer att skapas om det inte finns någon lista att lägga till. + other: Du håller på att lägga upp till %{count} 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: + one: Du är på väg att tysta upp till %{count} konto från %{filename}. + other: Du är på väg att tysta upp till %{count} konton 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: @@ -1402,6 +1490,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: @@ -1737,8 +1826,8 @@ sv: tags: does_not_match_previous_name: matchar inte det föregående namnet themes: - contrast: Hög kontrast - default: Mastodon + contrast: Mastodon (Hög kontrast) + default: Mastodon (Mörk) mastodon-light: Mastodon (ljust) system: Automatisk (använd systemtema) time: @@ -1883,6 +1972,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 c6ba60736d..ea039a2b99 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: ทำการกระทำ @@ -1147,9 +1148,11 @@ th: 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,6 +1343,32 @@ th: merge_long: เก็บระเบียนที่มีอยู่และเพิ่มระเบียนใหม่ overwrite: เขียนทับ overwrite_long: แทนที่ระเบียนปัจจุบันด้วยระเบียนใหม่ + overwrite_preambles: + blocking_html: + other: คุณกำลังจะ แทนที่รายการการปิดกั้นของคุณ ด้วยมากถึง %{count} บัญชี จาก %{filename} + bookmarks_html: + other: คุณกำลังจะ แทนที่ที่คั่นหน้าของคุณ ด้วยมากถึง %{count} โพสต์ จาก %{filename} + domain_blocking_html: + other: คุณกำลังจะ แทนที่รายการการปิดกั้นโดเมนของคุณ ด้วยมากถึง %{count} โดเมน จาก %{filename} + following_html: + other: คุณกำลังจะ ติดตาม มากถึง %{count} บัญชี จาก %{filename} และ หยุดการติดตามคนอื่นใด + lists_html: + other: คุณกำลังจะ แทนที่รายการของคุณ ด้วยเนื้อหาของ %{filename} จะเพิ่มมากถึง %{count} บัญชี ไปยังรายการใหม่ + muting_html: + other: คุณกำลังจะ แทนที่รายการบัญชีที่ซ่อนอยู่ของคุณ ด้วยมากถึง %{count} บัญชี จาก %{filename} + preambles: + blocking_html: + other: คุณกำลังจะ ปิดกั้น มากถึง %{count} บัญชี จาก %{filename} + bookmarks_html: + other: คุณกำลังจะเพิ่มมากถึง %{count} โพสต์ จาก %{filename} ไปยัง ที่คั่นหน้า ของคุณ + domain_blocking_html: + other: คุณกำลังจะ ปิดกั้น มากถึง %{count} โดเมน จาก %{filename} + following_html: + other: คุณกำลังจะ ติดตาม มากถึง %{count} บัญชี จาก %{filename} + lists_html: + other: คุณกำลังจะเพิ่มมากถึง %{count} บัญชี จาก %{filename} ไปยัง รายการ ของคุณ จะสร้างรายการใหม่หากไม่มีรายการที่จะเพิ่มไปยัง + muting_html: + other: คุณกำลังจะ ซ่อน มากถึง %{count} บัญชี จาก %{filename} preface: คุณสามารถนำเข้าข้อมูลที่คุณได้ส่งออกจากเซิร์ฟเวอร์อื่น เช่น รายการผู้คนที่คุณกำลังติดตามหรือกำลังปิดกั้น recent_imports: การนำเข้าล่าสุด states: diff --git a/config/locales/tr.yml b/config/locales/tr.yml index ee74f237ee..942ee2fbf2 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -1166,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 diff --git a/config/locales/uk.yml b/config/locales/uk.yml index dec4299fb9..e6a765267f 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -1202,9 +1202,11 @@ uk: 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: Далі diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 7c30c5b127..172ce55a3d 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -33,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ủ @@ -132,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: @@ -165,49 +165,49 @@ 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_user: Duyệt đăng ký + 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 change_role_user: Đổi vai trò confirm_user: Xác minh create_account_warning: Cảnh cáo create_announcement: Tạo thông báo mới - create_canonical_email_block: Chặn địa chỉ 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_email_domain_block: Chặn tên miền email create_ip_block: Chặn IP - create_unavailable_domain: Ngừng liên hợp + create_unavailable_domain: Bỏ liên hợp create_user_role: Tạo vai trò demote_user: Hạ vai trò destroy_announcement: Xóa thông báo - destroy_canonical_email_block: Bỏ chặn địa chỉ 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: Bỏ chặn IP destroy_status: Xóa tút - destroy_unavailable_domain: Tái liên hợp + 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 disable_sign_in_token_auth_user: Tắt xác minh bằng email cho người dùng disable_user: Vô hiệu hóa đăng nhập - enable_custom_emoji: Duyệt emoji + 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: Cho phép đăng nhập - memorialize_account: Đánh dấu tưởng niệm + memorialize_account: Gán tưởng niệm promote_user: Nâng vai trò - reject_appeal: Từ chối kháng cáo + 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 @@ -217,7 +217,7 @@ vi: sensitive_account: Gán nhạy cảm silence_account: Gán ẩn suspend_account: Gán vô hiệu hóa - unassigned_report: Báo cáo chưa xử lý + 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 @@ -230,64 +230,64 @@ vi: update_status: Cập nhật tút update_user_role: Cập nhật vai trò actions: - approve_appeal_html: "%{name} đã duyệt 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 địa chỉ 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} đã 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 với hash %{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} đã nâng vai trò của %{target}" - reject_appeal_html: "%{name} đã từ chối kháng cáo 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} bỏ chặn địa chỉ email của %{target}" - unsensitive_account_html: "%{name} đánh dấu nội dung của %{target} là bình thường" + 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_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. @@ -354,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: @@ -372,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 @@ -692,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 thành viên 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 @@ -819,7 +819,7 @@ vi: original_status: Tút gốc reblogs: Lượt đăng lại status_changed: Tút đã sửa - title: Toàn bộ tút + title: Tất cả tút trending: Xu hướng visibility: Hiển thị with_media: Có media @@ -832,8 +832,8 @@ vi: sensitive: "%{name} đã đánh dấu %{target} là nhạy cảm" silence: "%{name} đã ẩn %{target}" suspend: "%{name} đã vô hiệu hóa %{target}" - appeal_approved: Đã khiếu nại - appeal_pending: Đang kháng cáo + appeal_approved: Khiếu nại được chấp nhận + appeal_pending: Đang khiếu nại appeal_rejected: Khiếu nại bị từ chối system_checks: database_schema_check: @@ -1008,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ể duyệt 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! @@ -1148,9 +1148,11 @@ 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ài viết của bạn được ghi nhận khi 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" + 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 @@ -1205,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: Duyệt 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}" @@ -1386,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 @@ -1747,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 @@ -1778,7 +1780,7 @@ 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: @@ -1852,8 +1854,8 @@ vi: 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 vi phạm:' subject: diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 2654804697..209683e21c 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -596,7 +596,7 @@ zh-CN: actions_no_posts: 该举报没有相关嘟文可供删除 add_to_report: 增加更多举报内容 already_suspended_badges: - local: 已经在此服务器上暂停 + local: 已在此服务器上被封禁 remote: 已在其所属服务器被封禁 are_you_sure: 你确定吗? assign_to_self: 接管 @@ -1148,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: 继续 @@ -1699,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: 失去的关注 @@ -1876,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: 个性化 @@ -1884,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: 推荐关注 @@ -1907,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-TW.yml b/config/locales/zh-TW.yml index c461aabcdc..d8fef10816 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -1150,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: 繼續 diff --git a/config/routes.rb b/config/routes.rb index b04ffe096c..867aedf707 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -65,6 +65,13 @@ Rails.application.routes.draw do tokens: 'oauth/tokens' end + namespace :oauth do + # As this is borrowed from OpenID, the specification says we must also support + # POST for the userinfo endpoint: + # https://openid.net/specs/openid-connect-core-1_0.html#UserInfo + match 'userinfo', via: [:get, :post], to: 'userinfo#show', defaults: { format: 'json' } + end + scope path: '.well-known' do scope module: :well_known do get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 334e806227..517cd91e06 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -40,8 +40,10 @@ namespace :admin do end end - get '/settings', to: redirect('/admin/settings/branding') - get '/settings/edit', to: redirect('/admin/settings/branding') + with_options to: redirect('/admin/settings/branding') do + get '/settings' + get '/settings/edit' + end namespace :settings do resource :branding, only: [:show, :update], controller: 'branding' diff --git a/config/routes/api.rb b/config/routes/api.rb index c0e0e7a336..e72107257a 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -50,15 +50,17 @@ namespace :api, format: false do resources :list, only: :show end - get '/streaming', to: 'streaming#index' - get '/streaming/(*any)', to: 'streaming#index' + with_options to: 'streaming#index' do + get '/streaming' + get '/streaming/(*any)' + end resources :custom_emojis, only: [:index] resources :suggestions, only: [:index, :destroy] resources :scheduled_statuses, only: [:index, :show, :update, :destroy] resources :preferences, only: [:index] - resources :annual_reports, only: [:index] do + resources :annual_reports, only: [:index, :show] do member do post :read end @@ -353,7 +355,7 @@ namespace :api, format: false do namespace :web do resource :settings, only: [:update] resources :embeds, only: [:show] - resources :push_subscriptions, only: [:create] do + resources :push_subscriptions, only: [:create, :destroy] do member do put :update end diff --git a/config/translation.yml b/config/translation.yml new file mode 100644 index 0000000000..e074c5d0f2 --- /dev/null +++ b/config/translation.yml @@ -0,0 +1,7 @@ +shared: + deepl: + api_key: <%= ENV.fetch('DEEPL_API_KEY', nil) %> + plan: <%= ENV.fetch('DEEPL_PLAN', 'free') %> + libre_translate: + api_key: <%= ENV.fetch('LIBRE_TRANSLATE_API_KEY', nil) %> + endpoint: <%= ENV.fetch('LIBRE_TRANSLATE_ENDPOINT', nil) %> diff --git a/db/migrate/20241014010506_remove_duplicate_indexes.rb b/db/migrate/20241014010506_remove_duplicate_indexes.rb new file mode 100644 index 0000000000..50e0e6ffcf --- /dev/null +++ b/db/migrate/20241014010506_remove_duplicate_indexes.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class RemoveDuplicateIndexes < ActiveRecord::Migration[7.1] + def change + remove_index :account_aliases, :account_id + remove_index :account_relationship_severance_events, :account_id + remove_index :custom_filter_statuses, :status_id + remove_index :webauthn_credentials, :user_id + end +end diff --git a/db/migrate/20241022214312_add_untrusted_favourites_count_and_untrusted_reblogs_count_to_status_stat.rb b/db/migrate/20241022214312_add_untrusted_favourites_count_and_untrusted_reblogs_count_to_status_stat.rb new file mode 100644 index 0000000000..e34caff240 --- /dev/null +++ b/db/migrate/20241022214312_add_untrusted_favourites_count_and_untrusted_reblogs_count_to_status_stat.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddUntrustedFavouritesCountAndUntrustedReblogsCountToStatusStat < ActiveRecord::Migration[7.1] + def change + add_column :status_stats, :untrusted_favourites_count, :bigint, null: true + add_column :status_stats, :untrusted_reblogs_count, :bigint, null: true + end +end diff --git a/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb b/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb new file mode 100644 index 0000000000..c8ec30ad57 --- /dev/null +++ b/db/migrate/20241104082851_create_annual_report_statuses_per_account_counts.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class CreateAnnualReportStatusesPerAccountCounts < ActiveRecord::Migration[7.1] + def change + create_table :annual_report_statuses_per_account_counts do |t| # rubocop:disable Rails/CreateTableWithTimestamps + t.integer :year, null: false + t.bigint :account_id, null: false + t.bigint :statuses_count, null: false + end + + add_index :annual_report_statuses_per_account_counts, [:year, :account_id], unique: true + end +end diff --git a/db/post_migrate/20230803082451_add_unique_index_on_preview_cards_statuses.rb b/db/post_migrate/20230803082451_add_unique_index_on_preview_cards_statuses.rb index 4271f8c08a..c35ad80028 100644 --- a/db/post_migrate/20230803082451_add_unique_index_on_preview_cards_statuses.rb +++ b/db/post_migrate/20230803082451_add_unique_index_on_preview_cards_statuses.rb @@ -15,21 +15,10 @@ class AddUniqueIndexOnPreviewCardsStatuses < ActiveRecord::Migration[6.1] private - def supports_concurrent_reindex? - @supports_concurrent_reindex ||= begin - ActiveRecord::Base.connection.database_version >= 120_000 - end - end - def deduplicate_and_reindex! deduplicate_preview_cards! - if supports_concurrent_reindex? - safety_assured { execute 'REINDEX INDEX CONCURRENTLY preview_cards_statuses_pkey' } - else - remove_index :preview_cards_statuses, name: :preview_cards_statuses_pkey - add_index :preview_cards_statuses, [:status_id, :preview_card_id], name: :preview_cards_statuses_pkey, algorithm: :concurrently, unique: true - end + safety_assured { execute 'REINDEX INDEX CONCURRENTLY preview_cards_statuses_pkey' } rescue ActiveRecord::RecordNotUnique retry end diff --git a/db/schema.rb b/db/schema.rb index 99b097da38..f7bf68fdaa 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_10_07_071624) do +ActiveRecord::Schema[7.1].define(version: 2024_11_04_082851) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -21,7 +21,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false t.index ["account_id", "uri"], name: "index_account_aliases_on_account_id_and_uri", unique: true - t.index ["account_id"], name: "index_account_aliases_on_account_id" end create_table "account_conversations", force: :cascade do |t| @@ -99,7 +98,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.integer "followers_count", default: 0, null: false t.integer "following_count", default: 0, null: false t.index ["account_id", "relationship_severance_event_id"], name: "idx_on_account_id_relationship_severance_event_id_7bd82bf20e", unique: true - t.index ["account_id"], name: "index_account_relationship_severance_events_on_account_id" t.index ["relationship_severance_event_id"], name: "idx_on_relationship_severance_event_id_403f53e707" end @@ -262,6 +260,13 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.bigint "status_ids", array: true end + create_table "annual_report_statuses_per_account_counts", force: :cascade do |t| + t.integer "year", null: false + t.bigint "account_id", null: false + t.bigint "statuses_count", null: false + t.index ["year", "account_id"], name: "idx_on_year_account_id_ff3e167cef", unique: true + end + create_table "appeals", force: :cascade do |t| t.bigint "account_id", null: false t.bigint "account_warning_id", null: false @@ -397,7 +402,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.datetime "updated_at", null: false t.index ["custom_filter_id"], name: "index_custom_filter_statuses_on_custom_filter_id" t.index ["status_id", "custom_filter_id"], name: "index_custom_filter_statuses_on_status_id_and_custom_filter_id", unique: true - t.index ["status_id"], name: "index_custom_filter_statuses_on_status_id" end create_table "custom_filters", force: :cascade do |t| @@ -1024,6 +1028,8 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.bigint "favourites_count", default: 0, null: false t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.bigint "untrusted_favourites_count" + t.bigint "untrusted_reblogs_count" t.index ["status_id"], name: "index_status_stats_on_status_id", unique: true end @@ -1217,7 +1223,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_10_07_071624) do t.datetime "updated_at", precision: nil, null: false t.index ["external_id"], name: "index_webauthn_credentials_on_external_id", unique: true t.index ["user_id", "nickname"], name: "index_webauthn_credentials_on_user_id_and_nickname", unique: true - t.index ["user_id"], name: "index_webauthn_credentials_on_user_id" end create_table "webhooks", force: :cascade do |t| diff --git a/lib/active_record/with_recursive.rb b/lib/active_record/with_recursive.rb deleted file mode 100644 index 4bd3e81eed..0000000000 --- a/lib/active_record/with_recursive.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -# Add support for writing recursive CTEs in ActiveRecord - -# Initially from Lorin Thwaits (https://github.com/lorint) as per comment: -# https://github.com/vlado/activerecord-cte/issues/16#issuecomment-1433043310 - -# Modified from the above code to change the signature to -# `with_recursive(hash)` and extending CTE hash values to also includes arrays -# of values that get turned into UNION ALL expressions. - -# This implementation has been merged in Rails: https://github.com/rails/rails/pull/51601 - -module ActiveRecord - module QueryMethodsExtensions - def with_recursive(*args) - @with_is_recursive = true - check_if_method_has_arguments!(__callee__, args) - spawn.with_recursive!(*args) - end - - # Like #with_recursive but modifies the relation in place. - def with_recursive!(*args) # :nodoc: - self.with_values += args - @with_is_recursive = true - self - end - - private - - def build_with(arel) - return if with_values.empty? - - with_statements = with_values.map do |with_value| - raise ArgumentError, "Unsupported argument type: #{with_value} #{with_value.class}" unless with_value.is_a?(Hash) - - build_with_value_from_hash(with_value) - end - - # Was: arel.with(with_statements) - @with_is_recursive ? arel.with(:recursive, with_statements) : arel.with(with_statements) - end - - def build_with_value_from_hash(hash) - hash.map do |name, value| - Arel::Nodes::TableAlias.new(build_with_expression_from_value(value), name) - end - end - - def build_with_expression_from_value(value) - case value - when Arel::Nodes::SqlLiteral then Arel::Nodes::Grouping.new(value) - when ActiveRecord::Relation then value.arel - when Arel::SelectManager then value - when Array then value.map { |e| build_with_expression_from_value(e) }.reduce { |result, value| Arel::Nodes::UnionAll.new(result, value) } - else - raise ArgumentError, "Unsupported argument type: `#{value}` #{value.class}" - end - end - end -end - -ActiveSupport.on_load(:active_record) do - ActiveRecord::QueryMethods.prepend(ActiveRecord::QueryMethodsExtensions) -end diff --git a/lib/arel/union_parenthesizing.rb b/lib/arel/union_parenthesizing.rb deleted file mode 100644 index 852d8e92d8..0000000000 --- a/lib/arel/union_parenthesizing.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -# Fix an issue with `LIMIT` ocurring on the left side of a `UNION` causing syntax errors. -# See https://github.com/rails/rails/issues/40181 - -# The fix has been merged in ActiveRecord: https://github.com/rails/rails/pull/51549 -# TODO: drop this when available in ActiveRecord - -# rubocop:disable all -- This is a mostly vendored file - -module Arel - module Visitors - class ToSql - private - - def infix_value_with_paren(o, collector, value, suppress_parens = false) - collector << "( " unless suppress_parens - collector = if o.left.class == o.class - infix_value_with_paren(o.left, collector, value, true) - else - select_parentheses o.left, collector, false # Changed from `visit o.left, collector` - end - collector << value - collector = if o.right.class == o.class - infix_value_with_paren(o.right, collector, value, true) - else - select_parentheses o.right, collector, false # Changed from `visit o.right, collector` - end - collector << " )" unless suppress_parens - collector - end - - def select_parentheses(o, collector, always_wrap_selects = true) - if o.is_a?(Nodes::SelectStatement) && (always_wrap_selects || require_parentheses?(o)) - collector << "(" - visit o, collector - collector << ")" - collector - else - visit o, collector - end - end - - def require_parentheses?(o) - !o.orders.empty? || o.limit || o.offset - end - end - end -end - -# rubocop:enable all diff --git a/lib/mastodon/cli/accounts.rb b/lib/mastodon/cli/accounts.rb index e76735298f..c8e91224cf 100644 --- a/lib/mastodon/cli/accounts.rb +++ b/lib/mastodon/cli/accounts.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'set' require_relative 'base' module Mastodon::CLI @@ -322,7 +321,9 @@ module Mastodon::CLI unless skip_domains.empty? say('The following domains were not available during the check:', :yellow) - skip_domains.each { |domain| say(" #{domain}") } + shell.indent(2) do + skip_domains.each { |domain| say(domain) } + end end end diff --git a/lib/mastodon/cli/cache.rb b/lib/mastodon/cli/cache.rb index f32ab292ee..cfb6cba1ff 100644 --- a/lib/mastodon/cli/cache.rb +++ b/lib/mastodon/cli/cache.rb @@ -52,7 +52,7 @@ module Mastodon::CLI account.account_stat.tap do |account_stat| account_stat.following_count = account.active_relationships.count account_stat.followers_count = account.passive_relationships.count - account_stat.statuses_count = account.statuses.where.not(visibility: :direct).count + account_stat.statuses_count = account.statuses.not_direct_visibility.count account_stat.save if account_stat.changed? end @@ -60,7 +60,7 @@ module Mastodon::CLI def recount_status_stats(status) status.status_stat.tap do |status_stat| - status_stat.replies_count = status.replies.where.not(visibility: :direct).count + status_stat.replies_count = status.replies.not_direct_visibility.count status_stat.reblogs_count = status.reblogs.count status_stat.favourites_count = status.favourites.count diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb index 6b9107c8ad..7b2da8ef9f 100644 --- a/lib/mastodon/cli/email_domain_blocks.rb +++ b/lib/mastodon/cli/email_domain_blocks.rb @@ -7,11 +7,13 @@ module Mastodon::CLI class EmailDomainBlocks < Base desc 'list', 'List blocked e-mail domains' def list - EmailDomainBlock.where(parent_id: nil).find_each do |entry| - say(entry.domain.to_s, :white) + EmailDomainBlock.parents.find_each do |parent| + say(parent.domain.to_s, :white) - EmailDomainBlock.where(parent_id: entry.id).find_each do |child| - say(" #{child.domain}", :cyan) + shell.indent do + EmailDomainBlock.where(parent_id: parent.id).find_each do |child| + say(child.domain, :cyan) + end end end end diff --git a/lib/mastodon/cli/emoji.rb b/lib/mastodon/cli/emoji.rb index 4a8949de0e..206961f854 100644 --- a/lib/mastodon/cli/emoji.rb +++ b/lib/mastodon/cli/emoji.rb @@ -62,7 +62,9 @@ module Mastodon::CLI failed += 1 say('Failure/Error: ', :red) say(entry.full_name) - say(" #{custom_emoji.errors[:image].join(', ')}", :red) + shell.indent(2) do + say(custom_emoji.errors[:image].join(', '), :red) + end end end end diff --git a/lib/mastodon/cli/ip_blocks.rb b/lib/mastodon/cli/ip_blocks.rb index ef24f2e047..f1f40c99ce 100644 --- a/lib/mastodon/cli/ip_blocks.rb +++ b/lib/mastodon/cli/ip_blocks.rb @@ -80,9 +80,9 @@ module Mastodon::CLI end ip_blocks = if options[:force] - IpBlock.where('ip >>= ?', address) + IpBlock.containing(address) else - IpBlock.where('ip <<= ?', address) + IpBlock.contained_by(address) end if ip_blocks.empty? diff --git a/lib/mastodon/cli/media.rb b/lib/mastodon/cli/media.rb index 996b7fd92c..68420fb15d 100644 --- a/lib/mastodon/cli/media.rb +++ b/lib/mastodon/cli/media.rb @@ -6,6 +6,8 @@ module Mastodon::CLI class Media < Base include ActionView::Helpers::NumberHelper + class UnrecognizedOrphanType < StandardError; end + VALID_PATH_SEGMENTS_SIZE = [7, 10].freeze option :days, type: :numeric, default: 7, aliases: [:d] @@ -120,23 +122,10 @@ module Mastodon::CLI object.acl.put(acl: s3_permissions) if options[:fix_permissions] && !dry_run? path_segments = object.key.split('/') - path_segments.delete('cache') - - unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) - progress.log(pastel.yellow("Unrecognized file found: #{object.key}")) - next - end - - model_name = path_segments.first.classify - attachment_name = path_segments[1].singularize - record_id = path_segments[2...-2].join.to_i - file_name = path_segments.last - record = record_map.dig(model_name, record_id) - attachment = record&.public_send(attachment_name) progress.increment - next unless attachment.blank? || !attachment.variant?(file_name) + next unless orphaned_file?(path_segments, record_map) begin object.delete unless dry_run? @@ -148,6 +137,8 @@ module Mastodon::CLI rescue => e progress.log(pastel.red("Error processing #{object.key}: #{e}")) end + rescue UnrecognizedOrphanType + progress.log(pastel.yellow("Unrecognized file found: #{object.key}")) end end when :fog @@ -165,26 +156,10 @@ module Mastodon::CLI key = path.gsub("#{root_path}#{File::SEPARATOR}", '') path_segments = key.split(File::SEPARATOR) - path_segments.delete('cache') - - unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) - progress.log(pastel.yellow("Unrecognized file found: #{key}")) - next - end - - model_name = path_segments.first.classify - record_id = path_segments[2...-2].join.to_i - attachment_name = path_segments[1].singularize - file_name = path_segments.last - - next unless PRELOADED_MODELS.include?(model_name) - - record = model_name.constantize.find_by(id: record_id) - attachment = record&.public_send(attachment_name) progress.increment - next unless attachment.blank? || !attachment.variant?(file_name) + next unless orphaned_file?(path_segments) begin size = File.size(path) @@ -205,6 +180,8 @@ module Mastodon::CLI rescue => e progress.log(pastel.red("Error processing #{key}: #{e}")) end + rescue UnrecognizedOrphanType + progress.log(pastel.yellow("Unrecognized file found: #{path}")) end end @@ -364,5 +341,23 @@ module Mastodon::CLI model_map[model_name] = model_name.constantize.where(id: record_ids).index_by(&:id) end end + + def orphaned_file?(path_segments, record_map = nil) + path_segments.delete('cache') + + raise UnrecognizedOrphanType unless VALID_PATH_SEGMENTS_SIZE.include?(path_segments.size) + + model_name = path_segments.first.classify + record_id = path_segments[2...-2].join.to_i + attachment_name = path_segments[1].singularize + file_name = path_segments.last + + raise UnrecognizedOrphanType unless PRELOADED_MODELS.include?(model_name) + + record = record_map.present? ? record_map.dig(model_name, record_id) : model_name.constantize.find_by(id: record_id) + attachment = record&.public_send(attachment_name) + + attachment.blank? || !attachment.variant?(file_name) + end end end diff --git a/lib/mastodon/cli/progress_helper.rb b/lib/mastodon/cli/progress_helper.rb index 5634343796..da9527ffd7 100644 --- a/lib/mastodon/cli/progress_helper.rb +++ b/lib/mastodon/cli/progress_helper.rb @@ -5,7 +5,7 @@ dev_null = Logger.new('/dev/null') Rails.logger = dev_null ActiveRecord::Base.logger = dev_null ActiveJob::Base.logger = dev_null -HttpLog.configuration.logger = dev_null +HttpLog.configuration.logger = dev_null if defined?(HttpLog) Paperclip.options[:log] = false Chewy.logger = dev_null diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake index 2822f2eeb1..e1e2dd8194 100644 --- a/lib/tasks/mastodon.rake +++ b/lib/tasks/mastodon.rake @@ -596,7 +596,7 @@ def disable_log_stdout! Rails.logger = dev_null ActiveRecord::Base.logger = dev_null - HttpLog.configuration.logger = dev_null + HttpLog.configuration.logger = dev_null if defined?(HttpLog) Paperclip.options[:log] = false end diff --git a/lib/tasks/repo.rake b/lib/tasks/repo.rake index 539c44273f..c8f977f651 100644 --- a/lib/tasks/repo.rake +++ b/lib/tasks/repo.rake @@ -18,7 +18,7 @@ namespace :repo do url = "https://api.github.com/repos/#{REPOSITORY_NAME}/contributors?anon=1" - HttpLog.config.compact_log = true + HttpLog.config.compact_log = true if defined?(HttpLog) while url.present? response = HTTP.get(url) @@ -43,7 +43,7 @@ namespace :repo do path = Rails.root.join('CHANGELOG.md') tmp = Tempfile.new - HttpLog.config.compact_log = true + HttpLog.config.compact_log = true if defined?(HttpLog) begin File.open(path, 'r') do |file| diff --git a/lib/tasks/tests.rake b/lib/tasks/tests.rake index cb7fce3139..74269439dd 100644 --- a/lib/tasks/tests.rake +++ b/lib/tasks/tests.rake @@ -11,7 +11,7 @@ namespace :tests do '3_3_0' => 2020_12_18_054746, }.each do |release, version| ActiveRecord::Tasks::DatabaseTasks - .migration_connection + .migration_connection_pool .migration_context .migrate(version) Rake::Task["tests:migrations:populate_v#{release}"] diff --git a/package.json b/package.json index 0465b4d44d..7e42cf47b9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/mastodon", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.5.0", + "packageManager": "yarn@4.5.1", "engines": { "node": ">=18" }, @@ -48,7 +48,7 @@ "@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.402", "@reduxjs/toolkit": "^2.0.1", "@svgr/webpack": "^5.5.0", "arrow-key-navigation": "^1.2.0", @@ -180,13 +180,13 @@ "eslint": "^8.41.0", "eslint-define-config": "^2.0.0", "eslint-import-resolver-typescript": "^3.5.5", - "eslint-plugin-formatjs": "^4.10.1", + "eslint-plugin-formatjs": "^5.0.0", "eslint-plugin-import": "~2.30.0", "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-jsx-a11y": "~6.10.0", "eslint-plugin-promise": "~7.1.0", "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-hooks": "^5.0.0", "husky": "^9.0.11", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", diff --git a/spec/controllers/admin/confirmations_controller_spec.rb b/spec/controllers/admin/confirmations_controller_spec.rb index 9559160786..59ea0121ca 100644 --- a/spec/controllers/admin/confirmations_controller_spec.rb +++ b/spec/controllers/admin/confirmations_controller_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Admin::ConfirmationsController do describe 'POST #create' do it 'confirms the user' do - user = Fabricate(:user, confirmed_at: false) + user = Fabricate(:user, confirmed_at: nil) post :create, params: { account_id: user.account.id } expect(response).to redirect_to(admin_accounts_path) diff --git a/spec/controllers/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb deleted file mode 100644 index b6471e80b2..0000000000 --- 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/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb index 6118edf4e3..d1542128e7 100644 --- a/spec/controllers/auth/registrations_controller_spec.rb +++ b/spec/controllers/auth/registrations_controller_spec.rb @@ -233,17 +233,7 @@ RSpec.describe Auth::RegistrationsController do Setting.registrations_mode = 'open' Fabricate(:email_domain_block, allow_with_approval: true, domain: 'mail.example.com') allow(User).to receive(:skip_mx_check?).and_return(false) - - resolver = instance_double(Resolv::DNS, :timeouts= => nil) - - allow(resolver).to receive(:getresources) - .with('example.com', Resolv::DNS::Resource::IN::MX) - .and_return([instance_double(Resolv::DNS::Resource::MX, exchange: 'mail.example.com')]) - allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([]) - allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([]) - allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: '2.3.4.5')]) - allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([instance_double(Resolv::DNS::Resource::IN::AAAA, address: 'fd00::2')]) - allow(Resolv::DNS).to receive(:open).and_yield(resolver) + configure_mx(domain: 'example.com', exchange: 'mail.example.com') end it 'creates unapproved user and redirects to setup' do diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb index d9702251f4..121e4aa6c6 100644 --- a/spec/controllers/statuses_controller_spec.rb +++ b/spec/controllers/statuses_controller_spec.rb @@ -736,76 +736,4 @@ RSpec.describe StatusesController do 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_conversation_fabricator.rb b/spec/fabricators/account_conversation_fabricator.rb new file mode 100644 index 0000000000..6145ed8254 --- /dev/null +++ b/spec/fabricators/account_conversation_fabricator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +Fabricator(:account_conversation) do + account + conversation + status_ids { [Fabricate(:status).id] } +end diff --git a/spec/fabricators/ip_block_fabricator.rb b/spec/fabricators/ip_block_fabricator.rb new file mode 100644 index 0000000000..30c48b90c6 --- /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/fabricators/preview_card_trend_fabricator.rb b/spec/fabricators/preview_card_trend_fabricator.rb new file mode 100644 index 0000000000..14c126cc89 --- /dev/null +++ b/spec/fabricators/preview_card_trend_fabricator.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Fabricator(:preview_card_trend) do + preview_card +end diff --git a/spec/fabricators/status_trend_fabricator.rb b/spec/fabricators/status_trend_fabricator.rb new file mode 100644 index 0000000000..c775892b1f --- /dev/null +++ b/spec/fabricators/status_trend_fabricator.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +Fabricator(:status_trend) do + status + account +end diff --git a/spec/fabricators/tombstone_fabricator.rb b/spec/fabricators/tombstone_fabricator.rb new file mode 100644 index 0000000000..b4cab086af --- /dev/null +++ b/spec/fabricators/tombstone_fabricator.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +Fabricator(:tombstone) do + account + uri { sequence(:uri) { |i| "https://host.example/value/#{i}" } } +end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 90dc0d36de..486e8c19eb 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -230,28 +230,6 @@ RSpec.describe ApplicationHelper do end end - describe 'visibility_icon' do - it 'returns a globe icon for a public visible status' do - result = helper.visibility_icon Status.new(visibility: 'public') - expect(result).to match(/globe/) - end - - it 'returns an unlock icon for a unlisted visible status' do - result = helper.visibility_icon Status.new(visibility: 'unlisted') - expect(result).to match(/lock_open/) - end - - it 'returns a lock icon for a private visible status' do - result = helper.visibility_icon Status.new(visibility: 'private') - expect(result).to match(/lock/) - end - - it 'returns an at icon for a direct visible status' do - result = helper.visibility_icon Status.new(visibility: 'direct') - expect(result).to match(/alternate_email/) - end - end - describe 'title' do it 'returns site title on production environment' do Setting.site_title = 'site title' diff --git a/spec/helpers/database_helper_spec.rb b/spec/helpers/database_helper_spec.rb new file mode 100644 index 0000000000..9ea398bf4c --- /dev/null +++ b/spec/helpers/database_helper_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DatabaseHelper do + context 'when a replica is enabled' do + around do |example| + ClimateControl.modify REPLICA_DB_NAME: 'prod-relay-quantum-tunnel-mirror' do + example.run + end + end + + before { allow(ApplicationRecord).to receive(:connected_to) } + + describe '#with_read_replica' do + it 'uses the replica for connections' do + helper.with_read_replica { _x = 1 } + + expect(ApplicationRecord) + .to have_received(:connected_to).with(role: :reading, prevent_writes: true) + end + end + + describe '#with_primary' do + it 'uses the primary for connections' do + helper.with_primary { _x = 1 } + + expect(ApplicationRecord) + .to have_received(:connected_to).with(role: :writing) + end + end + end + + context 'when a replica is not enabled' do + around do |example| + ClimateControl.modify REPLICA_DB_NAME: nil do + example.run + end + end + + before { allow(ApplicationRecord).to receive(:connected_to) } + + describe '#with_read_replica' do + it 'does not use the replica for connections' do + helper.with_read_replica { _x = 1 } + + expect(ApplicationRecord) + .to_not have_received(:connected_to).with(role: :reading, prevent_writes: true) + end + end + + describe '#with_primary' do + it 'does not use the primary for connections' do + helper.with_primary { _x = 1 } + + expect(ApplicationRecord) + .to_not have_received(:connected_to).with(role: :writing) + end + end + end +end diff --git a/spec/helpers/formatting_helper_spec.rb b/spec/helpers/formatting_helper_spec.rb index 136a609b1c..5ff534e4eb 100644 --- a/spec/helpers/formatting_helper_spec.rb +++ b/spec/helpers/formatting_helper_spec.rb @@ -6,19 +6,57 @@ RSpec.describe FormattingHelper do 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 e5d85656a2..0c1d92b2da 100644 --- a/spec/lib/account_reach_finder_spec.rb +++ b/spec/lib/account_reach_finder_spec.rb @@ -38,16 +38,23 @@ RSpec.describe AccountReachFinder do 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/account_statuses_filter_spec.rb b/spec/lib/account_statuses_filter_spec.rb index 7774585124..351d3dae57 100644 --- a/spec/lib/account_statuses_filter_spec.rb +++ b/spec/lib/account_statuses_filter_spec.rb @@ -52,36 +52,24 @@ RSpec.describe AccountStatusesFilter do end shared_examples 'filter params' do - context 'with only_media param' do - let(:params) { { only_media: true } } + it 'respects param options in results' do + expect(results_for(only_media: true)) + .to all(satisfy(&:with_media?)) - it 'returns only statuses with media' do - expect(subject.all?(&:with_media?)).to be true - end + expect(results_for(tagged: tag.name)) + .to all(satisfy { |status| status.tags.include?(tag) }) + + expect(results_for(exclude_replies: true)) + .to all(satisfy { |status| !status.reply? }) + + expect(results_for(exclude_reblogs: true)) + .to all(satisfy { |status| !status.reblog? }) end - context 'with tagged param' do - let(:params) { { tagged: tag.name } } - - it 'returns only statuses with tag' do - expect(subject.all? { |s| s.tags.include?(tag) }).to be true - end - end - - context 'with exclude_replies param' do - let(:params) { { exclude_replies: true } } - - it 'returns only statuses that are not replies' do - expect(subject.none?(&:reply?)).to be true - end - end - - context 'with exclude_reblogs param' do - let(:params) { { exclude_reblogs: true } } - - it 'returns only statuses that are not reblogs' do - expect(subject.none?(&:reblog?)).to be true - end + def results_for(params) + described_class + .new(account, current_account, params) + .results end end diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 6f68984018..385628852b 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 @@ RSpec.describe ActivityPub::Activity::Block do }.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 - subject.perform - end - + describe '#perform' do + context 'when the recipient does not follow the sender' do it 'creates a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be true + subject.perform + + expect(sender) + .to be_blocking(recipient) end end - end - context 'when the recipient is already blocked' do - before do - sender.block!(recipient, uri: 'old') + context 'when the recipient is already blocked' do + before { sender.block!(recipient, uri: 'old') } + + it 'creates a block from sender to recipient and sets uri to last received block activity' do + subject.perform + + expect(sender) + .to be_blocking(recipient) + expect(sender.block_relationships.find_by(target_account: recipient).uri) + .to eq 'foo' + end end - describe '#perform' do - subject { described_class.new(json, sender) } + context 'when the recipient follows the sender' do + before { recipient.follow!(sender) } + + it 'creates a block from sender to recipient and ensures recipient not following sender' do + subject.perform + + expect(sender) + .to be_blocking(recipient) + expect(recipient) + .to_not be_following(sender) + 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 + + it 'does not create 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 'sets the uri to that of last received block activity' do - 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 - - describe '#perform' do - subject { described_class.new(json, sender) } - - before 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 - 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) } - - before do - subject.perform - end - - it 'does not create a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be false - end - - 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 ab69a4693d..6a9fb93bd1 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -974,6 +974,32 @@ RSpec.describe ActivityPub::Activity::Create do expect(poll.votes.first).to be_nil end end + + context 'with counts' do + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + likes: { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar', '/likes'].join, + type: 'Collection', + totalItems: 50, + }, + shares: { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar', '/shares'].join, + type: 'Collection', + totalItems: 100, + }, + } + end + + it 'uses the counts from the created object' do + status = sender.statuses.first + expect(status.untrusted_favourites_count).to eq 50 + expect(status.untrusted_reblogs_count).to eq 100 + end + end end context 'when object URI uses bearcaps' do diff --git a/spec/lib/activitypub/activity/update_spec.rb b/spec/lib/activitypub/activity/update_spec.rb index 87e96d2d1b..b829f3a5ad 100644 --- a/spec/lib/activitypub/activity/update_spec.rb +++ b/spec/lib/activitypub/activity/update_spec.rb @@ -115,5 +115,69 @@ RSpec.describe ActivityPub::Activity::Update do expect(status.edited_at).to be_nil end end + + context 'with a Note object' do + let(:updated) { nil } + let(:favourites) { 50 } + let(:reblogs) { 100 } + + let!(:status) { Fabricate(:status, uri: 'https://example.com/statuses/poll', account: sender) } + let(:json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'foo', + type: 'Update', + actor: sender.uri, + object: { + type: 'Note', + id: status.uri, + content: 'Foo', + updated: updated, + likes: { + id: "#{status.uri}/likes", + type: 'Collection', + totalItems: favourites, + }, + shares: { + id: "#{status.uri}/shares", + type: 'Collection', + totalItems: reblogs, + }, + }, + }.with_indifferent_access + end + + shared_examples 'updates counts' do + it 'updates the reblog count' do + expect(status.untrusted_reblogs_count).to eq reblogs + end + + it 'updates the favourites count' do + expect(status.untrusted_favourites_count).to eq favourites + end + end + + context 'with an implicit update' do + before do + status.update!(uri: ActivityPub::TagManager.instance.uri_for(status)) + subject.perform + end + + it_behaves_like 'updates counts' + end + + context 'with an explicit update' do + let(:favourites) { 150 } + let(:reblogs) { 200 } + let(:updated) { Time.now.utc.iso8601 } + + before do + status.update!(uri: ActivityPub::TagManager.instance.uri_for(status)) + subject.perform + end + + it_behaves_like 'updates counts' + end + end end end diff --git a/spec/lib/admin/system_check/database_schema_check_spec.rb b/spec/lib/admin/system_check/database_schema_check_spec.rb index 311d524956..3dc5763f92 100644 --- a/spec/lib/admin/system_check/database_schema_check_spec.rb +++ b/spec/lib/admin/system_check/database_schema_check_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Admin::SystemCheck::DatabaseSchemaCheck do context 'when database needs migration' do before do context = instance_double(ActiveRecord::MigrationContext, needs_migration?: true) - allow(ActiveRecord::Base.connection).to receive(:migration_context).and_return(context) + allow(ActiveRecord::Base.connection_pool).to receive(:migration_context).and_return(context) end it 'returns false' do @@ -24,7 +24,7 @@ RSpec.describe Admin::SystemCheck::DatabaseSchemaCheck do context 'when database does not need migration' do before do context = instance_double(ActiveRecord::MigrationContext, needs_migration?: false) - allow(ActiveRecord::Base.connection).to receive(:migration_context).and_return(context) + allow(ActiveRecord::Base.connection_pool).to receive(:migration_context).and_return(context) end it 'returns true' do diff --git a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb index e99d3cb4a7..0e31827912 100644 --- a/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb +++ b/spec/lib/annual_report/commonly_interacted_with_accounts_spec.rb @@ -32,7 +32,7 @@ RSpec.describe AnnualReport::CommonlyInteractedWithAccounts do expect(subject.generate) .to include( commonly_interacted_with_accounts: contain_exactly( - include(account_id: other_account.id, count: 2) + include(account_id: other_account.id.to_s, count: 2) ) ) end diff --git a/spec/lib/annual_report/most_reblogged_accounts_spec.rb b/spec/lib/annual_report/most_reblogged_accounts_spec.rb index 0280ba1992..2f04934e47 100644 --- a/spec/lib/annual_report/most_reblogged_accounts_spec.rb +++ b/spec/lib/annual_report/most_reblogged_accounts_spec.rb @@ -32,7 +32,7 @@ RSpec.describe AnnualReport::MostRebloggedAccounts do expect(subject.generate) .to include( most_reblogged_accounts: contain_exactly( - include(account_id: other_account.id, count: 2) + include(account_id: other_account.id.to_s, count: 2) ) ) end diff --git a/spec/lib/annual_report/percentiles_spec.rb b/spec/lib/annual_report/percentiles_spec.rb index 1d1df3166b..11df81cfb6 100644 --- a/spec/lib/annual_report/percentiles_spec.rb +++ b/spec/lib/annual_report/percentiles_spec.rb @@ -4,17 +4,20 @@ require 'rails_helper' RSpec.describe AnnualReport::Percentiles do describe '#generate' do - subject { described_class.new(account, Time.zone.now.year) } + subject { described_class.new(account, year) } + + let(:year) { Time.zone.now.year } context 'with an inactive account' do let(:account) { Fabricate :account } it 'builds a report for an account' do + described_class.prepare(year) + expect(subject.generate) .to include( percentiles: include( - followers: 0, - statuses: 0 + statuses: 100 ) ) end @@ -25,16 +28,15 @@ RSpec.describe AnnualReport::Percentiles do before do Fabricate.times 2, :status # Others as `account` - Fabricate.times 2, :follow # Others as `target_account` Fabricate.times 2, :status, account: account - Fabricate.times 2, :follow, target_account: account end it 'builds a report for an account' do + described_class.prepare(year) + expect(subject.generate) .to include( percentiles: include( - followers: 50, statuses: 50 ) ) diff --git a/spec/lib/annual_report/top_statuses_spec.rb b/spec/lib/annual_report/top_statuses_spec.rb index b956b03973..af29df1f65 100644 --- a/spec/lib/annual_report/top_statuses_spec.rb +++ b/spec/lib/annual_report/top_statuses_spec.rb @@ -39,9 +39,9 @@ RSpec.describe AnnualReport::TopStatuses do expect(subject.generate) .to include( top_statuses: include( - by_reblogs: reblogged_status.id, - by_favourites: favourited_status.id, - by_replies: replied_status.id + by_reblogs: reblogged_status.id.to_s, + by_favourites: favourited_status.id.to_s, + by_replies: replied_status.id.to_s ) ) end diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index b6696f4fd0..0abc515f34 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -3,6 +3,8 @@ require 'rails_helper' RSpec.describe FeedManager do + subject { described_class.instance } + before do |example| unless example.metadata[:skip_stub] stub_const 'FeedManager::MAX_ITEMS', 10 @@ -32,26 +34,26 @@ RSpec.describe FeedManager do it 'returns false for followee\'s status' do status = Fabricate(:status, text: 'Hello world', account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, status, bob)).to be false + expect(subject.filter?(:home, status, bob)).to be false end it 'returns false for reblog by followee' do status = Fabricate(:status, text: 'Hello world', account: jeff) reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, reblog, bob)).to be false + expect(subject.filter?(:home, reblog, bob)).to be false end it 'returns true for post from account who blocked me' do status = Fabricate(:status, text: 'Hello, World', account: alice) alice.block!(bob) - expect(described_class.instance.filter?(:home, status, bob)).to be true + expect(subject.filter?(:home, status, bob)).to be true end it 'returns true for post from blocked account' do status = Fabricate(:status, text: 'Hello, World', account: alice) bob.block!(alice) - expect(described_class.instance.filter?(:home, status, bob)).to be true + expect(subject.filter?(:home, status, bob)).to be true end it 'returns true for reblog by followee of blocked account' do @@ -59,7 +61,7 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) bob.block!(jeff) - expect(described_class.instance.filter?(:home, reblog, bob)).to be true + expect(subject.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog by followee of muted account' do @@ -67,7 +69,7 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) bob.mute!(jeff) - expect(described_class.instance.filter?(:home, reblog, bob)).to be true + expect(subject.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog by followee of someone who is blocking recipient' do @@ -75,14 +77,14 @@ RSpec.describe FeedManager do reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice) jeff.block!(bob) - expect(described_class.instance.filter?(:home, reblog, bob)).to be true + expect(subject.filter?(:home, reblog, bob)).to be true end it 'returns true for reblog from account with reblogs disabled' do status = Fabricate(:status, text: 'Hello world', account: jeff) reblog = Fabricate(:status, reblog: status, account: alice) bob.follow!(alice, reblogs: false) - expect(described_class.instance.filter?(:home, reblog, bob)).to be true + expect(subject.filter?(:home, reblog, bob)).to be true end it 'returns false for reply by followee to another followee' do @@ -90,49 +92,49 @@ RSpec.describe FeedManager do reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) bob.follow!(jeff) - expect(described_class.instance.filter?(:home, reply, bob)).to be false + expect(subject.filter?(:home, reply, bob)).to be false end it 'returns false for reply by followee to recipient' do status = Fabricate(:status, text: 'Hello world', account: bob) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, reply, bob)).to be false + expect(subject.filter?(:home, reply, bob)).to be false end it 'returns false for reply by followee to self' do status = Fabricate(:status, text: 'Hello world', account: alice) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, reply, bob)).to be false + expect(subject.filter?(:home, reply, bob)).to be false end it 'returns true for reply by followee to non-followed account' do status = Fabricate(:status, text: 'Hello world', account: jeff) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, reply, bob)).to be true + expect(subject.filter?(:home, reply, bob)).to be true end it 'returns true for the second reply by followee to a non-federated status' do reply = Fabricate(:status, text: 'Reply 1', reply: true, account: alice) second_reply = Fabricate(:status, text: 'Reply 2', thread: reply, account: alice) bob.follow!(alice) - expect(described_class.instance.filter?(:home, second_reply, bob)).to be true + expect(subject.filter?(:home, second_reply, bob)).to be true end it 'returns false for status by followee mentioning another account' do bob.follow!(alice) jeff.follow!(alice) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(described_class.instance.filter?(:home, status, bob)).to be false + expect(subject.filter?(:home, status, bob)).to be false end it 'returns true for status by followee mentioning blocked account' do bob.block!(jeff) bob.follow!(alice) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(described_class.instance.filter?(:home, status, bob)).to be true + expect(subject.filter?(:home, status, bob)).to be true end it 'returns true for status by followee mentioning muted account' do @@ -147,19 +149,19 @@ RSpec.describe FeedManager do alice.follow!(jeff) status = Fabricate(:status, text: 'Hello world', account: bob) reblog = Fabricate(:status, reblog: status, account: jeff) - expect(described_class.instance.filter?(:home, reblog, alice)).to be true + expect(subject.filter?(:home, reblog, alice)).to be true end it 'returns true for German post when follow is set to English only' do alice.follow!(bob, languages: %w(en)) status = Fabricate(:status, text: 'Hallo Welt', account: bob, language: 'de') - expect(described_class.instance.filter?(:home, status, alice)).to be true + expect(subject.filter?(:home, status, alice)).to be true end it 'returns false for German post when follow is set to German' do alice.follow!(bob, languages: %w(de)) status = Fabricate(:status, text: 'Hallo Welt', account: bob, language: 'de') - expect(described_class.instance.filter?(:home, status, alice)).to be false + expect(subject.filter?(:home, status, alice)).to be false end it 'returns true for post from followee on exclusive list' do @@ -168,7 +170,7 @@ RSpec.describe FeedManager do list.accounts << bob allow(List).to receive(:where).and_return(list) status = Fabricate(:status, text: 'I post a lot', account: bob) - expect(described_class.instance.filter?(:home, status, alice)).to be true + expect(subject.filter?(:home, status, alice)).to be true end it 'returns true for reblog from followee on exclusive list' do @@ -178,7 +180,7 @@ RSpec.describe FeedManager do allow(List).to receive(:where).and_return(list) status = Fabricate(:status, text: 'I post a lot', account: bob) reblog = Fabricate(:status, reblog: status, account: jeff) - expect(described_class.instance.filter?(:home, reblog, alice)).to be true + expect(subject.filter?(:home, reblog, alice)).to be true end it 'returns false for post from followee on non-exclusive list' do @@ -186,7 +188,7 @@ RSpec.describe FeedManager do alice.follow!(bob) list.accounts << bob status = Fabricate(:status, text: 'I post a lot', account: bob) - expect(described_class.instance.filter?(:home, status, alice)).to be false + expect(subject.filter?(:home, status, alice)).to be false end it 'returns false for reblog from followee on non-exclusive list' do @@ -195,7 +197,7 @@ RSpec.describe FeedManager do list.accounts << jeff status = Fabricate(:status, text: 'I post a lot', account: bob) reblog = Fabricate(:status, reblog: status, account: jeff) - expect(described_class.instance.filter?(:home, reblog, alice)).to be false + expect(subject.filter?(:home, reblog, alice)).to be false end end @@ -203,27 +205,27 @@ RSpec.describe FeedManager do it 'returns true for status that mentions blocked account' do bob.block!(jeff) status = PostStatusService.new.call(alice, text: 'Hey @jeff') - expect(described_class.instance.filter?(:mentions, status, bob)).to be true + expect(subject.filter?(:mentions, status, bob)).to be true end it 'returns true for status that replies to a blocked account' do status = Fabricate(:status, text: 'Hello world', account: jeff) reply = Fabricate(:status, text: 'Nay', thread: status, account: alice) bob.block!(jeff) - expect(described_class.instance.filter?(:mentions, reply, bob)).to be true + expect(subject.filter?(:mentions, reply, bob)).to be true end it 'returns false for status by limited account who recipient is not following' do status = Fabricate(:status, text: 'Hello world', account: alice) alice.silence! - expect(described_class.instance.filter?(:mentions, status, bob)).to be false + expect(subject.filter?(:mentions, status, bob)).to be false end it 'returns false for status by followed limited account' do status = Fabricate(:status, text: 'Hello world', account: alice) alice.silence! bob.follow!(alice) - expect(described_class.instance.filter?(:mentions, status, bob)).to be false + expect(subject.filter?(:mentions, status, bob)).to be false end end end @@ -235,7 +237,7 @@ RSpec.describe FeedManager do members = Array.new(described_class::MAX_ITEMS) { |count| [count, count] } redis.zadd("feed:home:#{account.id}", members) - described_class.instance.push_to_home(account, status) + subject.push_to_home(account, status) expect(redis.zcard("feed:home:#{account.id}")).to eq described_class::MAX_ITEMS end @@ -246,7 +248,7 @@ RSpec.describe FeedManager do reblogged = Fabricate(:status) reblog = Fabricate(:status, reblog: reblogged) - expect(described_class.instance.push_to_home(account, reblog)).to be true + expect(subject.push_to_home(account, reblog)).to be true end it 'does not save a new reblog of a recent status' do @@ -254,9 +256,9 @@ RSpec.describe FeedManager do reblogged = Fabricate(:status) reblog = Fabricate(:status, reblog: reblogged) - described_class.instance.push_to_home(account, reblogged) + subject.push_to_home(account, reblogged) - expect(described_class.instance.push_to_home(account, reblog)).to be false + expect(subject.push_to_home(account, reblog)).to be false end it 'saves a new reblog of an old status' do @@ -264,14 +266,14 @@ RSpec.describe FeedManager do reblogged = Fabricate(:status) reblog = Fabricate(:status, reblog: reblogged) - described_class.instance.push_to_home(account, reblogged) + subject.push_to_home(account, reblogged) # Fill the feed with intervening statuses described_class::REBLOG_FALLOFF.times do - described_class.instance.push_to_home(account, Fabricate(:status)) + subject.push_to_home(account, Fabricate(:status)) end - expect(described_class.instance.push_to_home(account, reblog)).to be true + expect(subject.push_to_home(account, reblog)).to be true end it 'does not save a new reblog of a recently-reblogged status' do @@ -280,10 +282,10 @@ RSpec.describe FeedManager do reblogs = Array.new(2) { Fabricate(:status, reblog: reblogged) } # The first reblog will be accepted - described_class.instance.push_to_home(account, reblogs.first) + subject.push_to_home(account, reblogs.first) # The second reblog should be ignored - expect(described_class.instance.push_to_home(account, reblogs.last)).to be false + expect(subject.push_to_home(account, reblogs.last)).to be false end it 'saves a new reblog of a recently-reblogged status when previous reblog has been deleted' do @@ -292,15 +294,15 @@ RSpec.describe FeedManager do old_reblog = Fabricate(:status, reblog: reblogged) # The first reblog should be accepted - expect(described_class.instance.push_to_home(account, old_reblog)).to be true + expect(subject.push_to_home(account, old_reblog)).to be true # The first reblog should be successfully removed - expect(described_class.instance.unpush_from_home(account, old_reblog)).to be true + expect(subject.unpush_from_home(account, old_reblog)).to be true reblog = Fabricate(:status, reblog: reblogged) # The second reblog should be accepted - expect(described_class.instance.push_to_home(account, reblog)).to be true + expect(subject.push_to_home(account, reblog)).to be true end it 'does not save a new reblog of a multiply-reblogged-then-unreblogged status' do @@ -309,14 +311,14 @@ RSpec.describe FeedManager do reblogs = Array.new(3) { Fabricate(:status, reblog: reblogged) } # Accept the reblogs - described_class.instance.push_to_home(account, reblogs[0]) - described_class.instance.push_to_home(account, reblogs[1]) + subject.push_to_home(account, reblogs[0]) + subject.push_to_home(account, reblogs[1]) # Unreblog the first one - described_class.instance.unpush_from_home(account, reblogs[0]) + subject.unpush_from_home(account, reblogs[0]) # The last reblog should still be ignored - expect(described_class.instance.push_to_home(account, reblogs.last)).to be false + expect(subject.push_to_home(account, reblogs.last)).to be false end it 'saves a new reblog of a long-ago-reblogged status' do @@ -325,15 +327,15 @@ RSpec.describe FeedManager do reblogs = Array.new(2) { Fabricate(:status, reblog: reblogged) } # The first reblog will be accepted - described_class.instance.push_to_home(account, reblogs.first) + subject.push_to_home(account, reblogs.first) # Fill the feed with intervening statuses described_class::REBLOG_FALLOFF.times do - described_class.instance.push_to_home(account, Fabricate(:status)) + subject.push_to_home(account, Fabricate(:status)) end # The second reblog should also be accepted - expect(described_class.instance.push_to_home(account, reblogs.last)).to be true + expect(subject.push_to_home(account, reblogs.last)).to be true end end @@ -341,9 +343,9 @@ RSpec.describe FeedManager do account = Fabricate(:account) reblog = Fabricate(:status) status = Fabricate(:status, reblog: reblog) - described_class.instance.push_to_home(account, status) + subject.push_to_home(account, status) - expect(described_class.instance.push_to_home(account, reblog)).to be false + expect(subject.push_to_home(account, reblog)).to be false end end @@ -366,9 +368,9 @@ RSpec.describe FeedManager do it "does not push when the given status's reblog is already inserted" do reblog = Fabricate(:status) status = Fabricate(:status, reblog: reblog) - described_class.instance.push_to_list(list, status) + subject.push_to_list(list, status) - expect(described_class.instance.push_to_list(list, reblog)).to be false + expect(subject.push_to_list(list, reblog)).to be false end context 'when replies policy is set to no replies' do @@ -378,19 +380,19 @@ RSpec.describe FeedManager do it 'pushes statuses that are not replies' do status = Fabricate(:status, text: 'Hello world', account: bob) - expect(described_class.instance.push_to_list(list, status)).to be true + expect(subject.push_to_list(list, status)).to be true end it 'pushes statuses that are replies to list owner' do status = Fabricate(:status, text: 'Hello world', account: owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end it 'does not push replies to another member of the list' do status = Fabricate(:status, text: 'Hello world', account: alice) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be false + expect(subject.push_to_list(list, reply)).to be false end end @@ -401,25 +403,25 @@ RSpec.describe FeedManager do it 'pushes statuses that are not replies' do status = Fabricate(:status, text: 'Hello world', account: bob) - expect(described_class.instance.push_to_list(list, status)).to be true + expect(subject.push_to_list(list, status)).to be true end it 'pushes statuses that are replies to list owner' do status = Fabricate(:status, text: 'Hello world', account: owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end it 'pushes replies to another member of the list' do status = Fabricate(:status, text: 'Hello world', account: alice) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end it 'does not push replies to someone not a member of the list' do status = Fabricate(:status, text: 'Hello world', account: eve) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be false + expect(subject.push_to_list(list, reply)).to be false end end @@ -430,25 +432,25 @@ RSpec.describe FeedManager do it 'pushes statuses that are not replies' do status = Fabricate(:status, text: 'Hello world', account: bob) - expect(described_class.instance.push_to_list(list, status)).to be true + expect(subject.push_to_list(list, status)).to be true end it 'pushes statuses that are replies to list owner' do status = Fabricate(:status, text: 'Hello world', account: owner) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end it 'pushes replies to another member of the list' do status = Fabricate(:status, text: 'Hello world', account: alice) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end it 'pushes replies to someone not a member of the list' do status = Fabricate(:status, text: 'Hello world', account: eve) reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) - expect(described_class.instance.push_to_list(list, reply)).to be true + expect(subject.push_to_list(list, reply)).to be true end end end @@ -458,9 +460,9 @@ RSpec.describe FeedManager do account = Fabricate(:account, id: 0) reblog = Fabricate(:status) status = Fabricate(:status, reblog: reblog) - described_class.instance.push_to_home(account, status) + subject.push_to_home(account, status) - described_class.instance.merge_into_home(account, reblog.account) + subject.merge_into_home(account, reblog.account) expect(redis.zscore('feed:home:0', reblog.id)).to be_nil end @@ -473,14 +475,14 @@ RSpec.describe FeedManager do reblogged = Fabricate(:status) status = Fabricate(:status, reblog: reblogged) - described_class.instance.push_to_home(receiver, reblogged) - described_class::REBLOG_FALLOFF.times { described_class.instance.push_to_home(receiver, Fabricate(:status)) } - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, reblogged) + described_class::REBLOG_FALLOFF.times { subject.push_to_home(receiver, Fabricate(:status)) } + subject.push_to_home(receiver, status) # The reblogging status should show up under normal conditions. expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) - described_class.instance.unpush_from_home(receiver, status) + subject.unpush_from_home(receiver, status) # Restore original status expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) @@ -491,12 +493,12 @@ RSpec.describe FeedManager do reblogged = Fabricate(:status) status = Fabricate(:status, reblog: reblogged) - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, status) # The reblogging status should show up under normal conditions. expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [status.id.to_s] - described_class.instance.unpush_from_home(receiver, status) + subject.unpush_from_home(receiver, status) expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to be_empty end @@ -506,14 +508,14 @@ RSpec.describe FeedManager do reblogs = Array.new(3) { Fabricate(:status, reblog: reblogged) } reblogs.each do |reblog| - described_class.instance.push_to_home(receiver, reblog) + subject.push_to_home(receiver, reblog) end # The reblogging status should show up under normal conditions. expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [reblogs.first.id.to_s] reblogs[0...-1].each do |reblog| - described_class.instance.unpush_from_home(receiver, reblog) + subject.unpush_from_home(receiver, reblog) end expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [reblogs.last.id.to_s] @@ -522,10 +524,10 @@ RSpec.describe FeedManager do it 'sends push updates' do status = Fabricate(:status) - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, status) allow(redis).to receive_messages(publish: nil) - described_class.instance.unpush_from_home(receiver, status) + subject.unpush_from_home(receiver, status) deletion = Oj.dump(event: :delete, payload: status.id.to_s) expect(redis).to have_received(:publish).with("timeline:#{receiver.id}", deletion) @@ -539,9 +541,9 @@ RSpec.describe FeedManager do it 'leaves a tagged status' do status = Fabricate(:status) status.tags << tag - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, status) - described_class.instance.unmerge_tag_from_home(tag, receiver) + subject.unmerge_tag_from_home(tag, receiver) expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) end @@ -552,9 +554,9 @@ RSpec.describe FeedManager do status = Fabricate(:status, account: followee) status.tags << tag - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, status) - described_class.instance.unmerge_tag_from_home(tag, receiver) + subject.unmerge_tag_from_home(tag, receiver) expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) end @@ -562,9 +564,9 @@ RSpec.describe FeedManager do it 'remains a tagged status written by receiver' do status = Fabricate(:status, account: receiver) status.tags << tag - described_class.instance.push_to_home(receiver, status) + subject.push_to_home(receiver, status) - described_class.instance.unmerge_tag_from_home(tag, receiver) + subject.unmerge_tag_from_home(tag, receiver) expect(redis.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s) end @@ -595,7 +597,7 @@ RSpec.describe FeedManager do end it 'correctly cleans the home timeline' do - described_class.instance.clear_from_home(account, target_account) + subject.clear_from_home(account, target_account) expect(redis.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_from_followed_account_first.id.to_s, status_from_followed_account_next.id.to_s] end diff --git a/spec/lib/plain_text_formatter_spec.rb b/spec/lib/plain_text_formatter_spec.rb index b22f473d0c..4683e15093 100644 --- a/spec/lib/plain_text_formatter_spec.rb +++ b/spec/lib/plain_text_formatter_spec.rb @@ -7,7 +7,7 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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 @@ RSpec.describe PlainTextFormatter do 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/vacuum/access_tokens_vacuum_spec.rb b/spec/lib/vacuum/access_tokens_vacuum_spec.rb index 54760c41bd..8768f6b2dc 100644 --- a/spec/lib/vacuum/access_tokens_vacuum_spec.rb +++ b/spec/lib/vacuum/access_tokens_vacuum_spec.rb @@ -14,32 +14,24 @@ RSpec.describe Vacuum::AccessTokensVacuum do 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 + expect { revoked_access_token.reload } + .to raise_error ActiveRecord::RecordNotFound + expect { expired_access_token.reload } + .to raise_error ActiveRecord::RecordNotFound - it 'deletes expired access tokens' do - expect { expired_access_token.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 'deletes revoked access grants' do - expect { revoked_access_grant.reload }.to raise_error ActiveRecord::RecordNotFound - end + expect { active_access_token.reload } + .to_not raise_error - it 'deletes expired access grants' do - expect { expired_access_grant.reload }.to raise_error ActiveRecord::RecordNotFound - end - - it 'does not delete active access tokens' do - expect { active_access_token.reload }.to_not raise_error - end - - 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 867dbe4020..4a025352cb 100644 --- a/spec/lib/vacuum/backups_vacuum_spec.rb +++ b/spec/lib/vacuum/backups_vacuum_spec.rb @@ -11,16 +11,13 @@ RSpec.describe Vacuum::BackupsVacuum do 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 ede1e3c360..38459a558f 100644 --- a/spec/lib/vacuum/feeds_vacuum_spec.rb +++ b/spec/lib/vacuum/feeds_vacuum_spec.rb @@ -14,11 +14,11 @@ RSpec.describe Vacuum::FeedsVacuum do 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 1039c36cea..f7749038cb 100644 --- a/spec/lib/vacuum/media_attachments_vacuum_spec.rb +++ b/spec/lib/vacuum/media_attachments_vacuum_spec.rb @@ -17,9 +17,9 @@ RSpec.describe Vacuum::MediaAttachmentsVacuum do 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 9dbdf0bc2f..caeedd3269 100644 --- a/spec/lib/vacuum/preview_cards_vacuum_spec.rb +++ b/spec/lib/vacuum/preview_cards_vacuum_spec.rb @@ -15,24 +15,22 @@ RSpec.describe Vacuum::PreviewCardsVacuum do 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 d5c0139506..1fff864879 100644 --- a/spec/lib/vacuum/statuses_vacuum_spec.rb +++ b/spec/lib/vacuum/statuses_vacuum_spec.rb @@ -15,24 +15,20 @@ RSpec.describe Vacuum::StatusesVacuum do 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/models/account_alias_spec.rb b/spec/models/account_alias_spec.rb index fc8c6bd250..17c83967a4 100644 --- a/spec/models/account_alias_spec.rb +++ b/spec/models/account_alias_spec.rb @@ -8,4 +8,26 @@ RSpec.describe AccountAlias do it { is_expected.to normalize(:acct).from(' @username@domain ').to('username@domain') } end end + + describe 'Validations' do + subject { described_class.new(account:) } + + let(:account) { Fabricate :account } + + it { is_expected.to_not allow_values(nil, '').for(:uri).against(:acct).with_message(not_found_message) } + + it { is_expected.to_not allow_values(account_uri).for(:uri).against(:acct).with_message(self_move_message) } + + def account_uri + ActivityPub::TagManager.instance.uri_for(subject.account) + end + + def not_found_message + I18n.t('migrations.errors.not_found') + end + + def self_move_message + I18n.t('migrations.errors.move_to_self') + end + end end diff --git a/spec/models/account_migration_spec.rb b/spec/models/account_migration_spec.rb index d658915ce3..b92771e8f5 100644 --- a/spec/models/account_migration_spec.rb +++ b/spec/models/account_migration_spec.rb @@ -9,8 +9,8 @@ RSpec.describe AccountMigration do end end - describe 'validations' do - subject { described_class.new(account: source_account, acct: target_acct) } + describe 'Validations' do + subject { Fabricate.build :account_migration, account: source_account } let(:source_account) { Fabricate(:account) } let(:target_acct) { target_account.acct } @@ -26,9 +26,7 @@ RSpec.describe AccountMigration do allow(service_double).to receive(:call).with(target_acct, anything).and_return(target_account) end - it 'passes validations' do - expect(subject).to be_valid - end + it { is_expected.to allow_value(target_account.acct).for(:acct) } end context 'with unresolvable account' do @@ -40,17 +38,13 @@ RSpec.describe AccountMigration do allow(service_double).to receive(:call).with(target_acct, anything).and_return(nil) end - it 'has errors on acct field' do - expect(subject).to model_have_error_on_field(:acct) - end + it { is_expected.to_not allow_value(target_acct).for(:acct) } end context 'with a space in the domain part' do let(:target_acct) { 'target@remote. org' } - it 'has errors on acct field' do - expect(subject).to model_have_error_on_field(:acct) - end + it { is_expected.to_not allow_value(target_acct).for(:acct) } end end end diff --git a/spec/models/account_moderation_note_spec.rb b/spec/models/account_moderation_note_spec.rb index 079774c492..f3bcff4cd6 100644 --- a/spec/models/account_moderation_note_spec.rb +++ b/spec/models/account_moderation_note_spec.rb @@ -3,29 +3,24 @@ require 'rails_helper' RSpec.describe AccountModerationNote do - describe 'chronological scope' do - it 'returns account moderation notes oldest to newest' do - account = Fabricate(:account) - note1 = Fabricate(:account_moderation_note, target_account: account) - note2 = Fabricate(:account_moderation_note, target_account: account) + describe 'Scopes' do + describe '.chronological' do + it 'returns account moderation notes oldest to newest' do + account = Fabricate(:account) + note1 = Fabricate(:account_moderation_note, target_account: account) + note2 = Fabricate(:account_moderation_note, target_account: account) - expect(account.targeted_moderation_notes.chronological).to eq [note1, note2] + expect(account.targeted_moderation_notes.chronological).to eq [note1, note2] + end end end - describe 'validations' do - it 'is invalid if the content is empty' do - report = Fabricate.build(:account_moderation_note, content: '') - expect(report.valid?).to be false - end + describe 'Validations' do + subject { Fabricate.build :account_moderation_note } - it 'is invalid if content is longer than character limit' do - report = Fabricate.build(:account_moderation_note, content: comment_over_limit) - expect(report.valid?).to be false - end - - def comment_over_limit - Faker::Lorem.paragraph_by_chars(number: described_class::CONTENT_SIZE_LIMIT * 2) + describe 'content' do + it { is_expected.to_not allow_value('').for(:content) } + it { is_expected.to validate_length_of(:content).is_at_most(described_class::CONTENT_SIZE_LIMIT) } end end end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index a8f6ed7493..7a5deed599 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -10,64 +10,6 @@ RSpec.describe Account do let(:bob) { Fabricate(:account, username: 'bob') } - describe '#suspended_locally?' do - context 'when the account is not suspended' do - it 'returns false' do - expect(subject.suspended_locally?).to be false - end - end - - context 'when the account is suspended locally' do - before do - subject.update!(suspended_at: 1.day.ago, suspension_origin: :local) - end - - it 'returns true' do - expect(subject.suspended_locally?).to be true - end - end - - context 'when the account is suspended remotely' do - before do - subject.update!(suspended_at: 1.day.ago, suspension_origin: :remote) - end - - it 'returns false' do - expect(subject.suspended_locally?).to be false - end - end - end - - describe '#suspend!' do - it 'marks the account as suspended and creates a deletion request' do - expect { subject.suspend! } - .to change(subject, :suspended?).from(false).to(true) - .and change(subject, :suspended_locally?).from(false).to(true) - .and(change { AccountDeletionRequest.exists?(account: subject) }.from(false).to(true)) - end - - context 'when the account is of a local user' do - subject { local_user_account } - - let!(:local_user_account) { Fabricate(:user, email: 'foo+bar@domain.org').account } - - it 'creates a canonical domain block' do - subject.suspend! - expect(CanonicalEmailBlock.block?(subject.user_email)).to be true - end - - context 'when a canonical domain block already exists for that email' do - before do - Fabricate(:canonical_email_block, email: subject.user_email) - end - - it 'does not raise an error' do - expect { subject.suspend! }.to_not raise_error - end - end - end - end - describe '#follow!' do it 'creates a follow' do follow = subject.follow!(bob) @@ -208,16 +150,16 @@ RSpec.describe Account do end end - context 'when last_webfingered_at is more than 24 hours before' do - let(:last_webfingered_at) { 25.hours.ago } + context 'when last_webfingered_at is before the threshold' do + let(:last_webfingered_at) { (described_class::STALE_THRESHOLD + 1.hour).ago } it 'returns true' do expect(account.possibly_stale?).to be true end end - context 'when last_webfingered_at is less than 24 hours before' do - let(:last_webfingered_at) { 23.hours.ago } + context 'when last_webfingered_at is after the threshold' do + let(:last_webfingered_at) { (described_class::STALE_THRESHOLD - 1.hour).ago } it 'returns false' do expect(account.possibly_stale?).to be false @@ -752,26 +694,42 @@ RSpec.describe Account do end end - describe '#prepare_contents' do - subject { Fabricate.build :account, domain: domain, note: ' padded note ', display_name: ' padded name ' } + describe 'Callbacks' do + describe 'Stripping content when required' do + context 'with a remote account' do + subject { Fabricate.build :account, domain: 'host.example', note: ' note ', display_name: ' display name ' } - context 'with local account' do - let(:domain) { nil } - - it 'strips values' do - expect { subject.valid? } - .to change(subject, :note).to('padded note') - .and(change(subject, :display_name).to('padded name')) + it 'preserves content' do + expect { subject.valid? } + .to not_change(subject, :note) + .and not_change(subject, :display_name) + end end - end - context 'with remote account' do - let(:domain) { 'host.example' } + context 'with a local account' do + subject { Fabricate.build :account, domain: nil, note:, display_name: } - it 'preserves values' do - expect { subject.valid? } - .to not_change(subject, :note) - .and(not_change(subject, :display_name)) + context 'with populated fields' do + let(:note) { ' note ' } + let(:display_name) { ' display name ' } + + it 'strips content' do + expect { subject.valid? } + .to change(subject, :note).to('note') + .and change(subject, :display_name).to('display name') + end + end + + context 'with empty fields' do + let(:note) { nil } + let(:display_name) { nil } + + it 'preserves content' do + expect { subject.valid? } + .to not_change(subject, :note) + .and not_change(subject, :display_name) + end + end end end end @@ -826,22 +784,19 @@ RSpec.describe Account do end end - describe 'validations' do + describe 'Validations' do it { is_expected.to validate_presence_of(:username) } - context 'when is local' do - it 'is invalid if the username is not unique in case-insensitive comparison among local accounts' do - _account = Fabricate(:account, username: 'the_doctor') - non_unique_account = Fabricate.build(:account, username: 'the_Doctor') - non_unique_account.valid? - expect(non_unique_account).to model_have_error_on_field(:username) + context 'when account is local' do + subject { Fabricate.build :account, domain: nil } + + context 'with an existing differently-cased username account' do + before { Fabricate :account, username: 'the_doctor' } + + it { is_expected.to_not allow_value('the_Doctor').for(:username) } end - it 'is invalid if the username is reserved' do - account = Fabricate.build(:account, username: 'support') - account.valid? - expect(account).to model_have_error_on_field(:username) - end + it { is_expected.to_not allow_value('support').for(:username) } it 'is valid when username is reserved but record has already been created' do account = Fabricate.build(:account, username: 'support') @@ -849,9 +804,10 @@ RSpec.describe Account do expect(account.valid?).to be true end - it 'is valid if we are creating an instance actor account with a period' do - account = Fabricate.build(:account, id: described_class::INSTANCE_ACTOR_ID, actor_type: 'Application', locked: true, username: 'example.com') - expect(account.valid?).to be true + context 'with the instance actor' do + subject { Fabricate.build :account, id: described_class::INSTANCE_ACTOR_ID, actor_type: 'Application', locked: true } + + it { is_expected.to allow_value('example.com').for(:username) } end it 'is valid if we are creating a possibly-conflicting instance actor account' do @@ -860,81 +816,31 @@ RSpec.describe Account do expect(instance_account.valid?).to be true end - it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do - account = Fabricate.build(:account, username: 'the-doctor') - account.valid? - expect(account).to model_have_error_on_field(:username) - end + it { is_expected.to_not allow_values('the-doctor', 'the.doctor').for(:username) } - it 'is invalid if the username contains a period' do - account = Fabricate.build(:account, username: 'the.doctor') - account.valid? - expect(account).to model_have_error_on_field(:username) - end + it { is_expected.to validate_length_of(:username).is_at_most(described_class::USERNAME_LENGTH_LIMIT) } + it { is_expected.to validate_length_of(:display_name).is_at_most(described_class::DISPLAY_NAME_LENGTH_LIMIT) } - it 'is invalid if the username is longer than the character limit' do - account = Fabricate.build(:account, username: username_over_limit) - account.valid? - expect(account).to model_have_error_on_field(:username) - end - - it 'is invalid if the display name is longer than the character limit' do - account = Fabricate.build(:account, display_name: display_name_over_limit) - account.valid? - expect(account).to model_have_error_on_field(:display_name) - end - - it 'is invalid if the note is longer than the character limit' do - account = Fabricate.build(:account, note: account_note_over_limit) - account.valid? - expect(account).to model_have_error_on_field(:note) - end + it { is_expected.to_not allow_values(account_note_over_limit).for(:note) } end - context 'when is remote' do - it 'is invalid if the username is same among accounts in the same normalized domain' do - Fabricate(:account, domain: 'にゃん', username: 'username') - account = Fabricate.build(:account, domain: 'xn--r9j5b5b', username: 'username') - account.valid? - expect(account).to model_have_error_on_field(:username) + context 'when account is remote' do + subject { Fabricate.build :account, domain: 'host.example' } + + context 'when a normalized domain account exists' do + subject { Fabricate.build :account, domain: 'xn--r9j5b5b' } + + before { Fabricate(:account, domain: 'にゃん', username: 'username') } + + it { is_expected.to_not allow_values('username', 'Username').for(:username) } end - it 'is invalid if the username is not unique in case-insensitive comparison among accounts in the same normalized domain' do - Fabricate(:account, domain: 'にゃん', username: 'username') - account = Fabricate.build(:account, domain: 'xn--r9j5b5b', username: 'Username') - account.valid? - expect(account).to model_have_error_on_field(:username) - end + it { is_expected.to allow_values('the-doctor', username_over_limit).for(:username) } + it { is_expected.to_not allow_values('the doctor').for(:username) } - it 'is valid even if the username contains hyphens' do - account = Fabricate.build(:account, domain: 'domain', username: 'the-doctor') - account.valid? - expect(account).to_not model_have_error_on_field(:username) - end + it { is_expected.to allow_values(display_name_over_limit).for(:display_name) } - it 'is invalid if the username doesn\'t only contains letters, numbers, underscores and hyphens' do - account = Fabricate.build(:account, domain: 'domain', username: 'the doctor') - account.valid? - expect(account).to model_have_error_on_field(:username) - end - - it 'is valid even if the username is longer than the character limit' do - account = Fabricate.build(:account, domain: 'domain', username: username_over_limit) - account.valid? - expect(account).to_not model_have_error_on_field(:username) - end - - it 'is valid even if the display name is longer than the character limit' do - account = Fabricate.build(:account, domain: 'domain', display_name: display_name_over_limit) - account.valid? - expect(account).to_not model_have_error_on_field(:display_name) - end - - it 'is valid even if the note is longer than the character limit' do - account = Fabricate.build(:account, domain: 'domain', note: account_note_over_limit) - account.valid? - expect(account).to_not model_have_error_on_field(:note) - end + it { is_expected.to allow_values(account_note_over_limit).for(:note) } end def username_over_limit @@ -1085,14 +991,6 @@ RSpec.describe Account do end end - describe 'suspended' do - it 'returns an array of accounts who are suspended' do - suspended_account = Fabricate(:account, suspended: true) - _account = Fabricate(:account, suspended: false) - expect(described_class.suspended).to contain_exactly(suspended_account) - end - end - describe 'searchable' do let!(:suspended_local) { Fabricate(:account, suspended: true, username: 'suspended_local') } let!(:suspended_remote) { Fabricate(:account, suspended: true, domain: 'example.org', username: 'suspended_remote') } diff --git a/spec/models/account_statuses_cleanup_policy_spec.rb b/spec/models/account_statuses_cleanup_policy_spec.rb index a08fd723a4..9bbbefa08e 100644 --- a/spec/models/account_statuses_cleanup_policy_spec.rb +++ b/spec/models/account_statuses_cleanup_policy_spec.rb @@ -5,17 +5,18 @@ require 'rails_helper' RSpec.describe AccountStatusesCleanupPolicy do let(:account) { Fabricate(:account, username: 'alice', domain: nil) } - describe 'validation' do - it 'disallow remote accounts' do - account.update(domain: 'example.com') - account_statuses_cleanup_policy = Fabricate.build(:account_statuses_cleanup_policy, account: account) - account_statuses_cleanup_policy.valid? - expect(account_statuses_cleanup_policy).to model_have_error_on_field(:account) - end + describe 'Validations' do + subject { Fabricate.build :account_statuses_cleanup_policy } + + let(:remote_account) { Fabricate(:account, domain: 'example.com') } + + it { is_expected.to_not allow_value(remote_account).for(:account) } end 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 +34,64 @@ RSpec.describe AccountStatusesCleanupPolicy do 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 @@ -337,14 +338,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep DMs and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = true - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy(keep_direct: true) } it 'returns every old status except does not return the old direct message for deletion' do expect(subject.pluck(:id)) @@ -354,14 +348,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep self-bookmarked toots and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = true - end + before { establish_policy(keep_self_bookmark: true) } it 'returns every old status but does not return the old self-bookmarked message for deletion' do expect(subject.pluck(:id)) @@ -371,14 +358,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep self-faved toots and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = true - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy(keep_self_fav: true) } it 'returns every old status but does not return the old self-faved message for deletion' do expect(subject.pluck(:id)) @@ -388,14 +368,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep toots with media and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = true - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy(keep_media: true) } it 'returns every old status but does not return the old message with media for deletion' do expect(subject.pluck(:id)) @@ -405,14 +378,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep toots with polls and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = true - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy(keep_polls: true) } it 'returns every old status but does not return the old poll message for deletion' do expect(subject.pluck(:id)) @@ -422,14 +388,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep pinned toots and reject everything else' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = true - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy(keep_pinned: true) } it 'returns every old status but does not return the old pinned message for deletion' do expect(subject.pluck(:id)) @@ -439,14 +398,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is to not keep any special messages' do - before do - account_statuses_cleanup_policy.keep_direct = false - account_statuses_cleanup_policy.keep_pinned = false - account_statuses_cleanup_policy.keep_polls = false - account_statuses_cleanup_policy.keep_media = false - account_statuses_cleanup_policy.keep_self_fav = false - account_statuses_cleanup_policy.keep_self_bookmark = false - end + before { establish_policy } it 'returns every old status but does not return the recent or unrelated statuses' do expect(subject.pluck(:id)) @@ -457,14 +409,7 @@ RSpec.describe AccountStatusesCleanupPolicy do end context 'when policy is set to keep every category of toots' do - before do - account_statuses_cleanup_policy.keep_direct = true - account_statuses_cleanup_policy.keep_pinned = true - account_statuses_cleanup_policy.keep_polls = true - account_statuses_cleanup_policy.keep_media = true - account_statuses_cleanup_policy.keep_self_fav = true - account_statuses_cleanup_policy.keep_self_bookmark = true - end + before { establish_policy(keep_direct: true, keep_pinned: true, keep_polls: true, keep_media: true, keep_self_fav: true, keep_self_bookmark: true) } it 'returns normal statuses and does not return unrelated old status' do expect(subject.pluck(:id)) @@ -500,5 +445,24 @@ RSpec.describe AccountStatusesCleanupPolicy do .and include(very_old_status.id, faved_primary.id, reblogged_primary.id, reblogged_secondary.id) end end + + private + + def establish_policy(options = {}) + default_policy_options.merge(options).each do |attribute, value| + account_statuses_cleanup_policy.send :"#{attribute}=", value + end + end + + def default_policy_options + { + keep_direct: false, + keep_media: false, + keep_pinned: false, + keep_polls: false, + keep_self_bookmark: false, + keep_self_fav: false, + } + end end end diff --git a/spec/models/announcement_spec.rb b/spec/models/announcement_spec.rb index 8bd1e74b29..884b352cb5 100644 --- a/spec/models/announcement_spec.rb +++ b/spec/models/announcement_spec.rb @@ -67,18 +67,30 @@ RSpec.describe Announcement do it { is_expected.to validate_presence_of(:text) } describe 'ends_at' do - it 'validates presence when starts_at is present' do - record = Fabricate.build(:announcement, starts_at: 1.day.ago) + context 'when starts_at is present' do + subject { Fabricate.build :announcement, starts_at: 1.day.ago } - expect(record).to_not be_valid - expect(record.errors[:ends_at]).to be_present + it { is_expected.to validate_presence_of(:ends_at) } end - it 'does not validate presence when starts_at is missing' do - record = Fabricate.build(:announcement, starts_at: nil) + context 'when starts_at is missing' do + subject { Fabricate.build :announcement, starts_at: nil } - expect(record).to be_valid - expect(record.errors[:ends_at]).to_not be_present + it { is_expected.to_not validate_presence_of(:ends_at) } + end + end + + describe 'starts_at' do + context 'when ends_at is present' do + subject { Fabricate.build :announcement, ends_at: 1.day.ago } + + it { is_expected.to validate_presence_of(:starts_at) } + end + + context 'when ends_at is missing' do + subject { Fabricate.build :announcement, ends_at: nil } + + it { is_expected.to_not validate_presence_of(:starts_at) } end end end diff --git a/spec/models/appeal_spec.rb b/spec/models/appeal_spec.rb index 7e324582ed..e974ff9254 100644 --- a/spec/models/appeal_spec.rb +++ b/spec/models/appeal_spec.rb @@ -4,20 +4,85 @@ require 'rails_helper' RSpec.describe Appeal do describe 'Validations' do - it 'validates text length is under limit' do - appeal = Fabricate.build( - :appeal, - strike: Fabricate(:account_warning), - text: 'a' * described_class::TEXT_LENGTH_LIMIT * 2 - ) + subject { Fabricate.build :appeal, strike: Fabricate(:account_warning) } - expect(appeal).to_not be_valid - expect(appeal).to model_have_error_on_field(:text) + it { is_expected.to validate_length_of(:text).is_at_most(described_class::TEXT_LENGTH_LIMIT) } + + context 'with a strike created too long ago' do + let(:strike) { Fabricate.build :account_warning, created_at: 100.days.ago } + + it { is_expected.to_not allow_values(strike).for(:strike).against(:base).on(:create) } end end - describe 'scopes' do - describe 'approved' do + describe 'Query methods' do + describe '#pending?' do + subject { Fabricate.build :appeal, approved_at:, rejected_at: } + + context 'with not approved and not rejected' do + let(:approved_at) { nil } + let(:rejected_at) { nil } + + it { expect(subject).to be_pending } + end + + context 'with approved and rejected' do + let(:approved_at) { 1.day.ago } + let(:rejected_at) { 1.day.ago } + + it { expect(subject).to_not be_pending } + end + + context 'with approved and not rejected' do + let(:approved_at) { 1.day.ago } + let(:rejected_at) { nil } + + it { expect(subject).to_not be_pending } + end + + context 'with not approved and rejected' do + let(:approved_at) { nil } + let(:rejected_at) { 1.day.ago } + + it { expect(subject).to_not be_pending } + end + end + + describe '#approved?' do + subject { Fabricate.build :appeal, approved_at: } + + context 'with not approved' do + let(:approved_at) { nil } + + it { expect(subject).to_not be_approved } + end + + context 'with approved' do + let(:approved_at) { 1.day.ago } + + it { expect(subject).to be_approved } + end + end + + describe '#rejected?' do + subject { Fabricate.build :appeal, rejected_at: } + + context 'with not rejected' do + let(:rejected_at) { nil } + + it { expect(subject).to_not be_rejected } + end + + context 'with rejected' do + let(:rejected_at) { 1.day.ago } + + it { expect(subject).to be_rejected } + end + end + end + + describe 'Scopes' do + describe '.approved' do let(:approved_appeal) { Fabricate(:appeal, approved_at: 10.days.ago) } let(:not_approved_appeal) { Fabricate(:appeal, approved_at: nil) } @@ -27,7 +92,7 @@ RSpec.describe Appeal do end end - describe 'rejected' do + describe '.rejected' do let(:rejected_appeal) { Fabricate(:appeal, rejected_at: 10.days.ago) } let(:not_rejected_appeal) { Fabricate(:appeal, rejected_at: nil) } @@ -37,7 +102,7 @@ RSpec.describe Appeal do end end - describe 'pending' do + describe '.pending' do let(:approved_appeal) { Fabricate(:appeal, approved_at: 10.days.ago) } let(:rejected_appeal) { Fabricate(:appeal, rejected_at: 10.days.ago) } let(:pending_appeal) { Fabricate(:appeal, rejected_at: nil, approved_at: nil) } diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb index 84f0f318f4..62d7e40e28 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/concerns/account/suspensions_spec.rb b/spec/models/concerns/account/suspensions_spec.rb new file mode 100644 index 0000000000..3d71f1b723 --- /dev/null +++ b/spec/models/concerns/account/suspensions_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Account::Suspensions do + subject { Fabricate(:account) } + + describe '.suspended' do + let!(:suspended_account) { Fabricate :account, suspended: true } + + before { Fabricate :account, suspended: false } + + it 'returns accounts that are suspended' do + expect(Account.suspended) + .to contain_exactly(suspended_account) + end + end + + describe '#suspended_locally?' do + context 'when the account is not suspended' do + it { is_expected.to_not be_suspended_locally } + end + + context 'when the account is suspended locally' do + before { subject.update!(suspended_at: 1.day.ago, suspension_origin: :local) } + + it { is_expected.to be_suspended_locally } + end + + context 'when the account is suspended remotely' do + before { subject.update!(suspended_at: 1.day.ago, suspension_origin: :remote) } + + it { is_expected.to_not be_suspended_locally } + end + end + + describe '#suspend!' do + it 'marks the account as suspended and creates a deletion request' do + expect { subject.suspend! } + .to change(subject, :suspended?).from(false).to(true) + .and change(subject, :suspended_locally?).from(false).to(true) + .and(change { AccountDeletionRequest.exists?(account: subject) }.from(false).to(true)) + end + + context 'when the account is of a local user' do + subject { local_user_account } + + let!(:local_user_account) { Fabricate(:user, email: 'foo+bar@domain.org').account } + + it 'creates a canonical domain block' do + expect { subject.suspend! } + .to change { CanonicalEmailBlock.block?(subject.user_email) }.from(false).to(true) + end + + context 'when a canonical domain block already exists for that email' do + before { Fabricate(:canonical_email_block, email: subject.user_email) } + + it 'does not raise an error' do + expect { subject.suspend! } + .to_not raise_error + end + end + end + end +end diff --git a/spec/models/domain_allow_spec.rb b/spec/models/domain_allow_spec.rb index d8f438f07e..fbb324657e 100644 --- a/spec/models/domain_allow_spec.rb +++ b/spec/models/domain_allow_spec.rb @@ -6,11 +6,10 @@ RSpec.describe DomainAllow do describe 'Validations' do it { is_expected.to validate_presence_of(:domain) } - it 'is invalid if the same normalized domain already exists' do - _domain_allow = Fabricate(:domain_allow, domain: 'にゃん') - domain_allow_with_normalized_value = Fabricate.build(:domain_allow, domain: 'xn--r9j5b5b') - domain_allow_with_normalized_value.valid? - expect(domain_allow_with_normalized_value).to model_have_error_on_field(:domain) + context 'when a normalized domain exists' do + before { Fabricate(:domain_allow, domain: 'にゃん') } + + it { is_expected.to_not allow_value('xn--r9j5b5b').for(:domain) } end end end diff --git a/spec/models/featured_tag_spec.rb b/spec/models/featured_tag_spec.rb index 0f5ead8f97..20059cfba4 100644 --- a/spec/models/featured_tag_spec.rb +++ b/spec/models/featured_tag_spec.rb @@ -126,16 +126,54 @@ RSpec.describe FeaturedTag do end describe '#decrement' do - it 'decreases the count and updates the last_status_at timestamp' do - tag = Fabricate :tag, name: 'test' - status = Fabricate :status, visibility: :public, created_at: 10.days.ago - status.tags << tag + let(:tag) { Fabricate(:tag, name: 'test') } + let(:account) { Fabricate(:account) } + let(:featured_tag) { Fabricate(:featured_tag, name: 'test', account: account) } - featured_tag = Fabricate :featured_tag, name: 'test', account: status.account + context 'when removing the last status using the tag' do + let(:status) { Fabricate(:status, visibility: :public, account: account, created_at: 10.days.ago) } - expect { featured_tag.decrement(status.id) } - .to change(featured_tag, :statuses_count).from(1).to(0) - .and change(featured_tag, :last_status_at).to(nil) + before do + status.tags << tag + end + + it 'decreases the count and updates the last_status_at timestamp' do + expect { featured_tag.decrement(status) } + .to change(featured_tag, :statuses_count).from(1).to(0) + .and change(featured_tag, :last_status_at).to(nil) + end + end + + context 'when removing a previous status using the tag' do + let(:previous_status) { Fabricate(:status, visibility: :public, account: account, created_at: 1.month.ago) } + let(:status) { Fabricate(:status, visibility: :public, account: account, created_at: 10.days.ago) } + + before do + previous_status.tags << tag + status.tags << tag + end + + it 'decreases the count and updates the last_status_at timestamp' do + expect { featured_tag.decrement(previous_status) } + .to change(featured_tag, :statuses_count).from(2).to(1) + .and not_change(featured_tag, :last_status_at) + end + end + + context 'when removing the most recent use of the tag' do + let(:previous_status) { Fabricate(:status, visibility: :public, account: account, created_at: 1.month.ago) } + let(:status) { Fabricate(:status, visibility: :public, account: account, created_at: 10.days.ago) } + + before do + previous_status.tags << tag + status.tags << tag + end + + it 'decreases the count and updates the last_status_at timestamp' do + expect { featured_tag.decrement(status) } + .to change(featured_tag, :statuses_count).from(2).to(1) + .and change(featured_tag, :last_status_at) + end end end end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index f22bd6ea88..8684170dcf 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -3,27 +3,26 @@ require 'rails_helper' RSpec.describe Follow do - let(:alice) { Fabricate(:account, username: 'alice') } - let(:bob) { Fabricate(:account, username: 'bob') } - - describe 'validations' do - subject { described_class.new(account: alice, target_account: bob, rate_limit: true) } - + describe 'Associations' do it { is_expected.to belong_to(:account).required } it { is_expected.to belong_to(:target_account).required } + end - it 'is invalid if account already follows too many people' do - alice.update(following_count: FollowLimitValidator::LIMIT) + describe 'Validations' do + subject { Fabricate.build :follow, rate_limit: true } - expect(subject).to_not be_valid - expect(subject).to model_have_error_on_field(:base) + let(:account) { Fabricate(:account) } + + context 'when account follows too many people' do + before { account.update(following_count: FollowLimitValidator::LIMIT) } + + it { is_expected.to_not allow_value(account).for(:account).against(:base) } end - it 'is valid if account is only on the brink of following too many people' do - alice.update(following_count: FollowLimitValidator::LIMIT - 1) + context 'when account is on brink of following too many people' do + before { account.update(following_count: FollowLimitValidator::LIMIT - 1) } - expect(subject).to be_valid - expect(subject).to_not model_have_error_on_field(:base) + it { is_expected.to allow_value(account).for(:account).against(:base) } end end @@ -54,4 +53,58 @@ RSpec.describe Follow do expect(account.requested?(target_account)).to be true end 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 :follow, 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 + + describe 'Maintaining counters' do + subject { Fabricate.build :follow, account:, target_account: } + + let(:account) { Fabricate :account } + let(:target_account) { Fabricate :account } + + before do + account.account_stat.update following_count: 123 + target_account.account_stat.update followers_count: 123 + end + + describe 'saving the follow' do + it 'increments counters' do + expect { subject.save } + .to change(account, :following_count).by(1) + .and(change(target_account, :followers_count).by(1)) + end + end + + describe 'destroying the follow' do + it 'decrements counters' do + expect { subject.destroy } + .to change(account, :following_count).by(-1) + .and(change(target_account, :followers_count).by(-1)) + end + end + end + end end diff --git a/spec/models/form/admin_settings_spec.rb b/spec/models/form/admin_settings_spec.rb index 6080b9e081..73106f2b69 100644 --- a/spec/models/form/admin_settings_spec.rb +++ b/spec/models/form/admin_settings_spec.rb @@ -3,33 +3,17 @@ require 'rails_helper' RSpec.describe Form::AdminSettings do - describe 'validations' do + describe 'Validations' do describe 'site_contact_username' do context 'with no accounts' do - it 'is not valid' do - setting = described_class.new(site_contact_username: 'Test') - setting.valid? - - expect(setting).to model_have_error_on_field(:site_contact_username) - end + it { is_expected.to_not allow_value('Test').for(:site_contact_username) } end context 'with an account' do before { Fabricate(:account, username: 'Glorp') } - it 'is not valid when account doesnt match' do - setting = described_class.new(site_contact_username: 'Test') - setting.valid? - - expect(setting).to model_have_error_on_field(:site_contact_username) - end - - it 'is valid when account matches' do - setting = described_class.new(site_contact_username: 'Glorp') - setting.valid? - - expect(setting).to_not model_have_error_on_field(:site_contact_username) - end + it { is_expected.to_not allow_value('Test').for(:site_contact_username) } + it { is_expected.to allow_value('Glorp').for(:site_contact_username) } end end end diff --git a/spec/models/ip_block_spec.rb b/spec/models/ip_block_spec.rb index ac9f5db601..b85856780a 100644 --- a/spec/models/ip_block_spec.rb +++ b/spec/models/ip_block_spec.rb @@ -3,18 +3,13 @@ require 'rails_helper' RSpec.describe IpBlock do - describe 'validations' do + describe 'Validations' do + subject { Fabricate.build :ip_block } + it { is_expected.to validate_presence_of(:ip) } it { is_expected.to validate_presence_of(:severity) } - it 'validates ip uniqueness', :aggregate_failures do - described_class.create!(ip: '127.0.0.1', severity: :no_access) - - ip_block = described_class.new(ip: '127.0.0.1', severity: :no_access) - - expect(ip_block).to_not be_valid - expect(ip_block).to model_have_error_on_field(:ip) - end + it { is_expected.to validate_uniqueness_of(:ip) } end describe '#to_log_human_identifier' do diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb index 736f3615d0..66f521ab3f 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 @@ RSpec.describe Poll do end end - describe 'attached' do + describe '.attached' do it 'finds the correct records' do results = described_class.attached @@ -21,7 +21,7 @@ RSpec.describe Poll do end end - describe 'unattached' do + describe '.unattached' do it 'finds the correct records' do results = described_class.unattached @@ -30,11 +30,23 @@ RSpec.describe Poll do end end - describe 'validations' do - context 'when not valid' do - subject { Fabricate.build(:poll) } + 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 { is_expected.to validate_presence_of(:expires_at) } + 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/preview_card_spec.rb b/spec/models/preview_card_spec.rb index c0bc2b6e0e..0fe76c37b0 100644 --- a/spec/models/preview_card_spec.rb +++ b/spec/models/preview_card_spec.rb @@ -9,26 +9,10 @@ RSpec.describe PreviewCard do end end - describe 'validations' do - describe 'urls' do - it 'allows http schemes' do - record = described_class.new(url: 'http://example.host/path') - - expect(record).to be_valid - end - - it 'allows https schemes' do - record = described_class.new(url: 'https://example.host/path') - - expect(record).to be_valid - end - - it 'does not allow javascript: schemes' do - record = described_class.new(url: 'javascript:alert()') - - expect(record).to_not be_valid - expect(record).to model_have_error_on_field(:url) - end + describe 'Validations' do + describe 'url' do + it { is_expected.to allow_values('http://example.host/path', 'https://example.host/path').for(:url) } + it { is_expected.to_not allow_value('javascript:alert()').for(:url) } end end end diff --git a/spec/models/preview_card_trend_spec.rb b/spec/models/preview_card_trend_spec.rb new file mode 100644 index 0000000000..6edd24b693 --- /dev/null +++ b/spec/models/preview_card_trend_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe PreviewCardTrend do + describe 'Associations' do + it { is_expected.to belong_to(:preview_card).required } + end + + describe '.locales' do + before do + Fabricate :preview_card_trend, language: 'en' + Fabricate :preview_card_trend, language: 'en' + Fabricate :preview_card_trend, language: 'es' + end + + it 'returns unique set of languages' do + expect(described_class.locales) + .to eq(['en', 'es']) + end + end +end diff --git a/spec/models/public_feed_spec.rb b/spec/models/public_feed_spec.rb index 8a1a01e892..5f2444dc6b 100644 --- a/spec/models/public_feed_spec.rb +++ b/spec/models/public_feed_spec.rb @@ -55,12 +55,10 @@ RSpec.describe PublicFeed do 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 @@ -71,12 +69,10 @@ RSpec.describe PublicFeed do 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_note_spec.rb b/spec/models/report_note_spec.rb index 417971c9a1..0d1c0f619e 100644 --- a/spec/models/report_note_spec.rb +++ b/spec/models/report_note_spec.rb @@ -3,29 +3,24 @@ require 'rails_helper' RSpec.describe ReportNote do - describe 'chronological scope' do - it 'returns report notes oldest to newest' do - report = Fabricate(:report) - note1 = Fabricate(:report_note, report: report) - note2 = Fabricate(:report_note, report: report) + describe 'Scopes' do + describe '.chronological' do + it 'returns report notes oldest to newest' do + report = Fabricate(:report) + note1 = Fabricate(:report_note, report: report) + note2 = Fabricate(:report_note, report: report) - expect(report.notes.chronological).to eq [note1, note2] + expect(report.notes.chronological).to eq [note1, note2] + end end end - describe 'validations' do - it 'is invalid if the content is empty' do - report = Fabricate.build(:report_note, content: '') - expect(report.valid?).to be false - end + describe 'Validations' do + subject { Fabricate.build :report_note } - it 'is invalid if content is longer than character limit' do - report = Fabricate.build(:report_note, content: comment_over_limit) - expect(report.valid?).to be false - end - - def comment_over_limit - Faker::Lorem.paragraph_by_chars(number: described_class::CONTENT_SIZE_LIMIT * 2) + describe 'content' do + it { is_expected.to_not allow_value('').for(:content) } + it { is_expected.to validate_length_of(:content).is_at_most(described_class::CONTENT_SIZE_LIMIT) } end end end diff --git a/spec/models/status_pin_spec.rb b/spec/models/status_pin_spec.rb index da375009ae..1501d43cc4 100644 --- a/spec/models/status_pin_spec.rb +++ b/spec/models/status_pin_spec.rb @@ -3,70 +3,100 @@ require 'rails_helper' RSpec.describe StatusPin do - describe 'validations' do - it 'allows pins of own statuses' do - account = Fabricate(:account) - status = Fabricate(:status, account: account) + describe 'Validations' do + subject { Fabricate.build :status_pin } - expect(described_class.new(account: account, status: status).save).to be true - end + context 'with an account pinning statuses' do + subject { Fabricate.build :status_pin, account: account } - it 'does not allow pins of statuses by someone else' do - account = Fabricate(:account) - status = Fabricate(:status) + let(:account) { Fabricate(:account) } - expect(described_class.new(account: account, status: status).save).to be false - end + context 'with a self-owned status' do + let(:status) { Fabricate(:status, account: account) } - it 'does not allow pins of reblogs' do - account = Fabricate(:account) - status = Fabricate(:status, account: account) - reblog = Fabricate(:status, reblog: status) - - expect(described_class.new(account: account, status: reblog).save).to be false - end - - it 'does allow pins of direct statuses' do - account = Fabricate(:account) - status = Fabricate(:status, account: account, visibility: :private) - - expect(described_class.new(account: account, status: status).save).to be true - end - - it 'does not allow pins of direct statuses' do - account = Fabricate(:account) - status = Fabricate(:status, account: account, visibility: :direct) - - expect(described_class.new(account: account, status: status).save).to be false - end - - context 'with a pin limit' do - before { stub_const('StatusPinValidator::PIN_LIMIT', 2) } - - it 'does not allow pins above the max' do - account = Fabricate(:account) - - Fabricate.times(StatusPinValidator::PIN_LIMIT, :status_pin, account: account) - - pin = described_class.new(account: account, status: Fabricate(:status, account: account)) - expect(pin.save) - .to be(false) - - expect(pin.errors[:base]) - .to contain_exactly(I18n.t('statuses.pin_errors.limit')) + it { is_expected.to allow_value(status).for(:status) } end - it 'allows pins above the max for remote accounts' do - account = Fabricate(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/') + context 'with a status from someone else' do + let(:status) { Fabricate(:status) } - Fabricate.times(StatusPinValidator::PIN_LIMIT, :status_pin, account: account) + it { is_expected.to_not allow_value(status).for(:status).against(:base) } + end - pin = described_class.new(account: account, status: Fabricate(:status, account: account)) - expect(pin.save) - .to be(true) + context 'with a reblog status' do + let(:status) { Fabricate(:status, reblog: Fabricate(:status, account: account)) } - expect(pin.errors[:base]) - .to be_empty + it { is_expected.to_not allow_value(status).for(:status).against(:base) } + end + + context 'with a private status' do + let(:status) { Fabricate(:status, account: account, visibility: :private) } + + it { is_expected.to allow_value(status).for(:status).against(:base) } + end + + context 'with a direct status' do + let(:status) { Fabricate(:status, account: account, visibility: :direct) } + + it { is_expected.to_not allow_value(status).for(:status).against(:base) } + end + end + + context 'with a validator pin limit' do + before { stub_const('StatusPinValidator::PIN_LIMIT', 2) } + + context 'with a local account at the limit' do + let(:account) { Fabricate :account } + + before { Fabricate.times(StatusPinValidator::PIN_LIMIT, :status_pin, account: account) } + + it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('statuses.pin_errors.limit')) } + end + + context 'with a remote account at the limit' do + let(:account) { Fabricate :account, domain: 'remote.test' } + + before { Fabricate.times(StatusPinValidator::PIN_LIMIT, :status_pin, account: account) } + + it { is_expected.to allow_value(account).for(:account) } + end + end + end + + describe 'Callbacks' do + describe 'Invalidating status via policy' do + subject { Fabricate :status_pin, status: Fabricate(:status, account: account), account: account } + + context 'with a local account that owns the status and has a policy' do + let(:account) { Fabricate :account, domain: nil } + + before do + Fabricate :account_statuses_cleanup_policy, account: account + account.statuses_cleanup_policy.record_last_inspected(subject.status.id + 1_024) + end + + it 'calls the invalidator on destroy' do + expect { subject.destroy } + .to change(account.statuses_cleanup_policy, :last_inspected) + end + end + + context 'with a local account that owns the status and does not have a policy' do + let(:account) { Fabricate :account, domain: nil } + + it 'does not call the invalidator on destroy' do + expect { subject.destroy } + .to_not change(account, :updated_at) + end + end + + context 'with a remote account' do + let(:account) { Fabricate :account, domain: 'host.example' } + + it 'does not call the invalidator on destroy' do + expect { subject.destroy } + .to_not change(account, :updated_at) + end end end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index da98e6c577..cd0d32b56b 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -164,6 +164,31 @@ RSpec.describe Status do end end + describe '#untrusted_reblogs_count' do + before do + alice.update(domain: 'example.com') + subject.status_stat.tap do |status_stat| + status_stat.untrusted_reblogs_count = 0 + status_stat.save + end + subject.save + end + + it 'is incremented by the number of reblogs' do + Fabricate(:status, account: bob, reblog: subject) + Fabricate(:status, account: alice, reblog: subject) + + expect(subject.untrusted_reblogs_count).to eq 2 + end + + it 'is decremented when reblog is removed' do + reblog = Fabricate(:status, account: bob, reblog: subject) + expect(subject.untrusted_reblogs_count).to eq 1 + reblog.destroy + expect(subject.untrusted_reblogs_count).to eq 0 + end + end + describe '#replies_count' do it 'is the number of replies' do Fabricate(:status, account: bob, thread: subject) @@ -194,6 +219,31 @@ RSpec.describe Status do end end + describe '#untrusted_favourites_count' do + before do + alice.update(domain: 'example.com') + subject.status_stat.tap do |status_stat| + status_stat.untrusted_favourites_count = 0 + status_stat.save + end + subject.save + end + + it 'is incremented by favorites' do + Fabricate(:favourite, account: bob, status: subject) + Fabricate(:favourite, account: alice, status: subject) + + expect(subject.untrusted_favourites_count).to eq 2 + end + + it 'is decremented when favourite is removed' do + favourite = Fabricate(:favourite, account: bob, status: subject) + expect(subject.untrusted_favourites_count).to eq 1 + favourite.destroy + expect(subject.untrusted_favourites_count).to eq 0 + end + end + describe '#proper' do it 'is itself for original statuses' do expect(subject.proper).to eq subject diff --git a/spec/models/status_trend_spec.rb b/spec/models/status_trend_spec.rb new file mode 100644 index 0000000000..34522493cd --- /dev/null +++ b/spec/models/status_trend_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe StatusTrend do + describe 'Associations' do + it { is_expected.to belong_to(:account).required } + it { is_expected.to belong_to(:status).required } + end + + describe '.locales' do + before do + Fabricate :status_trend, language: 'en' + Fabricate :status_trend, language: 'en' + Fabricate :status_trend, language: 'es' + end + + it 'returns unique set of languages' do + expect(described_class.locales) + .to eq(['en', 'es']) + end + end +end diff --git a/spec/models/tombstone_spec.rb b/spec/models/tombstone_spec.rb new file mode 100644 index 0000000000..ba0603fe3d --- /dev/null +++ b/spec/models/tombstone_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Tombstone do + describe 'Associations' do + it { is_expected.to belong_to(:account).required } + end + + describe 'Validations' do + subject { Fabricate.build :tombstone } + + it { is_expected.to validate_presence_of(:uri) } + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d28e6658f1..4393be5a4e 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -387,23 +387,43 @@ RSpec.describe User do 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) } - expect(user.token_for_app(app)).to be_nil + it 'returns nil' do + expect(user.token_for_app(app)) + .to be_nil + end + end + + context 'when app is nil' do + it 'returns nil' do + expect(user.token_for_app(nil)) + .to be_nil + end end end diff --git a/spec/models/webauthn_credential_spec.rb b/spec/models/webauthn_credential_spec.rb index c4105d9150..067c696c13 100644 --- a/spec/models/webauthn_credential_spec.rb +++ b/spec/models/webauthn_credential_spec.rb @@ -3,53 +3,17 @@ require 'rails_helper' RSpec.describe WebauthnCredential do - describe 'validations' do + describe 'Validations' do + subject { Fabricate.build :webauthn_credential } + it { is_expected.to validate_presence_of(:external_id) } it { is_expected.to validate_presence_of(:public_key) } it { is_expected.to validate_presence_of(:nickname) } it { is_expected.to validate_presence_of(:sign_count) } - it 'is invalid if already exist a webauthn credential with the same external id' do - Fabricate(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw') - new_webauthn_credential = Fabricate.build(:webauthn_credential, external_id: '_Typ0ygudDnk9YUVWLQayw') + it { is_expected.to validate_uniqueness_of(:external_id) } + it { is_expected.to validate_uniqueness_of(:nickname).scoped_to(:user_id) } - new_webauthn_credential.valid? - - expect(new_webauthn_credential).to model_have_error_on_field(:external_id) - end - - it 'is invalid if user already registered a webauthn credential with the same nickname' do - user = Fabricate(:user) - Fabricate(:webauthn_credential, user_id: user.id, nickname: 'USB Key') - new_webauthn_credential = Fabricate.build(:webauthn_credential, user_id: user.id, nickname: 'USB Key') - - new_webauthn_credential.valid? - - expect(new_webauthn_credential).to model_have_error_on_field(:nickname) - end - - it 'is invalid if sign_count is not a number' do - webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: 'invalid sign_count') - - webauthn_credential.valid? - - expect(webauthn_credential).to model_have_error_on_field(:sign_count) - end - - it 'is invalid if sign_count is negative number' do - webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: -1) - - webauthn_credential.valid? - - expect(webauthn_credential).to model_have_error_on_field(:sign_count) - end - - it 'is invalid if sign_count is greater than the limit' do - webauthn_credential = Fabricate.build(:webauthn_credential, sign_count: (described_class::SIGN_COUNT_LIMIT * 2)) - - webauthn_credential.valid? - - expect(webauthn_credential).to model_have_error_on_field(:sign_count) - end + it { is_expected.to validate_numericality_of(:sign_count).only_integer.is_greater_than_or_equal_to(0).is_less_than_or_equal_to(described_class::SIGN_COUNT_LIMIT - 1) } end end diff --git a/spec/policies/account_moderation_note_policy_spec.rb b/spec/policies/account_moderation_note_policy_spec.rb index 8c37acc39f..8b33a71012 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 @@ RSpec.describe AccountModerationNotePolicy do 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 d7a21d8e39..75724e831b 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 @@ RSpec.describe AccountPolicy do 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 0000000000..9abc9d35d6 --- /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 53e224f19f..33f2fb1187 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 @@ RSpec.describe AccountWarningPresetPolicy do 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 07af425516..4df29393e3 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 @@ RSpec.describe Admin::StatusPolicy do 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 503ffca6dc..ab0c1dbaf5 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 @@ RSpec.describe AnnouncementPolicy do 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 1bf8ce0a0d..cdb93bf56c 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 @@ RSpec.describe AppealPolicy do 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 0000000000..d9d9359433 --- /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 28cb65d789..031021d91d 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 f5029d9e6b..b253b439a6 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 @@ RSpec.describe CanonicalEmailBlockPolicy do 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 cb869c7d9a..189885938c 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 0000000000..90c71db381 --- /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 bb82389eec..8bc200159a 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 @@ RSpec.describe DeliveryPolicy do 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 0000000000..1d285065b8 --- /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 4c89f3f374..7c77d1870d 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 @@ RSpec.describe DomainBlockPolicy do 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 7ecff4be49..e98d65a3c7 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 ae74d5c3a8..665ed9b059 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 @@ RSpec.describe FollowRecommendationPolicy do 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 a0d9a008b7..6cdc738022 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 cbe3735d80..3717a44999 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 97bc239e9a..33ea342c10 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 @@ RSpec.describe IpBlockPolicy do 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 0000000000..aa1701cb06 --- /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 a1944303e1..d02a6016cd 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 @@ RSpec.describe PreviewCardPolicy do 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 676039a1b7..5e25b364a4 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 @@ RSpec.describe PreviewCardProviderPolicy do 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 29ba02c26a..5983b2d2ff 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 b40a878887..02317f763a 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 4fc4178075..67f40b5188 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 5d435e38c1..3086f30446 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 @@ RSpec.describe RulePolicy do 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 4a99314905..48821c706a 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 e19ba61612..2bda84cce9 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 725bd0bbb3..eb2af75d92 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 35da3cc62a..23166e4669 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 7854547d26..11a166a24e 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 @@ RSpec.describe UserPolicy do 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 0000000000..c48b345d68 --- /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 96aaae2c30..9899235d83 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/rails_helper.rb b/spec/rails_helper.rb index 84cee0974f..574d543844 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -32,7 +32,7 @@ end STREAMING_PORT = ENV.fetch('TEST_STREAMING_PORT', '4020') ENV['STREAMING_API_BASE_URL'] = "http://localhost:#{STREAMING_PORT}" -require File.expand_path('../config/environment', __dir__) +require_relative '../config/environment' abort('The Rails environment is running in production mode!') if Rails.env.production? @@ -43,6 +43,7 @@ require 'paperclip/matchers' 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 } @@ -112,6 +113,7 @@ RSpec.configure do |config| config.include ActiveSupport::Testing::TimeHelpers config.include Chewy::Rspec::Helpers config.include Redisable + config.include DomainHelpers config.include ThreadingHelpers config.include SignedRequestHelpers, type: :request config.include CommandLineHelpers, type: :cli diff --git a/spec/requests/activitypub/likes_spec.rb b/spec/requests/activitypub/likes_spec.rb new file mode 100644 index 0000000000..d780ad5168 --- /dev/null +++ b/spec/requests/activitypub/likes_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'ActivityPub Likes' do + let(:account) { Fabricate(:account) } + let(:status) { Fabricate :status, account: account } + + before { Fabricate :favourite, status: status } + + describe 'GET /accounts/:account_username/statuses/:status_id/likes' do + it 'returns http success and activity json types and correct items count' do + get account_status_likes_path(account, status) + + expect(response) + .to have_http_status(200) + expect(response.media_type) + .to eq 'application/activity+json' + + expect(response.parsed_body) + .to include(type: 'Collection') + .and include(totalItems: 1) + end + end +end diff --git a/spec/requests/activitypub/shares_spec.rb b/spec/requests/activitypub/shares_spec.rb new file mode 100644 index 0000000000..956bc7d201 --- /dev/null +++ b/spec/requests/activitypub/shares_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'ActivityPub Shares' do + let(:account) { Fabricate(:account) } + let(:status) { Fabricate :status, account: account } + + before { Fabricate :status, reblog: status } + + describe 'GET /accounts/:account_username/statuses/:status_id/shares' do + it 'returns http success and activity json types and correct items count' do + get account_status_shares_path(account, status) + + expect(response) + .to have_http_status(200) + expect(response.media_type) + .to eq 'application/activity+json' + + expect(response.parsed_body) + .to include(type: 'Collection') + .and include(totalItems: 1) + end + end +end diff --git a/spec/requests/api/v1/domain_blocks/previews_spec.rb b/spec/requests/api/v1/domain_blocks/previews_spec.rb new file mode 100644 index 0000000000..eb191f436b --- /dev/null +++ b/spec/requests/api/v1/domain_blocks/previews_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Domain Blocks Previews API' do + let(:user) { Fabricate(:user) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:scopes) { 'write:blocks' } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + let(:account) { Fabricate(:account, user: user) } + + describe 'GET /api/v1/domain_blocks/preview' do + subject { get '/api/v1/domain_blocks/preview', params: { domain: domain }, headers: headers } + + let(:domain) { 'host.example' } + + before do + Fabricate :follow, account: account, target_account: Fabricate(:account, domain: domain) + Fabricate :follow, target_account: account, account: Fabricate(:account, domain: domain) + end + + it_behaves_like 'forbidden for wrong scope', 'write:statuses' + + it 'returns http success and follower counts' do + subject + + expect(response) + .to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body) + .to include(followers_count: 1) + .and include(following_count: 1) + end + end +end diff --git a/spec/requests/api/v1/trends/statuses_spec.rb b/spec/requests/api/v1/trends/statuses_spec.rb index fe00c9c645..414d7651b9 100644 --- a/spec/requests/api/v1/trends/statuses_spec.rb +++ b/spec/requests/api/v1/trends/statuses_spec.rb @@ -39,6 +39,42 @@ RSpec.describe 'API V1 Trends Statuses' do end Trends::Statuses.new(threshold: 1, decay_threshold: -1).refresh end + + context 'with a comically inflated external interactions count' do + def prepare_fake_trends + fake_remote_account = Fabricate(:account, domain: 'other.com') + fake_status = Fabricate(:status, account: fake_remote_account, text: 'I am a big faker', trendable: true, language: 'en') + fake_status.status_stat.tap do |status_stat| + status_stat.reblogs_count = 0 + status_stat.favourites_count = 0 + status_stat.untrusted_reblogs_count = 1_000_000_000 + status_stat.untrusted_favourites_count = 1_000_000_000 + status_stat.save + end + real_remote_account = Fabricate(:account, domain: 'other.com') + real_status = Fabricate(:status, account: real_remote_account, text: 'I make real friends online', trendable: true, language: 'en') + real_status.status_stat.tap do |status_stat| + status_stat.reblogs_count = 10 + status_stat.favourites_count = 10 + status_stat.untrusted_reblogs_count = 10 + status_stat.untrusted_favourites_count = 10 + status_stat.save + end + Trends.statuses.add(fake_status, 100) + Trends.statuses.add(real_status, 101) + Trends::Statuses.new(threshold: 1, decay_threshold: 1).refresh + end + + it 'ignores the feeble attempts at deception' do + prepare_fake_trends + stub_const('Api::BaseController::DEFAULT_STATUSES_LIMIT', 10) + get '/api/v1/trends/statuses' + + expect(response).to have_http_status(200) + expect(response.parsed_body.length).to eq(1) + expect(response.parsed_body[0]['content']).to eq('I make real friends online') + end + end end end end diff --git a/spec/requests/api/v2/media_spec.rb b/spec/requests/api/v2/media_spec.rb index 70e0679f57..807e427d3f 100644 --- a/spec/requests/api/v2/media_spec.rb +++ b/spec/requests/api/v2/media_spec.rb @@ -29,6 +29,22 @@ RSpec.describe 'Media API', :attachment_processing do end end + context 'when media description is too long' do + let(:params) do + { + file: fixture_file_upload('attachment-jpg.123456_abcd', 'image/jpeg'), + description: 'aa' * MediaAttachment::MAX_DESCRIPTION_LENGTH, + } + end + + it 'returns http error' do + post '/api/v2/media', headers: headers, params: params + + expect(response).to have_http_status(422) + expect(response.body).to include 'Description is too long' + end + end + context 'when large format media attachment has not been processed' do let(:params) { { file: fixture_file_upload('attachment.webm', 'video/webm') } } diff --git a/spec/requests/api/web/push_subscriptions_spec.rb b/spec/requests/api/web/push_subscriptions_spec.rb new file mode 100644 index 0000000000..a903dc6f89 --- /dev/null +++ b/spec/requests/api/web/push_subscriptions_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'API Web Push Subscriptions' do + describe 'DELETE /api/web/push_subscriptions/:id' do + subject { delete api_web_push_subscription_path(token) } + + context 'when the subscription exists' do + let!(:web_push_subscription) do + Fabricate(:web_push_subscription) + end + let(:token) do + web_push_subscription.generate_token_for(:unsubscribe) + end + + it 'deletes the subscription' do + expect { subject } + .to change(Web::PushSubscription, :count).by(-1) + + expect(response).to have_http_status(200) + end + end + + context 'when the subscription does not exist' do + let(:web_push_subscription) do + Fabricate(:web_push_subscription) + end + let(:token) do + web_push_subscription.generate_token_for(:unsubscribe) + end + + before do + token # memoize before destroying the record + web_push_subscription.destroy! + end + + it 'does nothing' do + subject + + expect(response).to have_http_status(200) + end + end + + context 'when the token is invalid' do + let(:token) { 'invalid--invalid' } + + it 'does nothing' do + subject + + expect(response).to have_http_status(200) + end + end + end +end diff --git a/spec/requests/oauth/userinfo_spec.rb b/spec/requests/oauth/userinfo_spec.rb new file mode 100644 index 0000000000..7d6226cd41 --- /dev/null +++ b/spec/requests/oauth/userinfo_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Oauth Userinfo Endpoint' do + include RoutingHelper + + let(:user) { Fabricate(:user) } + let(:account) { user.account } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:scopes) { 'profile' } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } + + shared_examples 'returns successfully' do + it 'returns http success' do + subject + + expect(response).to have_http_status(:success) + expect(response.content_type).to start_with('application/json') + expect(response.parsed_body).to include({ + iss: root_url, + sub: account_url(account), + name: account.display_name, + preferred_username: account.username, + profile: short_account_url(account), + picture: full_asset_url(account.avatar_original_url), + }) + end + end + + describe 'GET /oauth/userinfo' do + subject do + get '/oauth/userinfo', headers: headers + end + + it_behaves_like 'forbidden for wrong scope', 'read:accounts' + it_behaves_like 'returns successfully' + end + + # As this is borrowed from OpenID, the specification says we must also support + # POST for the userinfo endpoint: + # https://openid.net/specs/openid-connect-core-1_0.html#UserInfo + describe 'POST /oauth/userinfo' do + subject do + post '/oauth/userinfo', headers: headers + end + + it_behaves_like 'forbidden for wrong scope', 'read:accounts' + it_behaves_like 'returns successfully' + end +end diff --git a/spec/requests/statuses/embed_spec.rb b/spec/requests/statuses/embed_spec.rb new file mode 100644 index 0000000000..33c7ea192c --- /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/well_known/oauth_metadata_spec.rb b/spec/requests/well_known/oauth_metadata_spec.rb index 9c86dbedfe..01e9146fde 100644 --- a/spec/requests/well_known/oauth_metadata_spec.rb +++ b/spec/requests/well_known/oauth_metadata_spec.rb @@ -3,12 +3,6 @@ require 'rails_helper' RSpec.describe 'The /.well-known/oauth-authorization-server request' do - let(:protocol) { ENV.fetch('LOCAL_HTTPS', true) ? :https : :http } - - before do - host! Rails.configuration.x.local_domain - end - it 'returns http success with valid JSON response' do get '/.well-known/oauth-authorization-server' @@ -22,11 +16,12 @@ RSpec.describe 'The /.well-known/oauth-authorization-server request' do grant_types_supported << 'refresh_token' if Doorkeeper.configuration.refresh_token_enabled? expect(response.parsed_body).to include( - issuer: root_url(protocol: protocol), + issuer: root_url, service_documentation: 'https://docs.joinmastodon.org/', - authorization_endpoint: oauth_authorization_url(protocol: protocol), - token_endpoint: oauth_token_url(protocol: protocol), - revocation_endpoint: oauth_revoke_url(protocol: protocol), + authorization_endpoint: oauth_authorization_url, + token_endpoint: oauth_token_url, + userinfo_endpoint: oauth_userinfo_url, + revocation_endpoint: oauth_revoke_url, scopes_supported: Doorkeeper.configuration.scopes.map(&:to_s), response_types_supported: Doorkeeper.configuration.authorization_response_types, response_modes_supported: Doorkeeper.configuration.authorization_response_flows.flat_map(&:response_mode_matches).uniq, @@ -34,7 +29,7 @@ RSpec.describe 'The /.well-known/oauth-authorization-server request' do grant_types_supported: grant_types_supported, code_challenge_methods_supported: ['S256'], # non-standard extension: - app_registration_endpoint: api_v1_apps_url(protocol: protocol) + app_registration_endpoint: api_v1_apps_url ) end end diff --git a/spec/serializers/activitypub/actor_serializer_spec.rb b/spec/serializers/activitypub/actor_serializer_spec.rb new file mode 100644 index 0000000000..ad24455953 --- /dev/null +++ b/spec/serializers/activitypub/actor_serializer_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::ActorSerializer do + subject { serialized_record_json(record, described_class) } + + describe '#type' do + context 'with the instance actor' do + let(:record) { Account.find(Account::INSTANCE_ACTOR_ID) } + + it { is_expected.to include('type' => 'Application') } + end + + context 'with an application actor' do + let(:record) { Fabricate :account, actor_type: 'Application' } + + it { is_expected.to include('type' => 'Service') } + end + + context 'with a service actor' do + let(:record) { Fabricate :account, actor_type: 'Service' } + + it { is_expected.to include('type' => 'Service') } + end + + context 'with a Group actor' do + let(:record) { Fabricate :account, actor_type: 'Group' } + + it { is_expected.to include('type' => 'Group') } + end + + context 'with a Person actor' do + let(:record) { Fabricate :account, actor_type: 'Person' } + + it { is_expected.to include('type' => 'Person') } + end + end +end diff --git a/spec/serializers/activitypub/add_serializer_spec.rb b/spec/serializers/activitypub/add_serializer_spec.rb new file mode 100644 index 0000000000..3b3eaeb1b0 --- /dev/null +++ b/spec/serializers/activitypub/add_serializer_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::AddSerializer do + describe '.serializer_for' do + subject { described_class.serializer_for(model, {}) } + + context 'with a Status model' do + let(:model) { Status.new } + + it { is_expected.to eq(described_class::UriSerializer) } + end + + context 'with a FeaturedTag model' do + let(:model) { FeaturedTag.new } + + it { is_expected.to eq(ActivityPub::HashtagSerializer) } + end + + context 'with an Array' do + let(:model) { [] } + + it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) } + end + end +end diff --git a/spec/serializers/activitypub/collection_serializer_spec.rb b/spec/serializers/activitypub/collection_serializer_spec.rb new file mode 100644 index 0000000000..7726df914f --- /dev/null +++ b/spec/serializers/activitypub/collection_serializer_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::CollectionSerializer do + describe '.serializer_for' do + subject { described_class.serializer_for(model, {}) } + + context 'with a Status model' do + let(:model) { Status.new } + + it { is_expected.to eq(ActivityPub::NoteSerializer) } + end + + context 'with a FeaturedTag model' do + let(:model) { FeaturedTag.new } + + it { is_expected.to eq(ActivityPub::HashtagSerializer) } + end + + context 'with an ActivityPub::CollectionPresenter' do + let(:model) { ActivityPub::CollectionPresenter.new } + + it { is_expected.to eq(described_class) } + end + + context 'with a String' do + let(:model) { '' } + + it { is_expected.to eq(described_class::StringSerializer) } + end + + context 'with an Array' do + let(:model) { [] } + + it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) } + end + end +end diff --git a/spec/serializers/activitypub/note_serializer_spec.rb b/spec/serializers/activitypub/note_serializer_spec.rb index 285b241ee2..a6976193b2 100644 --- a/spec/serializers/activitypub/note_serializer_spec.rb +++ b/spec/serializers/activitypub/note_serializer_spec.rb @@ -14,7 +14,7 @@ RSpec.describe ActivityPub::NoteSerializer do 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 @@ RSpec.describe ActivityPub::NoteSerializer do '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/serializers/activitypub/remove_serializer_spec.rb b/spec/serializers/activitypub/remove_serializer_spec.rb new file mode 100644 index 0000000000..0e4b199838 --- /dev/null +++ b/spec/serializers/activitypub/remove_serializer_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::RemoveSerializer do + describe '.serializer_for' do + subject { described_class.serializer_for(model, {}) } + + context 'with a Status model' do + let(:model) { Status.new } + + it { is_expected.to eq(described_class::UriSerializer) } + end + + context 'with a FeaturedTag model' do + let(:model) { FeaturedTag.new } + + it { is_expected.to eq(ActivityPub::HashtagSerializer) } + end + + context 'with an Array' do + let(:model) { [] } + + it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) } + end + end +end diff --git a/spec/serializers/rest/account_relationship_severance_event_serializer_spec.rb b/spec/serializers/rest/account_relationship_severance_event_serializer_spec.rb new file mode 100644 index 0000000000..95b4d7dcd2 --- /dev/null +++ b/spec/serializers/rest/account_relationship_severance_event_serializer_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::AccountRelationshipSeveranceEventSerializer do + subject { serialized_record_json(record, described_class) } + + let(:record) { Fabricate.build :account_relationship_severance_event, id: 123 } + + describe 'serialization' do + it 'returns expected values' do + expect(subject) + .to include( + 'id' => be_a(String).and(eq('123')) + ) + end + end +end diff --git a/spec/serializers/rest/account_warning_serializer_spec.rb b/spec/serializers/rest/account_warning_serializer_spec.rb new file mode 100644 index 0000000000..0f335d1215 --- /dev/null +++ b/spec/serializers/rest/account_warning_serializer_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::AccountWarningSerializer do + subject { serialized_record_json(record, described_class) } + + let(:record) { Fabricate :account_warning, id: 123, status_ids: [456, 789] } + + describe 'serialization' do + it 'returns expected values' do + expect(subject) + .to include( + 'id' => be_a(String).and(eq('123')), + 'status_ids' => be_a(Array).and(eq(['456', '789'])) + ) + end + end +end diff --git a/spec/serializers/rest/admin/account_serializer_spec.rb b/spec/serializers/rest/admin/account_serializer_spec.rb new file mode 100644 index 0000000000..58f58a997b --- /dev/null +++ b/spec/serializers/rest/admin/account_serializer_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::Admin::AccountSerializer do + subject { serialized_record_json(record, described_class) } + + describe 'created_by_application_id' do + context 'when account is application-created' do + let(:record) { Fabricate :account, user: Fabricate(:user, created_by_application: application) } + let(:application) { Fabricate :application } + + it { is_expected.to include('created_by_application_id' => application.id.to_s) } + end + end + + describe 'invited_by_account_id' do + context 'when account was invited' do + let(:record) { Fabricate :account, user: Fabricate(:user, invite: invite) } + let(:invite) { Fabricate :invite } + + it { is_expected.to include('invited_by_account_id' => invite.user.account.id.to_s) } + end + end +end diff --git a/spec/serializers/rest/admin/cohort_serializer_spec.rb b/spec/serializers/rest/admin/cohort_serializer_spec.rb new file mode 100644 index 0000000000..ed6067c0d2 --- /dev/null +++ b/spec/serializers/rest/admin/cohort_serializer_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::Admin::CohortSerializer do + subject { serialized_record_json(record, described_class) } + + let(:record) { Admin::Metrics::Retention.new('2024-01-01', '2024-01-02', 'day').cohorts.first } + + describe 'serialization' do + it 'returns expected values' do + expect(subject) + .to include( + 'data' => be_a(Array), + 'period' => /2024-01-01/ + ) + end + end +end diff --git a/spec/serializers/rest/admin/webhook_event_serializer_spec.rb b/spec/serializers/rest/admin/webhook_event_serializer_spec.rb new file mode 100644 index 0000000000..3cbfbd92a3 --- /dev/null +++ b/spec/serializers/rest/admin/webhook_event_serializer_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::Admin::WebhookEventSerializer do + describe '.serializer_for' do + subject { described_class.serializer_for(model, {}) } + + context 'with an Account model' do + let(:model) { Account.new } + + it { is_expected.to eq(REST::Admin::AccountSerializer) } + end + + context 'with a Report model' do + let(:model) { Report.new } + + it { is_expected.to eq(REST::Admin::ReportSerializer) } + end + + context 'with a Status model' do + let(:model) { Status.new } + + it { is_expected.to eq(REST::StatusSerializer) } + end + + context 'with an Array' do + let(:model) { [] } + + it { is_expected.to eq(ActiveModel::Serializer::CollectionSerializer) } + end + end +end diff --git a/spec/serializers/rest/appeal_serializer_spec.rb b/spec/serializers/rest/appeal_serializer_spec.rb new file mode 100644 index 0000000000..1ae6617de5 --- /dev/null +++ b/spec/serializers/rest/appeal_serializer_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::AppealSerializer do + subject { serialized_record_json(record, described_class) } + + describe 'state' do + context 'when appeal is approved' do + let(:record) { Fabricate.build :appeal, approved_at: 2.days.ago } + + it { is_expected.to include('state' => 'approved') } + end + + context 'when appeal is rejected' do + let(:record) { Fabricate.build :appeal, rejected_at: 2.days.ago } + + it { is_expected.to include('state' => 'rejected') } + end + + context 'when appeal is not approved or rejected' do + let(:record) { Fabricate.build :appeal, approved_at: nil, rejected_at: nil } + + it { is_expected.to include('state' => 'pending') } + end + end +end diff --git a/spec/serializers/rest/custom_emoji_serializer_spec.rb b/spec/serializers/rest/custom_emoji_serializer_spec.rb new file mode 100644 index 0000000000..a694ca515a --- /dev/null +++ b/spec/serializers/rest/custom_emoji_serializer_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::CustomEmojiSerializer do + subject { serialized_record_json(record, described_class) } + + let(:record) { Fabricate.build :custom_emoji, id: 123, category: Fabricate(:custom_emoji_category, name: 'Category Name') } + + describe 'serialization' do + it 'returns expected values' do + expect(subject) + .to include( + 'category' => be_a(String).and(eq('Category Name')) + ) + end + end +end diff --git a/spec/serializers/rest/extended_description_serializer_spec.rb b/spec/serializers/rest/extended_description_serializer_spec.rb new file mode 100644 index 0000000000..d7bd078e1d --- /dev/null +++ b/spec/serializers/rest/extended_description_serializer_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::ExtendedDescriptionSerializer do + subject { serialized_record_json(record, described_class) } + + describe 'serialization' do + context 'with text present' do + let(:record) { ExtendedDescription.new text: 'Hello world', updated_at: Date.new(2024, 1, 1) } + + it 'returns expected values' do + expect(subject) + .to include( + 'content' => eq(<<~HTML), +

Hello world

+ HTML + 'updated_at' => eq('2024-01-01') + ) + end + end + + context 'with text missing' do + let(:record) { ExtendedDescription.new text: nil, updated_at: Date.new(2024, 1, 1) } + + it 'returns expected values' do + expect(subject) + .to include( + 'content' => eq(''), + 'updated_at' => eq('2024-01-01') + ) + end + end + end +end diff --git a/spec/serializers/rest/rule_serializer_spec.rb b/spec/serializers/rest/rule_serializer_spec.rb new file mode 100644 index 0000000000..4d801e77d3 --- /dev/null +++ b/spec/serializers/rest/rule_serializer_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::RuleSerializer do + subject { serialized_record_json(record, described_class) } + + let(:record) { Fabricate.build :rule, id: 123 } + + describe 'serialization' do + it 'returns expected values' do + expect(subject) + .to include( + 'id' => be_a(String).and(eq('123')) + ) + end + end +end diff --git a/spec/serializers/rest/status_serializer_spec.rb b/spec/serializers/rest/status_serializer_spec.rb new file mode 100644 index 0000000000..e96d1fbe67 --- /dev/null +++ b/spec/serializers/rest/status_serializer_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe REST::StatusSerializer do + subject do + serialized_record_json( + status, + described_class, + options: { + scope: current_user, + scope_name: :current_user, + } + ) + end + + let(:current_user) { Fabricate(:user) } + let(:alice) { Fabricate(:account, username: 'alice') } + let(:bob) { Fabricate(:account, username: 'bob', domain: 'other.com') } + let(:status) { Fabricate(:status, account: alice) } + + context 'with a remote status' do + let(:status) { Fabricate(:status, account: bob) } + + before do + status.status_stat.tap do |status_stat| + status_stat.reblogs_count = 10 + status_stat.favourites_count = 20 + status_stat.save + end + end + + context 'with only trusted counts' do + it 'shows the trusted counts' do + expect(subject['reblogs_count']).to eq(10) + expect(subject['favourites_count']).to eq(20) + end + end + + context 'with untrusted counts' do + before do + status.status_stat.tap do |status_stat| + status_stat.untrusted_reblogs_count = 30 + status_stat.untrusted_favourites_count = 40 + status_stat.save + end + end + + it 'shows the untrusted counts' do + expect(subject['reblogs_count']).to eq(30) + expect(subject['favourites_count']).to eq(40) + end + end + end +end diff --git a/spec/services/app_sign_up_service_spec.rb b/spec/services/app_sign_up_service_spec.rb index ec7b7516f9..b78868db49 100644 --- a/spec/services/app_sign_up_service_spec.rb +++ b/spec/services/app_sign_up_service_spec.rb @@ -53,17 +53,7 @@ RSpec.describe AppSignUpService do Setting.registrations_mode = 'open' Fabricate(:email_domain_block, allow_with_approval: true, domain: 'smtp.email.com') allow(User).to receive(:skip_mx_check?).and_return(false) - - resolver = instance_double(Resolv::DNS, :timeouts= => nil) - - allow(resolver).to receive(:getresources) - .with('email.com', Resolv::DNS::Resource::IN::MX) - .and_return([instance_double(Resolv::DNS::Resource::MX, exchange: 'smtp.email.com')]) - allow(resolver).to receive(:getresources).with('email.com', Resolv::DNS::Resource::IN::A).and_return([]) - allow(resolver).to receive(:getresources).with('email.com', Resolv::DNS::Resource::IN::AAAA).and_return([]) - allow(resolver).to receive(:getresources).with('smtp.email.com', Resolv::DNS::Resource::IN::A).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: '2.3.4.5')]) - allow(resolver).to receive(:getresources).with('smtp.email.com', Resolv::DNS::Resource::IN::AAAA).and_return([instance_double(Resolv::DNS::Resource::IN::AAAA, address: 'fd00::2')]) - allow(Resolv::DNS).to receive(:open).and_yield(resolver) + configure_mx(domain: 'email.com', exchange: 'smtp.email.com') end it 'creates an unapproved user', :aggregate_failures do diff --git a/spec/services/translate_status_service_spec.rb b/spec/services/translate_status_service_spec.rb index cd92fb8d10..ac7a43ff2a 100644 --- a/spec/services/translate_status_service_spec.rb +++ b/spec/services/translate_status_service_spec.rb @@ -18,7 +18,7 @@ RSpec.describe TranslateStatusService do 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( @@ -37,6 +37,7 @@ RSpec.describe TranslateStatusService do .to have_attributes( content: '

Hola

', detected_source_language: 'en', + language: 'es', provider: 'Dummy', status: status ) @@ -101,6 +102,16 @@ RSpec.describe TranslateStatusService do 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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2a27544407..13683e404e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -34,8 +34,8 @@ RSpec.configure do |config| end end -def serialized_record_json(record, serializer, adapter: nil) - options = { serializer: serializer } +def serialized_record_json(record, serializer, adapter: nil, options: {}) + options[:serializer] = serializer options[:adapter] = adapter if adapter.present? JSON.parse( ActiveModelSerializers::SerializableResource.new( diff --git a/spec/support/command_line_helpers.rb b/spec/support/command_line_helpers.rb index 6f9d63d939..09b2b70ba1 100644 --- a/spec/support/command_line_helpers.rb +++ b/spec/support/command_line_helpers.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true module CommandLineHelpers - def output_results(*args) + def output_results(*) output( - include(*args) + include(*) ).to_stdout end end diff --git a/spec/support/domain_helpers.rb b/spec/support/domain_helpers.rb new file mode 100644 index 0000000000..9977702099 --- /dev/null +++ b/spec/support/domain_helpers.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module DomainHelpers + def configure_mx(domain:, exchange:, ip_v4_addr: '2.3.4.5', ip_v6_addr: 'fd00::2') + resolver = instance_double(Resolv::DNS, :timeouts= => nil) + + allow(resolver).to receive(:getresources) + .with(domain, Resolv::DNS::Resource::IN::MX) + .and_return([double_mx(exchange)]) + allow(resolver) + .to receive(:getresources) + .with(domain, Resolv::DNS::Resource::IN::A) + .and_return([]) + allow(resolver) + .to receive(:getresources) + .with(domain, Resolv::DNS::Resource::IN::AAAA) + .and_return([]) + allow(resolver) + .to receive(:getresources) + .with(exchange, Resolv::DNS::Resource::IN::A) + .and_return([double_resource_v4(ip_v4_addr)]) + allow(resolver) + .to receive(:getresources) + .with(exchange, Resolv::DNS::Resource::IN::AAAA) + .and_return([double_resource_v6(ip_v6_addr)]) + allow(Resolv::DNS) + .to receive(:open) + .and_yield(resolver) + end + + private + + def double_mx(exchange) + instance_double(Resolv::DNS::Resource::MX, exchange: exchange) + end + + def double_resource_v4(addr) + instance_double(Resolv::DNS::Resource::IN::A, address: addr) + end + + def double_resource_v6(addr) + instance_double(Resolv::DNS::Resource::IN::AAAA, address: addr) + end +end diff --git a/spec/support/stories/profile_stories.rb b/spec/support/stories/profile_stories.rb index 07eaaca9fb..43a8e170cc 100644 --- a/spec/support/stories/profile_stories.rb +++ b/spec/support/stories/profile_stories.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module ProfileStories - attr_reader :bob, :alice, :alice_bio + attr_reader :bob def fill_in_auth_details(email, password) fill_in 'user_email', with: email @@ -31,18 +31,6 @@ module ProfileStories bob.update!(role: UserRole.find_by!(name: 'Admin')) end - def with_alice_as_local_user - @alice_bio = '@alice and @bob are fictional characters commonly used as' \ - 'placeholder names in #cryptology, as well as #science and' \ - 'engineering 📖 literature. Not affiliated with @pepe.' - - @alice = Fabricate( - :user, - email: 'alice@example.com', password: password, confirmed_at: confirmed_at, - account: Fabricate(:account, username: 'alice', note: @alice_bio) - ) - end - def confirmed_at @confirmed_at ||= Time.zone.now end diff --git a/spec/system/admin/invites_spec.rb b/spec/system/admin/invites_spec.rb new file mode 100644 index 0000000000..f2cee626c6 --- /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 1e787ea110..d0f70a93f0 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/profile_spec.rb b/spec/system/profile_spec.rb index 7e3cbfd334..a05a146fef 100644 --- a/spec/system/profile_spec.rb +++ b/spec/system/profile_spec.rb @@ -11,10 +11,10 @@ RSpec.describe 'Profile' do before do as_a_logged_in_user - with_alice_as_local_user + Fabricate(:user, account: Fabricate(:account, username: 'alice')) end - it 'I can view Annes public account' do + it 'I can view public account page for Alice' do visit account_path('alice') expect(subject).to have_title("alice (@alice@#{local_domain})") diff --git a/spec/workers/account_refresh_worker_spec.rb b/spec/workers/account_refresh_worker_spec.rb index 3e88e8db28..4408ef77a9 100644 --- a/spec/workers/account_refresh_worker_spec.rb +++ b/spec/workers/account_refresh_worker_spec.rb @@ -7,9 +7,7 @@ RSpec.describe AccountRefreshWorker do let(:service) { instance_double(ResolveAccountService, call: true) } describe '#perform' do - before do - allow(ResolveAccountService).to receive(:new).and_return(service) - end + before { stub_service } context 'when account does not exist' do it 'returns immediately without processing' do @@ -48,5 +46,11 @@ RSpec.describe AccountRefreshWorker do (Account::BACKGROUND_REFRESH_INTERVAL + 3.days).ago end end + + def stub_service + allow(ResolveAccountService) + .to receive(:new) + .and_return(service) + end end end diff --git a/spec/workers/activitypub/followers_synchronization_worker_spec.rb b/spec/workers/activitypub/followers_synchronization_worker_spec.rb new file mode 100644 index 0000000000..0847b247e3 --- /dev/null +++ b/spec/workers/activitypub/followers_synchronization_worker_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ActivityPub::FollowersSynchronizationWorker do + let(:worker) { described_class.new } + let(:service) { instance_double(ActivityPub::SynchronizeFollowersService, call: true) } + + describe '#perform' do + before { stub_service } + + let(:account) { Fabricate(:account, domain: 'host.example') } + let(:url) { 'https://sync.url' } + + it 'sends the status to the service' do + worker.perform(account.id, url) + + expect(service).to have_received(:call).with(account, url) + end + + it 'returns nil for non-existent record' do + result = worker.perform(123_123_123, url) + + expect(result).to be(true) + end + end + + def stub_service + allow(ActivityPub::SynchronizeFollowersService) + .to receive(:new) + .and_return(service) + end +end diff --git a/spec/workers/push_conversation_worker_spec.rb b/spec/workers/push_conversation_worker_spec.rb index d651059c9a..a98c603c17 100644 --- a/spec/workers/push_conversation_worker_spec.rb +++ b/spec/workers/push_conversation_worker_spec.rb @@ -6,8 +6,30 @@ RSpec.describe PushConversationWorker do let(:worker) { described_class.new } describe 'perform' do - it 'runs without error for missing record' do - expect { worker.perform(nil) }.to_not raise_error + context 'with missing values' do + it 'runs without error' do + expect { worker.perform(nil) } + .to_not raise_error + end + end + + context 'with valid records' do + let(:account_conversation) { Fabricate :account_conversation } + + before { allow(redis).to receive(:publish) } + + it 'pushes message to timeline' do + expect { worker.perform(account_conversation.id) } + .to_not raise_error + + expect(redis) + .to have_received(:publish) + .with(redis_key, anything) + end + + def redis_key + "timeline:direct:#{account_conversation.account_id}" + end end end end diff --git a/spec/workers/push_update_worker_spec.rb b/spec/workers/push_update_worker_spec.rb index 6206ab5986..f3e0a128df 100644 --- a/spec/workers/push_update_worker_spec.rb +++ b/spec/workers/push_update_worker_spec.rb @@ -6,11 +6,31 @@ RSpec.describe PushUpdateWorker do let(:worker) { described_class.new } describe 'perform' do - it 'runs without error for missing record' do - account_id = nil - status_id = nil + context 'with missing values' do + it 'runs without error' do + expect { worker.perform(nil, nil) } + .to_not raise_error + end + end - expect { worker.perform(account_id, status_id) }.to_not raise_error + context 'with valid records' do + let(:account) { Fabricate :account } + let(:status) { Fabricate :status } + + before { allow(redis).to receive(:publish) } + + it 'pushes message to timeline' do + expect { worker.perform(account.id, status.id) } + .to_not raise_error + + expect(redis) + .to have_received(:publish) + .with(redis_key, anything) + end + + def redis_key + "timeline:#{account.id}" + end end end end diff --git a/spec/workers/remote_account_refresh_worker_spec.rb b/spec/workers/remote_account_refresh_worker_spec.rb new file mode 100644 index 0000000000..9938d971b9 --- /dev/null +++ b/spec/workers/remote_account_refresh_worker_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe RemoteAccountRefreshWorker do + let(:worker) { described_class.new } + let(:service) { instance_double(ActivityPub::FetchRemoteAccountService, call: true) } + + describe '#perform' do + before { stub_service } + + let(:account) { Fabricate(:account, domain: 'host.example') } + + it 'sends the status to the service' do + worker.perform(account.id) + + expect(service).to have_received(:call).with(account.uri) + end + + it 'returns nil for non-existent record' do + result = worker.perform(123_123_123) + + expect(result).to be_nil + end + + it 'returns nil for a local record' do + account = Fabricate :account, domain: nil + result = worker.perform(account) + expect(result).to be_nil + end + + def stub_service + allow(ActivityPub::FetchRemoteAccountService) + .to receive(:new) + .and_return(service) + end + end +end diff --git a/spec/workers/remove_featured_tag_worker_spec.rb b/spec/workers/remove_featured_tag_worker_spec.rb index 7866824ee7..a8a5bcea81 100644 --- a/spec/workers/remove_featured_tag_worker_spec.rb +++ b/spec/workers/remove_featured_tag_worker_spec.rb @@ -4,12 +4,35 @@ require 'rails_helper' RSpec.describe RemoveFeaturedTagWorker do let(:worker) { described_class.new } + let(:service) { instance_double(RemoveFeaturedTagService, call: true) } describe 'perform' do - it 'runs without error for missing record' do - account_id = nil - featured_tag_id = nil - expect { worker.perform(account_id, featured_tag_id) }.to_not raise_error + context 'with missing values' do + it 'runs without error' do + expect { worker.perform(nil, nil) } + .to_not raise_error + end + end + + context 'with real records' do + before { stub_service } + + let(:account) { Fabricate :account } + let(:featured_tag) { Fabricate :featured_tag } + + it 'calls the service for processing' do + worker.perform(account.id, featured_tag.id) + + expect(service) + .to have_received(:call) + .with(be_an(Account), be_an(FeaturedTag)) + end + + def stub_service + allow(RemoveFeaturedTagService) + .to receive(:new) + .and_return(service) + end end end end diff --git a/spec/workers/resolve_account_worker_spec.rb b/spec/workers/resolve_account_worker_spec.rb index de349adacb..58c2c12129 100644 --- a/spec/workers/resolve_account_worker_spec.rb +++ b/spec/workers/resolve_account_worker_spec.rb @@ -4,10 +4,34 @@ require 'rails_helper' RSpec.describe ResolveAccountWorker do let(:worker) { described_class.new } + let(:service) { instance_double(ResolveAccountService, call: true) } describe 'perform' do - it 'runs without error for missing record' do - expect { worker.perform(nil) }.to_not raise_error + context 'with missing values' do + it 'runs without error' do + expect { worker.perform(nil) } + .to_not raise_error + end + end + + context 'with a URI' do + before { stub_service } + + let(:uri) { 'https://host/path/value' } + + it 'initiates account resolution' do + worker.perform(uri) + + expect(service) + .to have_received(:call) + .with(uri) + end + + def stub_service + allow(ResolveAccountService) + .to receive(:new) + .and_return(service) + 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 7071fa6e98..98150aa5ef 100644 --- a/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb +++ b/spec/workers/scheduler/ip_cleanup_scheduler_spec.rb @@ -5,9 +5,50 @@ require 'rails_helper' 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 7f836d99e4..4993d467b3 100644 --- a/spec/workers/web/push_notification_worker_spec.rb +++ b/spec/workers/web/push_notification_worker_spec.rb @@ -61,6 +61,7 @@ RSpec.describe Web::PushNotificationWorker do 'Ttl' => '172800', 'Urgency' => 'normal', 'Authorization' => 'WebPush jwt.encoded.payload', + 'Unsubscribe-URL' => %r{/api/web/push_subscriptions/}, }, body: "+\xB8\xDBT}\u0013\xB6\xDD.\xF9\xB0\xA7\xC8Ҁ\xFD\x99#\xF7\xAC\x83\xA4\xDB,\u001F\xB5\xB9w\x85>\xF7\xADr" ) diff --git a/streaming/Dockerfile b/streaming/Dockerfile index bed6b63738..f94c04e7a2 100644 --- a/streaming/Dockerfile +++ b/streaming/Dockerfile @@ -9,7 +9,7 @@ ARG BUILDPLATFORM=${BUILDPLATFORM} # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # renovate: datasource=node-version depName=node -ARG NODE_MAJOR_VERSION="20" +ARG NODE_MAJOR_VERSION="22" # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] ARG DEBIAN_VERSION="bookworm" # Node image to use for base image based on combined variables (ex: 20-bookworm-slim) diff --git a/streaming/index.js b/streaming/index.js index d792f95acf..7bbcc1497f 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 bb6bce3f3c..263339a1ca 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 d573c9b284..585c4be4e1 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.5.0", + "packageManager": "yarn@4.5.1", "engines": { "node": ">=18" }, diff --git a/streaming/redis.js b/streaming/redis.js index 2a36b89dc5..0b582ef2f5 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 20637eff94..36e799c562 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,127 +42,129 @@ __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.25.7": - version: 7.25.7 - resolution: "@babel/code-frame@npm:7.25.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.9, @babel/code-frame@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/code-frame@npm:7.26.0" dependencies: - "@babel/highlight": "npm:^7.25.7" + "@babel/helper-validator-identifier": "npm:^7.25.9" + js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: 10c0/14825c298bdec914caf3d24d1383b6d4cd6b030714686004992f4fc251831ecf432236652896f99d5d341f17170ae9a07b58d8d7b15aa0df8cfa1c5a7d5474bc + checksum: 10c0/46f7e367714be736b52ea3c01b24f47e2102e210fb83021d1c8237d8fc511b9538909e16e2fcdbb5cb6173e0794e28624309a59014e52fcfb7bde908f5284388 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/compat-data@npm:7.25.7" - checksum: 10c0/e5cc915abdd18d021236474a96606b2d4a915c4fb620c1ad776b8a08d91111e788cb3b7e9bad43593d4e0bfa4f06894357bcb0984102de1861b9e7322b6bc9f8 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.9, @babel/compat-data@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/compat-data@npm:7.26.0" + checksum: 10c0/6325c9151a3c9b0a3a807e854a26255ef66d989bff331475a935af9bb18f160e0fffe6aed550e4e96b63f91efcd874bfbaab2a1f4a2f8d25645d712a0de590fb 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.7 - resolution: "@babel/core@npm:7.25.7" +"@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.26.0 + resolution: "@babel/core@npm:7.26.0" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@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.7" - "@babel/template": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" + "@babel/code-frame": "npm:^7.26.0" + "@babel/generator": "npm:^7.26.0" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-module-transforms": "npm:^7.26.0" + "@babel/helpers": "npm:^7.26.0" + "@babel/parser": "npm:^7.26.0" + "@babel/template": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" 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/dad20af39624086afc3a0910bd97ae712c9ad0e9dda09fc5da93876e8ea1802b63ddd81c44f4aa8a9834db46de801eaab1ce9b81ab54b4fe907ae052c24de136 + checksum: 10c0/91de73a7ff5c4049fbc747930aa039300e4d2670c2a91f5aa622f1b4868600fc89b01b6278385fbcd46f9574186fa3d9b376a9e7538e50f8d118ec13cfbcb63e languageName: node linkType: hard -"@babel/generator@npm:^7.25.7, @babel/generator@npm:^7.7.2": - version: 7.25.7 - resolution: "@babel/generator@npm:7.25.7" +"@babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0, @babel/generator@npm:^7.7.2": + version: 7.26.0 + resolution: "@babel/generator@npm:7.26.0" dependencies: - "@babel/types": "npm:^7.25.7" + "@babel/parser": "npm:^7.26.0" + "@babel/types": "npm:^7.26.0" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^3.0.2" - checksum: 10c0/c03a26c79864d60d04ce36b649c3fa0d6fd7b2bf6a22e22854a0457aa09206508392dd73ee40e7bc8d50b3602f9ff068afa47770cda091d332e7db1ca382ee96 + checksum: 10c0/b6bb9185f19a97eaf58e04a6d39a13237076678e7ed16b6321dea914535d4bf6a8d7727c9dcb65539845aa0096b326eb67be4bab764bd74bcfd848e2eda68609 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-annotate-as-pure@npm:7.25.7" +"@babel/helper-annotate-as-pure@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" dependencies: - "@babel/types": "npm:^7.25.7" - checksum: 10c0/2f020b0fa9d336b5778485cc2de3141561ec436a7591b685457a5bcdae4ce41d9ddee68169c95504e0789e5a4327e73b8b7e72e5b60e82e96d730c4d19255248 + "@babel/types": "npm:^7.25.9" + checksum: 10c0/095b6ba50489d797733abebc4596a81918316a99e3632755c9f02508882912b00c2ae5e468532a25a5c2108d109ddbe9b7da78333ee7cc13817fc50c00cf06fe languageName: node linkType: hard -"@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" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.25.9" dependencies: - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/e9dc5a7920a1d74150dec53ccd5e34f2b31ae307df7cdeec6289866f7bda97ecb1328b49a7710ecde5db5b6daad768c904a030f9a0fa3184963b0017622c42aa + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/a6068bb813e7f72d12b72edeecb99167f60cd7964cacedfb60e01fff5e7bed4a5a7f4f7414de7cf352a1b71487df5f8dab8c2b5230de4ad5aea16adf32e14219 languageName: node linkType: hard -"@babel/helper-builder-react-jsx@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-builder-react-jsx@npm:7.25.7" +"@babel/helper-builder-react-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-builder-react-jsx@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/f8123a76e8c3fcdbb24cc14bfefc80e4c7bf58112ab26bea3247298748c674cbaee70591c362d0d881e4d88154ea4809b145f3ddcf96221cf55ba27bfde535c6 + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/99d6e87eede0971f25b5e638220f5f966c56c03f6a6278a693c73ac0a31acddb86110208a89d948aa337c8cf7998fb317c00e8baf2e9fa0a42b9207b977dc9c6 languageName: node linkType: hard -"@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" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-compilation-targets@npm:7.25.9" dependencies: - "@babel/compat-data": "npm:^7.25.7" - "@babel/helper-validator-option": "npm:^7.25.7" + "@babel/compat-data": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" browserslist: "npm:^4.24.0" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/705be7e5274a3fdade68e3e2cf42e2b600316ab52794e13b91299a16f16c926f15886b6e9d6df20eb943ccc1cdba5a363d4766f8d01e47b8e6f4e01175f5e66c + checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa languageName: node linkType: hard -"@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" +"@babel/helper-create-class-features-plugin@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.9" dependencies: - "@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" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-member-expression-to-functions": "npm:^7.25.9" + "@babel/helper-optimise-call-expression": "npm:^7.25.9" + "@babel/helper-replace-supers": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/405c3c1a137acda1206380a96993cf2cfd808b3bee1c11c4af47ee0f03a20858497aa53394d6adc5431793c543be5e02010620e871a5ab39d938ae90a54b50f2 + checksum: 10c0/b2bdd39f38056a76b9ba00ec5b209dd84f5c5ebd998d0f4033cf0e73d5f2c357fbb49d1ce52db77a2709fb29ee22321f84a5734dc9914849bdfee9ad12ce8caf languageName: node linkType: hard -"@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" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.25.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" regexpu-core: "npm:^6.1.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/75919fd5a67cd7be8497b56f7b9ed6b4843cb401956ba8d403aa9ae5b005bc28e35c7f27e704d820edbd1154394ed7a7984d4719916795d89d716f6980fe8bd4 + checksum: 10c0/3adc60a758febbf07d65a15eaccab1f7b9fcc55e7141e59122f13c9f81fc0d1cce4525b7f4af50285d27c93b34c859fd2c39c39820c5fb92211898c3bbdc77ef languageName: node linkType: hard @@ -181,223 +183,210 @@ __metadata: languageName: node linkType: hard -"@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" +"@babel/helper-member-expression-to-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-member-expression-to-functions@npm:7.25.9" dependencies: - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/1e948162ab48d84593a7c6ec9570d14c906146f1697144fc369c59dbeb00e4a062da67dd06cb0d8f98a044cd8389002dcf2ab6f5613d99c35748307846ec63fc + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/e08c7616f111e1fb56f398365e78858e26e466d4ac46dff25921adc5ccae9b232f66e952a2f4162bbe336627ba336c7fd9eca4835b6548935973d3380d77eaff 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.25.7": - version: 7.25.7 - resolution: "@babel/helper-module-imports@npm:7.25.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.9": + version: 7.25.9 + resolution: "@babel/helper-module-imports@npm:7.25.9" dependencies: - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/0fd0c3673835e5bf75558e184bcadc47c1f6dd2fe2016d53ebe1e5a6ae931a44e093015c2f9a6651c1a89f25c76d9246710c2b0b460b95ee069c464f2837fa2c + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-module-transforms@npm:7.25.7" +"@babel/helper-module-transforms@npm:^7.25.9, @babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" dependencies: - "@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" + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/f37fa7d1d4df21690535b278468cbd5faf0133a3080f282000cfa4f3ffc9462a1458f866b04b6a2f2d1eec4691236cba9a867da61270dab3ab19846e62f05090 + checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-optimise-call-expression@npm:7.25.7" +"@babel/helper-optimise-call-expression@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-optimise-call-expression@npm:7.25.9" dependencies: - "@babel/types": "npm:^7.25.7" - checksum: 10c0/19b4cc7e77811b1fedca4928dbc14026afef913c2ba4142e5e110ebdcb5c3b2efc0f0fbee9f362c23a194674147b9d627adea71c289b9be08b9067bc0085308b + "@babel/types": "npm:^7.25.9" + checksum: 10c0/90203e6607edeadd2a154940803fd616c0ed92c1013d6774c4b8eb491f1a5a3448b68faae6268141caa5c456e55e3ee49a4ed2bd7ddaf2365daea321c435914c 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.25.7, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.25.7 - resolution: "@babel/helper-plugin-utils@npm:7.25.7" - checksum: 10c0/241f8cf3c5b7700e91cab7cfe5b432a3c710ae3cd5bb96dc554da536a6d25f5b9f000cc0c0917501ceb4f76ba92599ee3beb25e10adaf96be59f8df89a842faf +"@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.9, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.25.9 + resolution: "@babel/helper-plugin-utils@npm:7.25.9" + checksum: 10c0/483066a1ba36ff16c0116cd24f93de05de746a603a777cd695ac7a1b034928a65a4ecb35f255761ca56626435d7abdb73219eba196f9aa83b6c3c3169325599d languageName: node linkType: hard -"@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" +"@babel/helper-remap-async-to-generator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.25.7" - "@babel/helper-wrap-function": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-wrap-function": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/972d84876adce6ab61c87a2df47e1afc790b73cff0d1767d0a1c5d9f7aa5e91d8c581a272b66b2051a26cfbb167d8a780564705e488e3ce1f477f1c15059bc5f + checksum: 10c0/6798b562f2788210980f29c5ee96056d90dc73458c88af5bd32f9c82e28e01975588aa2a57bb866c35556bd9b76bac937e824ee63ba472b6430224b91b4879e9 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-replace-supers@npm:7.25.7" +"@babel/helper-replace-supers@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-replace-supers@npm:7.25.9" dependencies: - "@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" + "@babel/helper-member-expression-to-functions": "npm:^7.25.9" + "@babel/helper-optimise-call-expression": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/761d64ee74429f7326a6aa65e2cd5bfcb8de9e3bc3f1efb14b8f610d2410f003b0fca52778dc801d49ff8fbc90b057e8f51b27c62b0b05c95eaf23140ca1287b + checksum: 10c0/0b40d7d2925bd3ba4223b3519e2e4d2456d471ad69aa458f1c1d1783c80b522c61f8237d3a52afc9e47c7174129bbba650df06393a6787d5722f2ec7f223c3f4 languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-simple-access@npm:7.25.7" +"@babel/helper-simple-access@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-simple-access@npm:7.25.9" dependencies: - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/eed1b499bfb4f613c18debd61517e3de77b6da2727ca025aa05ac81599e0269f1dddb5237db04e8bb598115d015874752e0a7f11ff38672d74a4976097417059 + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/3f1bcdb88ee3883ccf86959869a867f6bbf8c4737cd44fb9f799c38e54f67474590bc66802500ae9fe18161792875b2cfb7ec15673f48ed6c8663f6d09686ca8 languageName: node linkType: hard -"@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" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.9" dependencies: - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/5804adb893849a9d8cfb548e3812566a81d95cb0c9a10d66b52912d13f488e577c33063bf19bc06ac70e6333162a7370d67ba1a1c3544d37fb50d5f4a00db4de + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/09ace0c6156961624ac9524329ce7f45350bab94bbe24335cbe0da7dfaa1448e658771831983cb83fe91cf6635b15d0a3cab57c03b92657480bfb49fb56dd184 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-string-parser@npm:7.25.7" - checksum: 10c0/73ef2ceb81f8294678a0afe8ab0103729c0370cac2e830e0d5128b03be5f6a2635838af31d391d763e3c5a4460ed96f42fd7c9b552130670d525be665913bc4c +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-validator-identifier@npm:7.25.7" - checksum: 10c0/07438e5bf01ab2882a15027fdf39ac3b0ba1b251774a5130917907014684e2f70fef8fd620137ca062c4c4eedc388508d2ea7a3a7d9936a32785f4fe116c68c0 +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-validator-option@npm:7.25.7" - checksum: 10c0/12ed418c8e3ed9ed44c8c80d823f4e42d399b5eb2e423adccb975e31a31a008cd3b5d8eab688b31f740caff4a1bb28fe06ea2fa7d635aee34cc0ad6995d50f0a +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helper-wrap-function@npm:7.25.7" +"@babel/helper-wrap-function@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-wrap-function@npm:7.25.9" dependencies: - "@babel/template": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/b5d412f72697f4a4ce4cb9784fbaf82501c63cf95066c0eadd3179e3439cbbf0aa5fa4858d93590083671943cd357aeb87286958df34aa56fdf8a4c9dea39755 + "@babel/template": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/b6627d83291e7b80df020f8ee2890c52b8d49272962cac0114ef90f189889c90f1027985873d1b5261a4e986e109b2754292dc112392f0b1fcbfc91cc08bd003 languageName: node linkType: hard -"@babel/helpers@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/helpers@npm:7.25.7" +"@babel/helpers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helpers@npm:7.26.0" dependencies: - "@babel/template": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/3b3ae9e373bd785414195ef8f59976a69d5a6ebe0ef2165fdcc5165e5c3ee09e0fcee94bb457df2ddb8c0532e4146d0a9b7a96b3497399a4bff4ffe196b30228 + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.26.0" + checksum: 10c0/343333cced6946fe46617690a1d0789346960910225ce359021a88a60a65bc0d791f0c5d240c0ed46cf8cc63b5fd7df52734ff14e43b9c32feae2b61b1647097 languageName: node linkType: hard -"@babel/highlight@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/highlight@npm:7.25.7" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0": + version: 7.26.1 + resolution: "@babel/parser@npm:7.26.1" dependencies: - "@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/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.7": - version: 7.25.7 - resolution: "@babel/parser@npm:7.25.7" - dependencies: - "@babel/types": "npm:^7.25.7" + "@babel/types": "npm:^7.26.0" bin: parser: ./bin/babel-parser.js - checksum: 10c0/b771469bb6b636c18a8d642b9df3c73913c3860a979591e1a29a98659efd38b81d3e393047b5251fe382d4c82c681c12da9ce91c98d69316d2604d155a214bcf + checksum: 10c0/dc7d4e6b7eb667fa0784e7e2c3f6f92ca12ad72242f6d4311995310dae55093f02acdb595b69b0dbbf04cb61ad87156ac03186ff32eacfa35149c655bc22c14b languageName: node linkType: hard -"@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" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/c6ba97c39973897a2ab021c4a77221e1e93e853a5811d498db325da1bd692e41fa521db6d91bb709ccafd4e54ddd00869ffb35846923c3ccd49d46124b316904 + checksum: 10c0/7aab47fcbb8c1ddc195a3cd66609edcad54c5022f018db7de40185f0182950389690e953e952f117a1737b72f665ff02ad30de6c02b49b97f1d8f4ccdffedc34 languageName: node linkType: hard -"@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" +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/ac284868bf410f952c6959b0d77708464127160416f003b05c8127d30e64792d671abc167ebf778b17707e32174223ea8d3ff487276991fa90297d92f0dac6e2 + checksum: 10c0/3a652b3574ca62775c5f101f8457950edc540c3581226579125da535d67765f41ad7f0e6327f8efeb2540a5dad5bb0c60a89fb934af3f67472e73fb63612d004 languageName: node linkType: hard -"@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" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/1bffc0a20c8c82b4c77515eb4c99b961b38184116f008bb42bed4e12d3379ba7b2bc6cf299bcea8118d645bb7a5e0caa83969842f16dd1fce49fb3a050e4ac65 + checksum: 10c0/18fc9004104a150f9f5da9f3307f361bc3104d16778bb593b7523d5110f04a8df19a2587e6bdd5e726fb1d397191add45223f4f731bb556c33f14f2779d596e8 languageName: node linkType: hard -"@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" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.25.9" dependencies: - "@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" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" + "@babel/plugin-transform-optional-chaining": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.13.0 - checksum: 10c0/32223f012614a0b2657579317ded7d0d09af2aa316285715c5012f974d0f15c2ce2fe0d8e80fdd9bac6c10c21c93cc925a9dfd6c8e21ce7ba1a9fe06a58088b4 + checksum: 10c0/3f6c8781a2f7aa1791a31d2242399ca884df2ab944f90c020b6f112fb19f05fa6dad5be143d274dad1377e40415b63d24d5489faf5060b9c4a99e55d8f0c317c languageName: node linkType: hard -"@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" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/aa2ee7a5954d187de6cbcca0e0b64cfb79c4d224c332d1eb1e0e4afd92ef1a1f4bc4af24f66154097ccb348c08121a875456f47baed220b1b9e93584e6a19b65 + checksum: 10c0/02b365f0cc4df8b8b811c68697c93476da387841e5f153fe42766f34241b685503ea51110d5ed6df7132759820b93e48d9fa3743cffc091eed97c19f7e5fe272 languageName: node linkType: hard @@ -432,7 +421,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 +432,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" +"@babel/plugin-syntax-import-assertions@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": "npm:^7.14.5" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 + checksum: 10c0/525b174e60b210d96c1744c1575fc2ddedcc43a479cba64a5344cf77bd0541754fc58120b5a11ff832ba098437bb05aa80900d1f49bb3d888c5e349a4a3a356e 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" +"@babel/plugin-syntax-import-attributes@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": "npm:^7.8.0" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/9c50927bf71adf63f60c75370e2335879402648f468d0172bc912e303c6a3876927d8eb35807331b57f415392732ed05ab9b42c68ac30a936813ab549e0246c5 + checksum: 10c0/e594c185b12bfe0bbe7ca78dfeebe870e6d569a12128cac86f3164a075fe0ff70e25ddbd97fd0782906b91f65560c9dc6957716b7b4a68aba2516c9b7455e352 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.25.7": - version: 7.25.7 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.25.7" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0fee0d971f3c654749fdf92e09b6556bba26ab014c8e99b7252f6a7f1ca108f17edd7ceefb5401d7b7008e98ab1b6f8c3c6a5db72862e7c7b2fcd649d000d690 - languageName: node - linkType: hard - -"@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.25.7" - peerDependencies: - "@babel/core": ^7.0.0-0 - 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 +476,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:7, @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" +"@babel/plugin-syntax-jsx@npm:^7.25.0, @babel/plugin-syntax-jsx@npm:^7.25.9, @babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.25.9 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/17db499c31fcfaa94d5408726d943955d51d478353d1e2dd84eda6024f7e3d104b9456a77f8aabfae0db7f4dc32f810d08357112f7fcbe305e7c9fcf5b3cac13 + checksum: 10c0/d56597aff4df39d3decda50193b6dfbe596ca53f437ff2934622ce19a743bf7f43492d3fb3308b0289f5cee2b825d99ceb56526a2b9e7b68bf04901546c5618c 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 +509,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 +553,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 +564,14 @@ __metadata: languageName: node linkType: hard -"@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" +"@babel/plugin-syntax-typescript@npm:^7.25.9, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.25.9 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ed51fd81a5cf571a89fc4cf4c0e3b0b91285c367237374c133d2e5e718f3963cfa61b81997df39220a8837dc99f9e9a8ab7701d259c09fae379e4843d9db60c2 + checksum: 10c0/5192ebe11bd46aea68b7a60fd9555465c59af7e279e71126788e59121b86e00b505816685ab4782abe159232b0f73854e804b54449820b0d950b397ee158caa2 languageName: node linkType: hard @@ -642,466 +587,454 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.25.7" +"@babel/plugin-transform-arrow-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c8d75ead93f130bf113b6d29493aca695092661ef039336d2a227169c3b7895aa5e9bcc548c42a95a6eaaaf49e512317b00699940bd40ccefd77443e703d3935 + checksum: 10c0/851fef9f58be60a80f46cc0ce1e46a6f7346a6f9d50fa9e0fa79d46ec205320069d0cc157db213e2bea88ef5b7d9bd7618bb83f0b1996a836e2426c3a3a1f622 languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.7" +"@babel/plugin-transform-async-generator-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-remap-async-to-generator": "npm:^7.25.7" - "@babel/plugin-syntax-async-generators": "npm:^7.8.4" - "@babel/traverse": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-remap-async-to-generator": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/dcdd17d8cafafe0eb2edd0a46a7abe86c72235c957c8eb1157ccadb2b199572d5d1aa36a2d3bce5cb99990f7d3c6290ecf09959c62f3081c4df9ff717a1c84a4 + checksum: 10c0/e3fcb9fc3d6ab6cbd4fcd956b48c17b5e92fe177553df266ffcd2b2c1f2f758b893e51b638e77ed867941e0436487d2b8b505908d615c41799241699b520dec6 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-async-to-generator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.25.9" dependencies: - "@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" + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-remap-async-to-generator": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/1dbefba9c1455f7a92b8c59a93c622091db945294c936fc2c09b1648308c5b4cb2ecaae92baae0d07a324ab890a8a2ee27ceb046bc120932845d27aede275821 + checksum: 10c0/c443d9e462ddef733ae56360064f32fc800105803d892e4ff32d7d6a6922b3765fa97b9ddc9f7f1d3f9d8c2d95721d85bef9dbf507804214c6cf6466b105c168 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-block-scoped-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b1e77492295d1b271ef850a81b0404cf3d0dd6a2bcbeab28a0fd99e61c6de4bda91dff583bb42138eec61bf71282bdd3b1bebcb53b7e373035e77fd6ba66caeb + checksum: 10c0/e92ba0e3d72c038513844d8fca1cc8437dcb35cd42778e97fd03cb8303380b201468611e7ecfdcae3de33473b2679fe2de1552c5f925d112c5693425cf851f10 languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-block-scoping@npm:7.25.7" +"@babel/plugin-transform-block-scoping@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b2057e00535cd0e8bd5ee5d4640aa2e952564aeafb1bcf4e7b6de33442422877bb0ca8669ad0a48262ec077271978c61eae87b6b3bc8f472d830fa781d6f7e44 + checksum: 10c0/a76e30becb6c75b4d87a2cd53556fddb7c88ddd56bfadb965287fd944810ac159aa8eb5705366fc37336041f63154ed9fab3862fb10482a45bf5ede63fd55fda languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-class-properties@npm:7.25.7" +"@babel/plugin-transform-class-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-class-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/1f41e6934b20ad3e05df63959cff9bc600ff3119153b9acbbd44c1731e7df04866397e6e17799173f4c53cdee6115e155632859aee20bf47ec7dcef3f2168a47 + checksum: 10c0/f0603b6bd34d8ba62c03fc0572cb8bbc75874d097ac20cc7c5379e001081210a84dba1749e7123fca43b978382f605bb9973c99caf2c5b4c492d5c0a4a441150 languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-class-static-block@npm:7.25.7" +"@babel/plugin-transform-class-static-block@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-transform-class-static-block@npm:7.26.0" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/helper-create-class-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.12.0 - checksum: 10c0/cbb4b46cbd8ad10106eb2bedb5a0665661a1d1d5b6f3ab565ff454b802dab4718e02b25670fe0d40835494aedb3dc26757c06cc4da6ff3e80291c5f882269bd3 + checksum: 10c0/cdcf5545ae6514ed75fbd73cccfa209c6a5dfdf0c2bb7bb62c0fb4ec334a32281bcf1bc16ace494d9dbe93feb8bdc0bd3cf9d9ccb6316e634a67056fa13b741b languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-classes@npm:7.25.7" +"@babel/plugin-transform-classes@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-classes@npm:7.25.9" dependencies: - "@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" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-replace-supers": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8121781e1d8acd80e6169019106f73a399475ad9c895c1988a344dfed5a6ddd340938ac55123dc1e423bb8f25f255f5d11031116ad756ba3c314595a97c973af + checksum: 10c0/02742ea7cd25be286c982e672619effca528d7a931626a6f3d6cea11852951b7ee973276127eaf6418ac0e18c4d749a16b520709c707e86a67012bd23ff2927d languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-computed-properties@npm:7.25.7" +"@babel/plugin-transform-computed-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-computed-properties@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/template": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/template": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7ad0a1c126f50935a02e77d438ebc39078a9d644b3a60de60bec32c5d9f49e7f2b193fcecb8c61bb1bc3cdd4af1e93f72d022d448511fa76a171527c633cd1bf + checksum: 10c0/948c0ae3ce0ba2375241d122a9bc7cda4a7ac8110bd8a62cd804bc46a5fdb7a7a42c7799c4cd972e14e0a579d2bd0999b92e53177b73f240bb0d4b09972c758b languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-destructuring@npm:7.25.7" +"@babel/plugin-transform-destructuring@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-destructuring@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a563123b2fb267e03aa50104005f00b56226a685938906c42c1b251462e0cc9fc89e587d5656d3324159071eb8ebda8c68a6011f11d5a00fb1436cb5a5411b7b + checksum: 10c0/7beec5fda665d108f69d5023aa7c298a1e566b973dd41290faa18aeea70f6f571295c1ece0a058f3ceb6c6c96de76de7cd34f5a227fbf09a1b8d8a735d28ca49 languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.25.7" +"@babel/plugin-transform-dotall-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7f1db3ec20b7fae46db4a9c4c257d75418b0896b72c0a3de20b3044f952801480f0a2e75ebb0d64f13e8cd4db0e49aa42c5c0edff372b23c41679b1ea5dd3ed4 + checksum: 10c0/7c3471ae5cf7521fd8da5b03e137e8d3733fc5ee4524ce01fb0c812f0bb77cb2c9657bc8a6253186be3a15bb4caa8974993c7ddc067f554ecc6a026f0a3b5e12 languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.25.7" +"@babel/plugin-transform-duplicate-keys@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b4079981e2db19737a0f1a00254e7388e2d3c01ce36e9fd826e4d86d3c1755339495e29c71fd7c84a068201ec24687328d48f3bf53b32b6d6224f51d9a34da74 + checksum: 10c0/d0c74894b9bf6ff2a04189afffb9cd43d87ebd7b7943e51a827c92d2aaa40fa89ac81565a2fd6fbeabf9e38413a9264c45862eee2b017f1d49046cc3c8ff06b4 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/e4946090ff6d88d54b78265ee653079ec34c117ac046e22f66f7c4ac44249cdc2dfca385bc5bf4386db668b9948eeb12985589500188bc252e684c7714c31475 + checksum: 10c0/a8039a6d2b90e011c7b30975edee47b5b1097cf3c2f95ec1f5ddd029898d783a995f55f7d6eb8d6bb8873c060fb64f9f1ccba938dfe22d118d09cf68e0cd3bf6 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.25.7" +"@babel/plugin-transform-dynamic-import@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c733252ff20a32d9747dd081916270f5a073856597e849a5f458b12f4354499b18714f5e7049e341432851d9975077cb37effcd276c7f816faa6f5ff708dc5e1 + checksum: 10c0/5e643a8209072b668350f5788f23c64e9124f81f958b595c80fecca6561086d8ef346c04391b9e5e4cad8b8cbe22c258f0cd5f4ea89b97e74438e7d1abfd98cf languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.25.7" +"@babel/plugin-transform-exponentiation-operator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.25.9" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c8537b9f3cddc5a8d3710f6980196dc7a0f4389f8f82617312a5f7b8b15bcd8ddaeba783c687c3ac6031eb0a4ba0bc380a98da6bf7efe98e225602a98ad42a1e + checksum: 10c0/3b42f65bab3fee28c385115ce6bcb6ba544dff187012df408a432c9fb44c980afd898911020c723dc1c9257aaf3d7d0131ad83ba15102bf30ad9a86fc2a8a912 languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.25.7" +"@babel/plugin-transform-export-namespace-from@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ef61fc5d54c9c8b075cbd9db62beaf295e38e08a1edb1882995105d3e959763be1631f7d7f7cb7461b702ebd0b4a601f2eb2cd6521acaf061310a3a3305fa756 + checksum: 10c0/f291ea2ec5f36de9028a00cbd5b32f08af281b8183bf047200ff001f4cb260be56f156b2449f42149448a4a033bd6e86a3a7f06d0c2825532eb0ae6b03058dfb languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-for-of@npm:7.25.7" +"@babel/plugin-transform-for-of@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-for-of@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/08a37a1742368a422d095c998ed76f60f6bf3f9cc060033be121d803fd2dddc08fe543e48ee49c022bdc9ed80893ca79d084958d83d30684178b088774754277 + checksum: 10c0/bf11abc71934a1f369f39cd7a33cf3d4dc5673026a53f70b7c1238c4fcc44e68b3ca1bdbe3db2076f60defb6ffe117cbe10b90f3e1a613b551d88f7c4e693bbe languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-function-name@npm:7.25.7" +"@babel/plugin-transform-function-name@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-function-name@npm:7.25.9" dependencies: - "@babel/helper-compilation-targets": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/traverse": "npm:^7.25.7" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ca98e1116c0ada7211ed43e4b7f21ca15f95bbbdad70f2fbe1ec2d90a97daedf9f22fcb0a25c8b164a5e394f509f2e4d1f7609d26dc938a58d37c5ee9b80088a + checksum: 10c0/8e67fbd1dd367927b8b6afdf0a6e7cb3a3fd70766c52f700ca77428b6d536f6c9d7ec643e7762d64b23093233765c66bffa40e31aabe6492682879bcb45423e1 languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-json-strings@npm:7.25.7" +"@babel/plugin-transform-json-strings@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-json-strings@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-json-strings": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/aa6e5f65c8a5f2459d7daa9b5b4ff97ff43bab21f4a8513ed84d35300b0323ec542dc101c5f11622e442dfc93b3a229c7f41ebc7645370dfec6d066bda800a0b + checksum: 10c0/00bc2d4751dfc9d44ab725be16ee534de13cfd7e77dfb386e5dac9e48101ce8fcbc5971df919dc25b3f8a0fa85d6dc5f2a0c3cf7ec9d61c163d9823c091844f0 languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-literals@npm:7.25.7" +"@babel/plugin-transform-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c2c2488102f33e566f45becdcb632e53bd052ecfb2879deb07a614b3e9437e3b624c3b16d080096d50b0b622edebd03e438acbf9260bcc41167897963f64560e + checksum: 10c0/00b14e9c14cf1e871c1f3781bf6334cac339c360404afd6aba63d2f6aca9270854d59a2b40abff1c4c90d4ffdca614440842d3043316c2f0ceb155fdf7726b3b languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.25.7" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d610a8a2c1be83e03cce2256f29519e705dc68289c09d67f1f362d1fd80f4b36eaf2affc05710abb53a272895041e24d9e95ec73a516a23a67cb907023fbe37b + checksum: 10c0/6e2051e10b2d6452980fc4bdef9da17c0d6ca48f81b8529e8804b031950e4fff7c74a7eb3de4a2b6ad22ffb631d0b67005425d232cce6e2b29ce861c78ed04f5 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-member-expression-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d6936b98ae4d3daed850dc4e064042ea4375f815219ba9d8591373bf1fba4cfdb5be42623ae8882f2d666cc34af650a4855e2a5ad89e3c235d73a6f172f9969c + checksum: 10c0/91d17b451bcc5ea9f1c6f8264144057ade3338d4b92c0b248366e4db3a7790a28fd59cc56ac433a9627a9087a17a5684e53f4995dd6ae92831cb72f1bd540b54 languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-modules-amd@npm:7.25.7" +"@babel/plugin-transform-modules-amd@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-amd@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-module-transforms": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c0bc999206c3834c090e6559a6c8a55d7672d3573104e832223ebe7df99bd1b82fc850e15ba32f512c84b0db1cdb613b66fa60abe9abb9c7e8dcbff91649b356 + checksum: 10c0/849957d9484d0a2d93331226ed6cf840cee7d57454549534c447c93f8b839ef8553eae9877f8f550e3c39f14d60992f91244b2e8e7502a46064b56c5d68ba855 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.25.7" +"@babel/plugin-transform-modules-commonjs@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-simple-access": "npm:^7.25.7" + "@babel/helper-module-transforms": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-simple-access": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2f1c945fc3c9b690b0ddcf2c80156b2e4fbf2cf15aac43ac8fe6e4b34125869528839a53d07c564e62e4aed394ebdc1d2c3b796b547374455522581c11b7599c + checksum: 10c0/6ce771fb04d4810257fc8900374fece877dacaed74b05eaa16ad9224b390f43795c4d046cbe9ae304e1eb5aad035d37383895e3c64496d647c2128d183916e74 languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.7" +"@babel/plugin-transform-modules-systemjs@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.9" dependencies: - "@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" + "@babel/helper-module-transforms": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + "@babel/traverse": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/95eaea7082636710c61e49e58b3907e85ec79db4327411d3784f28592509fbe94a53cc3d20a36a1cf245efc6d3f0017eae15b45ffd645c1ab949bb4e1670e6bb + checksum: 10c0/8299e3437542129c2684b86f98408c690df27db4122a79edded4782cf04e755d6ecb05b1e812c81a34224a81e664303392d5f3c36f3d2d51fdc99bb91c881e9a languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-modules-umd@npm:7.25.7" +"@babel/plugin-transform-modules-umd@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-umd@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-module-transforms": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8849ab04eecdb73cd37e2d7289449fa5256331832b0304c220b2a6aaa12e2d2dd87684f2813412d1fc5bdb3d6b55cc08c6386d3273fe05a65177c09bee5b6769 + checksum: 10c0/fa11a621f023e2ac437b71d5582f819e667c94306f022583d77da9a8f772c4128861a32bbb63bef5cba581a70cd7dbe87a37238edaafcfacf889470c395e7076 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/eb55fec55dc930cd122911f3e4a421320fa8b1b4de85bfd7ef11b46c611ec69b0213c114a6e1c6bc224d6b954ff183a0caa7251267d5258ecc0f00d6d9ca1d52 + checksum: 10c0/32b14fda5c885d1706863f8af2ee6c703d39264355b57482d3a24fce7f6afbd4c7a0896e501c0806ed2b0759beb621bf7f3f7de1fbbc82026039a98d961e78ef languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-new-target@npm:7.25.7" +"@babel/plugin-transform-new-target@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-new-target@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8e5dce6d027e0f3fd394578ea1af7f515de157793a15c23a5aad7034a6d8a4005ef280238e67a232bb4dd4fafd3a264fed462deb149128ddd9ce59ff6f575cff + checksum: 10c0/7b5f1b7998f1cf183a7fa646346e2f3742e5805b609f28ad5fee22d666a15010f3e398b7e1ab78cddb7901841a3d3f47135929af23d54e8bf4ce69b72051f71e languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.25.7" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b35a96a79ef4895b00e4f758d3185cb17e4fbfada311894ad5f0988a55fc2c21820dc789b26a3cb8fbd620434faa516e52acb6e2da105c2edbd29de8b6b0facf + checksum: 10c0/eb623db5be078a1c974afe7c7797b0309ba2ea9e9237c0b6831ade0f56d8248bb4ab3432ab34495ff8c877ec2fe412ff779d1e9b3c2b8139da18e1753d950bc3 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.25.7" +"@babel/plugin-transform-numeric-separator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c028ae89e6b4e1d757f8f1ebcb3b420e6559bb35002728f6f5651d5f669fbf73764adf6e3597908fa12adf8dbae683e5f74b3a7f68e8774a9663c18c0f999539 + checksum: 10c0/ad63ad341977844b6f9535fcca15ca0d6d6ad112ed9cc509d4f6b75e9bf4b1b1a96a0bcb1986421a601505d34025373608b5f76d420d924b4e21f86b1a1f2749 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.25.7" +"@babel/plugin-transform-object-rest-spread@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.25.9" dependencies: - "@babel/helper-compilation-targets": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-transform-parameters": "npm:^7.25.7" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/plugin-transform-parameters": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e8b978d9d1020452da0d5d92f80fe57e302761dac20137bb8bf863478a4779fcd63d314db89e796125d9d76da2a38f64f012d6e0c4913815951b3eb3fba2feb6 + checksum: 10c0/02077d8abd83bf6a48ff0b59e98d7561407cf75b591cffd3fdc5dc5e9a13dec1c847a7a690983762a3afecddb244831e897e0515c293e7c653b262c30cd614af languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-object-super@npm:7.25.7" +"@babel/plugin-transform-object-super@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-object-super@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-replace-supers": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-replace-supers": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7f2968d4da997101b63fd3b74445c9b16f56bd32cd8a0a16c368af9d3e983e7675c1b05d18601f32307cb06e7d884ee11d13ff18a1f6830c0db243a9a852afab + checksum: 10c0/0348d00e76f1f15ada44481a76e8c923d24cba91f6e49ee9b30d6861eb75344e7f84d62a18df8a6f9e9a7eacf992f388174b7f9cc4ce48287bcefca268c07600 languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.25.7" +"@babel/plugin-transform-optional-catch-binding@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/bb609e5103780be0825a255ffe1fefbb5335aead88a46eecc2257053279ea2c45ff66b0ef1fb54302c8c8c57146e88e52f3ecb62b4c6f619218d7b3843b352d9 + checksum: 10c0/722fd5ee12ab905309d4e84421584fce4b6d9e6b639b06afb20b23fa809e6ab251e908a8d5e8b14d066a28186b8ef8f58d69fd6eca9ce1b9ef7af08333378f6c languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.25.7" +"@babel/plugin-transform-optional-chaining@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/887441ada6c2bc1b789984b7531d9bc585f335ece99642886d3d9fd8aee7e6b8d4f7ca61d76b5f23477f3aa607284d5056eadaa1eb17e7b39af6b0e834cbe878 + checksum: 10c0/041ad2beae5affb8e68a0bcb6882a2dadb758db3c629a0e012f57488ab43a822ac1ea17a29db8ef36560a28262a5dfa4dbbbf06ed6e431db55abe024b7cd3961 languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-parameters@npm:7.25.7" +"@babel/plugin-transform-parameters@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-parameters@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b40ba70278842ce1e800d7ab400df730994941550da547ef453780023bd61a9b8acf4b9fb8419c1b5bcbe09819a1146ff59369db11db07eb71870bef86a12422 + checksum: 10c0/aecb446754b9e09d6b6fa95fd09e7cf682f8aaeed1d972874ba24c0a30a7e803ad5f014bb1fffc7bfeed22f93c0d200947407894ea59bf7687816f2f464f8df3 languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-private-methods@npm:7.25.7" +"@babel/plugin-transform-private-methods@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-private-methods@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-class-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/92e076f63f7c4696e1321dafdd56c4212eb41784cdadba0ebc39091f959a76d357c3df61a6c668be81d6b6ad8964ee458e85752ab0c6cfbbaf2066903edda732 + checksum: 10c0/64bd71de93d39daefa3e6c878d6f2fd238ed7d4ecfb13b0e771ddbbc131487def3ceb405b62b534a5cbb5043046b504e1b189b0a45229cc75af979a9fbcaa7bd languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.25.7" +"@babel/plugin-transform-private-property-in-object@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.25.9" dependencies: - "@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/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-create-class-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5ad8832ba54e2079c1f558b8680e170265e3f376424e5fbb75b17b7f08696fb0af6c96d23d92f7df3dcc559f5971a02587281fcec38a853174aa95478565f5fc + checksum: 10c0/d4965de19d9f204e692cc74dbc39f0bb469e5f29df96dd4457ea23c5e5596fba9d5af76eaa96f9d48a9fc20ec5f12a94c679285e36b8373406868ea228109e27 languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-property-literals@npm:7.25.7" +"@babel/plugin-transform-property-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-property-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6d5bccdc772207906666ad5201bd91e4e132e1d806dbcf4163a1d08e18c57cc3795578c4e10596514bcd6afaf9696f478ea4f0dea890176d93b9cb077b9e5c55 + checksum: 10c0/1639e35b2438ccf3107af760d34e6a8e4f9acdd3ae6186ae771a6e3029bd59dfe778e502d67090f1185ecda5c16addfed77561e39c518a3f51ff10d41790e106 languageName: node linkType: hard @@ -1116,305 +1049,303 @@ __metadata: languageName: node linkType: hard -"@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" +"@babel/plugin-transform-react-display-name@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-display-name@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a0c537cc7c328ed7468d3b6a37bf0d9cb15d94afcdf3f2849ce6e5a68494fc61f0fa4fc529482a6b95b00f3c5c734f310bf18085293bff40702789f06c816f36 + checksum: 10c0/63a0f962d64e71baf87c212755419e25c637d2d95ea6fdc067df26b91e606ae186442ae815b99a577eca9bf5404d9577ecad218a3cf42d0e9e286ca7b003a992 languageName: node linkType: hard "@babel/plugin-transform-react-inline-elements@npm:^7.21.0": - version: 7.25.7 - resolution: "@babel/plugin-transform-react-inline-elements@npm:7.25.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-react-inline-elements@npm:7.25.9" dependencies: - "@babel/helper-builder-react-jsx": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-builder-react-jsx": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/de85180c09002083cb330ef28d5b31b44e6ac6565c700b603be76e629f5a92c59ff69f79c08cc1dbd2dd1f271f44fe8d4c751deaf66c059ba721aa3cb43c881e + checksum: 10c0/d745bcfa8e51acc497b5ea2ff2fc4215cd39ebdb54703f2973962e3818a4829081ebc9e7818db28f90d1295e0b02e140986509ba48eef8aaa9de8c09b9434646 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-react-jsx-development@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.25.9" dependencies: - "@babel/plugin-transform-react-jsx": "npm:^7.25.7" + "@babel/plugin-transform-react-jsx": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a3dc14644d09a6d22875af7b5584393ab53e467e0531cd192fc6242504dacaffa421e89265ba7f84fd4edef2b7b100d2e2ebf092a4dce2b55cf9c5fe29390c18 + checksum: 10c0/c0b92ff9eb029620abf320ff74aae182cea87524723d740fb48a4373d0d16bddf5edbe1116e7ba341332a5337e55c2ceaee8b8cad5549e78af7f4b3cfe77debb languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-react-jsx@npm:7.25.7" +"@babel/plugin-transform-react-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx@npm:7.25.9" dependencies: - "@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" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/plugin-syntax-jsx": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6766b0357b8bbfcb77fca5350f06cf822c89bbe75ddcaea24614601ef23957504da24e76597d743038ce8fa081373b0663c8ad0c86d7c7226e8185f0680b8b56 + checksum: 10c0/5c9947e8ed141f7606f54da3e05eea1074950c5b8354c39df69cb7f43cb5a83c6c9d7973b24bc3d89341c8611f8ad50830a98ab10d117d850e6bdd8febdce221 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-react-pure-annotations@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d92c9b511850fb6dea71966a0d4f313d67e317db7fc3633a7ff2e27d6df2e95cbc91c4c25abdb6c8db651fcda842a0cb7433835a8a9d4a3fdc5d452068428101 + checksum: 10c0/7c8eac04644ad19dcd71bb8e949b0ae22b9e548fa4a58e545d3d0342f647fb89db7f8789a7c5b8074d478ce6d3d581eaf47dd4b36027e16fd68211c383839abc languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-regenerator@npm:7.25.7" +"@babel/plugin-transform-regenerator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-regenerator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" regenerator-transform: "npm:^0.15.2" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7ee3a57c4050bc908ef7ac392d810826b294970a7182f4ec34a8ca93dbe36deb21bc862616d46a6f3d881d6b5749930e1679e875b638a00866d844a4250df212 + checksum: 10c0/eef3ffc19f7d291b863635f32b896ad7f87806d9219a0d3404a470219abcfc5b43aabecd691026c48e875b965760d9c16abee25e6447272233f30cd07f453ec7 languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-reserved-words@npm:7.25.7" +"@babel/plugin-transform-regexp-modifiers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/4abc1db6c964efafc7a927cda814c7275275afa4b530483e0936fd614de23cb5802f7ca43edaa402008a723d4e7eac282b6f5283aa2eeb3b27da6d6c1dd7f8ed + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-reserved-words@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/920c98130daff6c1288fb13a9a2d2e45863bba93e619cb88d90e1f5b5cb358a3ee8880a425a3adb1b4bd5dbb6bd0500eea3370fc612633045eec851b08cc586c + checksum: 10c0/8b028b80d1983e3e02f74e21924323cc66ba930e5c5758909a122aa7d80e341b8b0f42e1698e42b50d47a6ba911332f584200b28e1a4e2104b7514d9dc011e96 languageName: node linkType: hard "@babel/plugin-transform-runtime@npm:^7.22.4": - version: 7.25.7 - resolution: "@babel/plugin-transform-runtime@npm:7.25.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-runtime@npm:7.25.9" dependencies: - "@babel/helper-module-imports": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" 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/9b2514e9079361ac8e7e500ffd522dad869d61a3894302da7e29bbac80de00276c8a1b4394d1dcf0b51c57b2c854919928df9648be336139fdf1d6ecd6d1bb32 + checksum: 10c0/888a4998ba0a2313de347954c9a8dfeccbff0633c69d33aee385b8878eba2b429dbfb00c3cc04f6bca454b9be8afa01ebbd73defb7fbbb6e2d3086205c07758b languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.25.7" +"@babel/plugin-transform-shorthand-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4250f89a0072f0f400be7a2e3515227b8e2518737899bd57d497e5173284a0e05d812e4a3c219ffcd484e9fa9a01c19fce5acd77bbb898f4d594512c56701eb4 + checksum: 10c0/05a20d45f0fb62567644c507ccd4e379c1a74dacf887d2b2cac70247415e3f6d7d3bf4850c8b336053144715fedb6200fc38f7130c4b76c94eec9b9c0c2a8e9b languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-spread@npm:7.25.7" +"@babel/plugin-transform-spread@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-spread@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/258bd1b52388cd7425d0ae25fa39538734f7540ea503a1d8a72211d33f6f214cb4e3b73d6cd03016cbcff5d41169f1e578b9ea331965ad224d223591983e90a7 + checksum: 10c0/996c8fed238efc30e0664f9f58bd7ec8c148f4659f84425f68923a094fe891245711d26eb10d1f815f50c124434e076e860dbe9662240844d1b77cd09907dcdf languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.25.7" +"@babel/plugin-transform-sticky-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/0e466cfc3ca1e0db4bb11eb630215b0e1f43066d7678325e5ddadcf5a118b2351a528f67205729c32ac5b78ab68ab7f40517dd33bcb1fb6b456509f5f54ce097 + checksum: 10c0/e9612b0615dab4c4fba1c560769616a9bd7b9226c73191ef84b6c3ee185c8b719b4f887cdd8336a0a13400ce606ab4a0d33bc8fa6b4fcdb53e2896d07f2568f6 languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-template-literals@npm:7.25.7" +"@babel/plugin-transform-template-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-template-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a3455303b6841cb536ac66d1a2d03c194b9f371519482d8d1e8edbd33bf5ca7cdd5db1586b2b0ea5f909ebf74a0eafacf0fb28d257e4905445282dcdccfa6139 + checksum: 10c0/5144da6036807bbd4e9d2a8b92ae67a759543929f34f4db9b463448a77298f4a40bf1e92e582db208fe08ee116224806a3bd0bed75d9da404fc2c0af9e6da540 languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.25.7" +"@babel/plugin-transform-typeof-symbol@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/ce1a0744a900b05de1372a70508c4148f17eb941c482da26eb369b9f0347570dce45470c8a86d907bc3a0443190344da1e18489ecfecb30388ab6178e8a9916b + checksum: 10c0/2b19fd88608589d9bc6b607ff17b06791d35c67ef3249f4659283454e6a9984241e3bd4c4eb72bb8b3d860a73223f3874558b861adb7314aa317c1c6a2f0cafb languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-typescript@npm:7.25.7" +"@babel/plugin-transform-typescript@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-typescript@npm:7.25.9" dependencies: - "@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" + "@babel/helper-annotate-as-pure": "npm:^7.25.9" + "@babel/helper-create-class-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.25.9" + "@babel/plugin-syntax-typescript": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5fa839b9560221698edff5e00b5cccc658c7875efaa7971c66d478f5b026770f12dd47b1be024463a44f9e29b4e14e8ddddbf4a2b324b0b94f58370dd5ae7195 + checksum: 10c0/c607ddb45f7e33cfcb928aad05cb1b18b1ecb564d2329d8f8e427f75192511aa821dee42d26871f1bdffbd883853e150ba81436664646c6e6b13063e65ce1475 languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.25.7" +"@babel/plugin-transform-unicode-escapes@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8b1f71fda0a832c6e26ba4c00f99e9033e6f9b36ced542a512921f4ad861a70e2fec2bd54a91a5ca2efa46aaa8c8893e4c602635c4ef172bd3ed6eef3178c70b + checksum: 10c0/615c84d7c53e1575d54ba9257e753e0b98c5de1e3225237d92f55226eaab8eb5bceb74df43f50f4aa162b0bbcc934ed11feafe2b60b8ec4934ce340fad4b8828 languageName: node linkType: hard -"@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" +"@babel/plugin-transform-unicode-property-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b4bfcf7529138d00671bf5cdfe606603d52cfe57ec1be837da57683f404fc0b0c171834a02515eb03379e5c806121866d097b90e31cb437d21d0ea59368ad82b + checksum: 10c0/1685836fc38af4344c3d2a9edbd46f7c7b28d369b63967d5b83f2f6849ec45b97223461cea3d14cc3f0be6ebb284938e637a5ca3955c0e79c873d62f593d615c languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.25.7" +"@babel/plugin-transform-unicode-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/73ae34c02ea8b7ac7e4efa690f8c226089c074e3fef658d2a630ad898a93550d84146ce05e073c271c8b2bbba61cbbfd5a2002a7ea940dcad3274e5b5dcb6bcf + checksum: 10c0/448004f978279e726af26acd54f63f9002c9e2582ecd70d1c5c4436f6de490fcd817afb60016d11c52f5ef17dbaac2590e8cc7bfaf4e91b58c452cf188c7920f languageName: node linkType: hard -"@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" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.25.7" - "@babel/helper-plugin-utils": "npm:^7.25.7" + "@babel/helper-create-regexp-features-plugin": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/39e45ae3db7adfc3457b1d6ba5608ffbace957ad019785967e5357a6639f261765bda12363f655d39265f5a2834af26327037751420191d0b73152ccc7ce3c35 + checksum: 10c0/56ee04fbe236b77cbcd6035cbf0be7566d1386b8349154ac33244c25f61170c47153a9423cd1d92855f7d6447b53a4a653d9e8fd1eaeeee14feb4b2baf59bd9f 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.7 - resolution: "@babel/preset-env@npm:7.25.7" + version: 7.26.0 + resolution: "@babel/preset-env@npm:7.26.0" dependencies: - "@babel/compat-data": "npm:^7.25.7" - "@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/compat-data": "npm:^7.26.0" + "@babel/helper-compilation-targets": "npm:^7.25.9" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.25.9" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.25.9" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.25.9" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.25.9" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.25.9" "@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.25.7" - "@babel/plugin-syntax-import-attributes": "npm:^7.25.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.26.0" + "@babel/plugin-syntax-import-attributes": "npm:^7.26.0" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" - "@babel/plugin-transform-arrow-functions": "npm:^7.25.7" - "@babel/plugin-transform-async-generator-functions": "npm:^7.25.7" - "@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.7" - "@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.7" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.25.7" - "@babel/plugin-transform-export-namespace-from": "npm:^7.25.7" - "@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.7" - "@babel/plugin-transform-literals": "npm:^7.25.7" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.25.7" - "@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.7" - "@babel/plugin-transform-numeric-separator": "npm:^7.25.7" - "@babel/plugin-transform-object-rest-spread": "npm:^7.25.7" - "@babel/plugin-transform-object-super": "npm:^7.25.7" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.25.7" - "@babel/plugin-transform-optional-chaining": "npm:^7.25.7" - "@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.7" - "@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/plugin-transform-arrow-functions": "npm:^7.25.9" + "@babel/plugin-transform-async-generator-functions": "npm:^7.25.9" + "@babel/plugin-transform-async-to-generator": "npm:^7.25.9" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.25.9" + "@babel/plugin-transform-block-scoping": "npm:^7.25.9" + "@babel/plugin-transform-class-properties": "npm:^7.25.9" + "@babel/plugin-transform-class-static-block": "npm:^7.26.0" + "@babel/plugin-transform-classes": "npm:^7.25.9" + "@babel/plugin-transform-computed-properties": "npm:^7.25.9" + "@babel/plugin-transform-destructuring": "npm:^7.25.9" + "@babel/plugin-transform-dotall-regex": "npm:^7.25.9" + "@babel/plugin-transform-duplicate-keys": "npm:^7.25.9" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.25.9" + "@babel/plugin-transform-dynamic-import": "npm:^7.25.9" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.25.9" + "@babel/plugin-transform-export-namespace-from": "npm:^7.25.9" + "@babel/plugin-transform-for-of": "npm:^7.25.9" + "@babel/plugin-transform-function-name": "npm:^7.25.9" + "@babel/plugin-transform-json-strings": "npm:^7.25.9" + "@babel/plugin-transform-literals": "npm:^7.25.9" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.25.9" + "@babel/plugin-transform-member-expression-literals": "npm:^7.25.9" + "@babel/plugin-transform-modules-amd": "npm:^7.25.9" + "@babel/plugin-transform-modules-commonjs": "npm:^7.25.9" + "@babel/plugin-transform-modules-systemjs": "npm:^7.25.9" + "@babel/plugin-transform-modules-umd": "npm:^7.25.9" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.25.9" + "@babel/plugin-transform-new-target": "npm:^7.25.9" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.25.9" + "@babel/plugin-transform-numeric-separator": "npm:^7.25.9" + "@babel/plugin-transform-object-rest-spread": "npm:^7.25.9" + "@babel/plugin-transform-object-super": "npm:^7.25.9" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.25.9" + "@babel/plugin-transform-optional-chaining": "npm:^7.25.9" + "@babel/plugin-transform-parameters": "npm:^7.25.9" + "@babel/plugin-transform-private-methods": "npm:^7.25.9" + "@babel/plugin-transform-private-property-in-object": "npm:^7.25.9" + "@babel/plugin-transform-property-literals": "npm:^7.25.9" + "@babel/plugin-transform-regenerator": "npm:^7.25.9" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.26.0" + "@babel/plugin-transform-reserved-words": "npm:^7.25.9" + "@babel/plugin-transform-shorthand-properties": "npm:^7.25.9" + "@babel/plugin-transform-spread": "npm:^7.25.9" + "@babel/plugin-transform-sticky-regex": "npm:^7.25.9" + "@babel/plugin-transform-template-literals": "npm:^7.25.9" + "@babel/plugin-transform-typeof-symbol": "npm:^7.25.9" + "@babel/plugin-transform-unicode-escapes": "npm:^7.25.9" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.25.9" + "@babel/plugin-transform-unicode-regex": "npm:^7.25.9" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.25.9" "@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" @@ -1423,7 +1354,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/bf704a06a69420250c1de2b126cd5c859a851002c2fb2cce0910cd85a8e6755b9b31577021e94feb7e1e53519923726349aaf07580923928791583db61438fb8 + checksum: 10c0/26e19dc407cfa1c5166be638b4c54239d084fe15d8d7e6306d8c6dc7bc1decc51070a8dcf28352c1a2feeefbe52a06d193a12e302327ad5f529583df75fb7a26 languageName: node linkType: hard @@ -1441,33 +1372,33 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.22.3": - version: 7.25.7 - resolution: "@babel/preset-react@npm:7.25.7" + version: 7.25.9 + resolution: "@babel/preset-react@npm:7.25.9" dependencies: - "@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" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" + "@babel/plugin-transform-react-display-name": "npm:^7.25.9" + "@babel/plugin-transform-react-jsx": "npm:^7.25.9" + "@babel/plugin-transform-react-jsx-development": "npm:^7.25.9" + "@babel/plugin-transform-react-pure-annotations": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b133b1a2f46c70a337d8b1ef442e09e3dbdaecb0d6bed8f1cb64dfddc31c16e248b017385ab909caeebd8462111c9c0e1c5409deb10f2be5cb5bcfdaa4d27718 + checksum: 10c0/c294b475ee741f01f63ea0d828862811c453fabc6023f01814ce983bc316388e9d73290164d2b1384c2684db9c330803a3d4d2170285b105dcbacd483329eb93 languageName: node linkType: hard "@babel/preset-typescript@npm:^7.21.5": - version: 7.25.7 - resolution: "@babel/preset-typescript@npm:7.25.7" + version: 7.26.0 + resolution: "@babel/preset-typescript@npm:7.26.0" dependencies: - "@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" + "@babel/helper-plugin-utils": "npm:^7.25.9" + "@babel/helper-validator-option": "npm:^7.25.9" + "@babel/plugin-syntax-jsx": "npm:^7.25.9" + "@babel/plugin-transform-modules-commonjs": "npm:^7.25.9" + "@babel/plugin-transform-typescript": "npm:^7.25.9" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8dc1258e3c5230bbe42ff9811f08924509238e6bd32fa0b7b0c0a6c5e1419512a8e1f733e1b114454d367b7c164beca2cf33acf2ed9e0d99be010c1c5cdbef0c + checksum: 10c0/20d86bc45d2bbfde2f84fc7d7b38746fa6481d4bde6643039ad4b1ff0b804c6d210ee43e6830effd8571f2ff43fa7ffd27369f42f2b3a2518bb92dc86c780c61 languageName: node linkType: hard @@ -1481,48 +1412,47 @@ __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.7 - resolution: "@babel/runtime@npm:7.25.7" + version: 7.26.0 + resolution: "@babel/runtime@npm:7.26.0" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/86b7829d2fc9343714a9afe92757cf96c4dc799006ca61d73cda62f4b9e29bfa1ce36794955bc6cb4c188f5b10db832c949339895e1bbe81a69022d9d578ce29 + checksum: 10c0/12c01357e0345f89f4f7e8c0e81921f2a3e3e101f06e8eaa18a382b517376520cd2fa8c237726eb094dab25532855df28a7baaf1c26342b52782f6936b07c287 languageName: node linkType: hard -"@babel/template@npm:^7.25.7, @babel/template@npm:^7.3.3": - version: 7.25.7 - resolution: "@babel/template@npm:7.25.7" +"@babel/template@npm:^7.25.9, @babel/template@npm:^7.3.3": + version: 7.25.9 + resolution: "@babel/template@npm:7.25.9" dependencies: - "@babel/code-frame": "npm:^7.25.7" - "@babel/parser": "npm:^7.25.7" - "@babel/types": "npm:^7.25.7" - checksum: 10c0/8ae9e36e4330ee83d4832531d1d9bec7dc2ef6a2a8afa1ef1229506fd60667abcb17f306d1c3d7e582251270597022990c845d5d69e7add70a5aea66720decb9 + "@babel/code-frame": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" + checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.25.7": - version: 7.25.7 - resolution: "@babel/traverse@npm:7.25.7" +"@babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/traverse@npm:7.25.9" dependencies: - "@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" + "@babel/code-frame": "npm:^7.25.9" + "@babel/generator": "npm:^7.25.9" + "@babel/parser": "npm:^7.25.9" + "@babel/template": "npm:^7.25.9" + "@babel/types": "npm:^7.25.9" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/75d73e52c507a7a7a4c7971d6bf4f8f26fdd094e0d3a0193d77edf6a5efa36fc3db91ec5cc48e8b94e6eb5d5ad21af0a1040e71309172851209415fd105efb1a + checksum: 10c0/e90be586a714da4adb80e6cb6a3c5cfcaa9b28148abdafb065e34cc109676fc3db22cf98cd2b2fff66ffb9b50c0ef882cab0f466b6844be0f6c637b82719bba1 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.25.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.25.7 - resolution: "@babel/types@npm:7.25.7" +"@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.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" dependencies: - "@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/e03e1e2e08600fa1e8eb90632ac9c253dd748176c8d670d85f85b0dc83a0573b26ae748a1cbcb81f401903a3d95f43c3f4f8d516a5ed779929db27de56289633 + "@babel/helper-string-parser": "npm:^7.25.9" + "@babel/helper-validator-identifier": "npm:^7.25.9" + checksum: 10c0/b694f41ad1597127e16024d766c33a641508aad037abd08d0d1f73af753e1119fa03b4a107d04b5f92cc19c095a594660547ae9bead1db2299212d644b0a5cb8 languageName: node linkType: hard @@ -1533,13 +1463,13 @@ __metadata: languageName: node linkType: hard -"@csstools/cascade-layer-name-parser@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/cascade-layer-name-parser@npm:2.0.2" +"@csstools/cascade-layer-name-parser@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/cascade-layer-name-parser@npm:2.0.4" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.2 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/2cc840445328400bb3e1e4186e6081e6519a23d9abde36a16c95892b6ad75155b3af3410d79fdda1c53a068384f970cabff4b5f5ba6867578168cbd3419016c8 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/774f2bcc96a576183853191bdfd31df15e22c51901ee01678ee47f1d1afcb4ab0e6d9a78e08f7383ac089c7e0b390013633f45ff1f1d577c9aefd252589bcced languageName: node linkType: hard @@ -1550,42 +1480,42 @@ __metadata: languageName: node linkType: hard -"@csstools/css-calc@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/css-calc@npm:2.0.2" +"@csstools/css-calc@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/css-calc@npm:2.0.4" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.2 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/b36e655b4abc8ea39b300725e33cd43b1875d759dd60bee8155bf7841065615a7f24cf53199382e30aa10bb137f64021043e4af7e11b7199b674a6e6cf3ccd01 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/ecb68fc9f8d930b861d5c9c5d4fc6eb43dabc619a4cd6c82dc18034ee746f907dba106fa6cdb909ac727fbfc9b1f7ceac1f356641542faeb2fab99c5fcd52a2e languageName: node linkType: hard -"@csstools/css-color-parser@npm:^3.0.3": - version: 3.0.3 - resolution: "@csstools/css-color-parser@npm:3.0.3" +"@csstools/css-color-parser@npm:^3.0.5": + version: 3.0.5 + resolution: "@csstools/css-color-parser@npm:3.0.5" dependencies: "@csstools/color-helpers": "npm:^5.0.1" - "@csstools/css-calc": "npm:^2.0.2" + "@csstools/css-calc": "npm:^2.0.4" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.2 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/02367ffc222254132c47f9cbc856f65fe0b81ee4a5e7381251b95c4064138b5ed99a5e5a79c0c8689f9e75e3d900f94773258a161a97f467c3f0420838c10e04 + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/535e2a38222ad7ee9e1143c3ef09ba07b2e70a4214bbdf7ca13398388b8d2db9ee295fe15d9d306342036e554d97dd235567a8c8ee03fea6825483f1c4dbbf7e languageName: node linkType: hard -"@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" +"@csstools/css-parser-algorithms@npm:^3.0.1, @csstools/css-parser-algorithms@npm:^3.0.4": + version: 3.0.4 + resolution: "@csstools/css-parser-algorithms@npm:3.0.4" peerDependencies: - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/246afbf518ee9eaa24ed7f083360eb66884f1172fd4f8c663bff8c6099de2a8abd1e2a31d5b6fe42e010277d238469d780cff62bc7fdc6a52e7a90626b8924dc + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/d411f07765e14eede17bccc6bd4f90ff303694df09aabfede3fd104b2dfacfd4fe3697cd25ddad14684c850328f3f9420ebfa9f78380892492974db24ae47dbd languageName: node linkType: hard -"@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 +"@csstools/css-tokenizer@npm:^3.0.1, @csstools/css-tokenizer@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/css-tokenizer@npm:3.0.3" + checksum: 10c0/c31bf410e1244b942e71798e37c54639d040cb59e0121b21712b40015fced2b0fb1ffe588434c5f8923c9cd0017cfc1c1c8f3921abc94c96edf471aac2eba5e5 languageName: node linkType: hard @@ -1599,82 +1529,82 @@ __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" +"@csstools/media-query-list-parser@npm:^4.0.2": + version: 4.0.2 + resolution: "@csstools/media-query-list-parser@npm:4.0.2" peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.2 - "@csstools/css-tokenizer": ^3.0.2 - checksum: 10c0/416417bcfd84c18a2df8dc77f31c87830e151dc20530fe7f0d8f13a0848b1a9090858abdf7792d82bf2edb41ddedb7b57b34eb78b68b5c10755ae02c019e496a + "@csstools/css-parser-algorithms": ^3.0.4 + "@csstools/css-tokenizer": ^3.0.3 + checksum: 10c0/5d008a70f5d4fd96224066a433f5cdefa76cfd78a74416a20d6d5b2bb1bc8282b140e8373015d807d4dadb91daf3deb73eb13f853ec4e0479d0cb92e80c6f20d 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" +"@csstools/postcss-cascade-layers@npm:^5.0.1": + version: 5.0.1 + resolution: "@csstools/postcss-cascade-layers@npm:5.0.1" dependencies: - "@csstools/selector-specificity": "npm:^4.0.0" - postcss-selector-parser: "npm:^6.1.0" + "@csstools/selector-specificity": "npm:^5.0.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/b608c69c12671682676598e451dcd79bfc6f5030a4e17b4d1bf9659e531f1daf03526be023f9aafdc952ecc87c87b04f379a763309e3eadb2140572cd4aa5b60 + checksum: 10c0/5cc3c6f220d9216f7ab16e716a20d6db845f127c917521e6236342bfa871accd63eb662a04c1e24a28e396412dcb47b1c4abccc490b88e4010cd704d14a702f1 languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-color-function@npm:4.0.3" +"@csstools/postcss-color-function@npm:^4.0.5": + version: 4.0.5 + resolution: "@csstools/postcss-color-function@npm:4.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/c994660ca0e2652755d9ad181c8cb46a07220c972086c97c843fa9bacf690be10c642770f898aeec4acc47c2b718dfc7372107285a678361f34d84d9e9c11e0c + checksum: 10c0/b47cc4567445eb12dd3e67a4298470d62a449a4d754fd4dd32eb78b23615ba6bd1fe8dacccc6c95087ce8749a6552bace8de0b9b6eee0c9a7b7202a0bcb8fcac languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^3.0.3": - version: 3.0.3 - resolution: "@csstools/postcss-color-mix-function@npm:3.0.3" +"@csstools/postcss-color-mix-function@npm:^3.0.5": + version: 3.0.5 + resolution: "@csstools/postcss-color-mix-function@npm:3.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/4ba358eb9030fc485bfe2922d897eeb712725762cc399eaba60ba665c84dc3e56a4d5a52dfb320093c0b217d32fedb9b5197fa45738cade53d9afcbefdadf04f + checksum: 10c0/a17d20dcc42d2c1ccd7a5ceb8d1413133ae9461bf973a9aad997a5782bf4cbbd847aef06accc20fa391ac6fbd44a1003e18c30a621d7c77052d4256fe39619aa languageName: node linkType: hard -"@csstools/postcss-content-alt-text@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/postcss-content-alt-text@npm:2.0.2" +"@csstools/postcss-content-alt-text@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/postcss-content-alt-text@npm:2.0.4" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/e52d40f6567b9b23b32a6c40f9b2a74d57f99a9921b4cae015f51f72453474236c760bb13120682f8815698a615e0ad7bed22314c29dca89c34b5480d83a7a6d + checksum: 10c0/84caccedd8a519df434babd58b14104c5a92cd326057ce509bdbaa2a4bb3130afb1c1456caf30235ba14da52d1628a5411ea4f5d2fb558d603d234f795538017 languageName: node linkType: hard -"@csstools/postcss-exponential-functions@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/postcss-exponential-functions@npm:2.0.2" +"@csstools/postcss-exponential-functions@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/postcss-exponential-functions@npm:2.0.4" dependencies: - "@csstools/css-calc": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/034ff89089872f63a6b00bda670c5ff11361babd221ed3e441dde969a718059e5d44ab0ed331868f137bb205331b808ecbcc4cb641d5c945238ebca28aa3ed59 + checksum: 10c0/b174faa8782b7b3f3a9636412f90963740ff033c6506acf662f002fa07f59b370eb23937dbe3f1a05d7df277373f662d6970237d34ae938cf282a0b8dbde9a47 languageName: node linkType: hard @@ -1690,46 +1620,46 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/postcss-gamut-mapping@npm:2.0.3" +"@csstools/postcss-gamut-mapping@npm:^2.0.5": + version: 2.0.5 + resolution: "@csstools/postcss-gamut-mapping@npm:2.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/21f5708f63e9c3b7603f8b72b5f288e0a021e9710a6abf4aaa713ff4d04bae057d1861e1f28d7670ea39ba463ac04f1507876d4a11178934e7cc7a1c6a780084 + checksum: 10c0/a9d7365bed5c323dddad06d53c137ef3508870e541c6275dbdf3a73a50d44437830c22fa62c510d9316441d1e9f3b5552730778d1b73d083422245673bd00dac languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^5.0.3": - version: 5.0.3 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.3" +"@csstools/postcss-gradients-interpolation-method@npm:^5.0.5": + version: 5.0.5 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/062d27148438309c940a1973bfc7d42a06caa9397bf2382c7a61979f5be3d6f3fae1bc8ddf94d2dd8e6c807e0530a9e76179510266aaddc439677bf79447a765 + checksum: 10c0/0ef258478270005ab3a879132dc6dbf2bf80788c79861515c826607953c551df1c2ef7005ba9592c31c6dad332d12ee247928a9fdd1569a51927a18a75dcc865 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-hwb-function@npm:4.0.3" +"@csstools/postcss-hwb-function@npm:^4.0.5": + version: 4.0.5 + resolution: "@csstools/postcss-hwb-function@npm:4.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/faf2bfbafeec765391e37c7a5cbc7b4647d9ab1ffa51e922c7dfffa545c3d436d15604dfdfb9d7684e760042e62bb42e0243dd4ebd8c3c14694a9f7be4e57b30 + checksum: 10c0/9ce0a66bf288c9ec7f1fc28323d56ec54d38a30cb2ab722d1afbd46ec070cc5e61121bacb503803cb00293fc5ed117269969ac21071d7f4ce94b385c96168445 languageName: node linkType: hard @@ -1755,29 +1685,29 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-is-pseudo-class@npm:^5.0.0": - version: 5.0.0 - resolution: "@csstools/postcss-is-pseudo-class@npm:5.0.0" +"@csstools/postcss-is-pseudo-class@npm:^5.0.1": + version: 5.0.1 + resolution: "@csstools/postcss-is-pseudo-class@npm:5.0.1" dependencies: - "@csstools/selector-specificity": "npm:^4.0.0" - postcss-selector-parser: "npm:^6.1.0" + "@csstools/selector-specificity": "npm:^5.0.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/738eb84728b24bfe19ca06ccf6ff773a423552df2f31c87704ce79da4abfd2ccf2a45d5d6d3e11e71e42cc3d92eb35a856209b9cd6116c879acf15ac75454683 + checksum: 10c0/3aaab18ebb2dcf5565efa79813eaa987d40de1e086765358524392a09631c68ad1ee952e6aff8f42513b2c18ab84891787e065fe287f696128498fc641520b6c languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^2.0.5": - version: 2.0.5 - resolution: "@csstools/postcss-light-dark-function@npm:2.0.5" +"@csstools/postcss-light-dark-function@npm:^2.0.7": + version: 2.0.7 + resolution: "@csstools/postcss-light-dark-function@npm:2.0.7" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/80635ee312d2a8f42aa5ce6792f1dc4a71199c384c66a3270d37e998d96db55beaa6836d689cda3b7e4828227960582fae04659ba5e4e0f64fd4543cbf15c6ab + checksum: 10c0/c116bfd2d3f4d0caabdedf8954c2a25908ffb29f9bbe2c57d44a2974277c7e46ee79862eea848385dc040275d343f2330350394a2095ec30f0aa17f72e2f4e39 languageName: node linkType: hard @@ -1819,42 +1749,42 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-logical-viewport-units@npm:^3.0.2": - version: 3.0.2 - resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.2" +"@csstools/postcss-logical-viewport-units@npm:^3.0.3": + version: 3.0.3 + resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.3" dependencies: - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/31f525e774bc053f545a159eb53bb21465ea2930118e87c40207ad90fa97d3151e6de83efd02f84803fb0e93ed4a4b42a3904b734423410e73ac4c6ce9666ab4 + checksum: 10c0/8ec746598d7ce8697c3dafd83cb3a319a90079ad755dd78e3ec92f4ba9ad849c4cdaba33b16e9dcbac1e9489b3d7c48262030110c20ce1d88cdacbe9f5987cec languageName: node linkType: hard -"@csstools/postcss-media-minmax@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/postcss-media-minmax@npm:2.0.2" +"@csstools/postcss-media-minmax@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/postcss-media-minmax@npm:2.0.4" dependencies: - "@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" + "@csstools/css-calc": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + "@csstools/media-query-list-parser": "npm:^4.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/83cf10742884fca3baa7ae26e2cb34123ce5a022622390566c139b4587ea8583fab00acbb85545786b36398e2201d2a94301e0fae805e55f375f1b5c38f67ce8 + checksum: 10c0/f9fe1e99b83a0724250f9426335da6f13bfbc28be6d10ebfafbf037766fc5245240ec33be7e68c9c5b60c013fbc2fa0be96fbed0d41383c919ee9e6f1b8225ce languageName: node linkType: hard -"@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" +"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.4": + version: 3.0.4 + resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.4" dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" - "@csstools/media-query-list-parser": "npm:^4.0.0" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + "@csstools/media-query-list-parser": "npm:^4.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/3ac4073d2e958bfb24ae45f673070dd805f0fcf07bc8d00a9a98f596d1096e7be282c8d8e87df3abde90f33fcbe2c7705e972b8c1a58e43ec44729f470b76096 + checksum: 10c0/27dc9419b0f4315774647588f599348e7cc593984f59b414c51c910066501fd087cbe232deb762907c18bd21dd4184e7b6e0e0b730e5c72341ab9cc696c75739 languageName: node linkType: hard @@ -1881,18 +1811,18 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-oklab-function@npm:4.0.3" +"@csstools/postcss-oklab-function@npm:^4.0.5": + version: 4.0.5 + resolution: "@csstools/postcss-oklab-function@npm:4.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/650bcb4f664308972588a8f789f806d63c4069e2e008cfc3b5c80bf9df992c62972dce279b8f434c7f78823e97095942ee4f0e37bc549258887213e72acb7ef8 + checksum: 10c0/a49e2ee60066f7da18316c7c80e5b2ced286ec962052f83c01f1952a1c5fe5b65ba9803a04698260125270a1dd47416f0b287a8f42e591f0d88c9a660ae844ce languageName: node linkType: hard @@ -1907,42 +1837,42 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^3.0.3": - version: 3.0.3 - resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.3" +"@csstools/postcss-relative-color-syntax@npm:^3.0.5": + version: 3.0.5 + resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/c241fe6b725d775f6d2085be1dff3868d189b176fa91ab1eb1133e30e30c8151bded4e50d17a845edd0bdd0a7adf9e8883cb2634fea3394872591fe9ad2a7e86 + checksum: 10c0/505da97e7b219095a9fb6fa0ad6c6a1358ce1f5debada00564e635e1aa11d034c588be9ce2f76263172a8d1bd07d90647fde826f4565de22dcfc0a76beb68ff1 languageName: node linkType: hard -"@csstools/postcss-scope-pseudo-class@npm:^4.0.0": - version: 4.0.0 - resolution: "@csstools/postcss-scope-pseudo-class@npm:4.0.0" +"@csstools/postcss-scope-pseudo-class@npm:^4.0.1": + version: 4.0.1 + resolution: "@csstools/postcss-scope-pseudo-class@npm:4.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/a6f562df1417c6f257c0fec95babf4cea99a25622573a2dbcfb416e2fcb8e1e53561127f5e7277d19fcb2a4603bdbc64dd6a4c416429623503c604050c99229a + checksum: 10c0/6a0ca50fae655f4498200d1ce298ca794c85fbe2e3fd5d6419843254f055df5007a973e09b5f1e78e376c02b54278e411516c8d824300c68b265d3e5b311d7ee languageName: node linkType: hard -"@csstools/postcss-stepped-value-functions@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.2" +"@csstools/postcss-stepped-value-functions@npm:^4.0.4": + version: 4.0.4 + resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.4" dependencies: - "@csstools/css-calc": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/444a27d725bc7a8e1554469e8ac69e248ff525b728fbe058523b0f1aefcff80ca707f543d21fead0a22d51603b1669190fb01f0f2dcd599a01768a37e0d62bc3 + checksum: 10c0/c8413a855a5ee9ad5b800263545d24d1bbd815f5ae0693c7dfd10c5f5b47bae5a9d985efdb2c46b03194ed3cae39f3d82c3ccfde502dee0b35d620fa539906be languageName: node linkType: hard @@ -1958,16 +1888,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-trigonometric-functions@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.2" +"@csstools/postcss-trigonometric-functions@npm:^4.0.4": + version: 4.0.4 + resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.4" dependencies: - "@csstools/css-calc": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-calc": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" peerDependencies: postcss: ^8.4 - checksum: 10c0/eaecb2ea891162e4fcbbccf4f660c99e9e59f21937b70fe6aec3b51441eff2a12c1a2dc13fff426722629a7929919fd866311eaa68d74ee9d1f5387a23502fe2 + checksum: 10c0/344c07961d24894f315faebf43c0128167fb2e33964c70d0d39d99a051c045678511d7378959105d672c5286a5360fde28fe390cdebfe823f3949e3cd1d50c4e languageName: node linkType: hard @@ -1980,12 +1910,12 @@ __metadata: languageName: node linkType: hard -"@csstools/selector-resolve-nested@npm:^2.0.0": - version: 2.0.0 - resolution: "@csstools/selector-resolve-nested@npm:2.0.0" +"@csstools/selector-resolve-nested@npm:^3.0.0": + version: 3.0.0 + resolution: "@csstools/selector-resolve-nested@npm:3.0.0" peerDependencies: - postcss-selector-parser: ^6.1.0 - checksum: 10c0/10516fd1db5e0a3963063caa57d24eeb1d1f69fcb63f0b5aec5d7a44f8b36ff07b1eded3012e8a9b92fc1f484e1a5a9def0cf57d788aa7f944ee79877837cc77 + postcss-selector-parser: ^7.0.0 + checksum: 10c0/2b01c36b3fa81388d5bddd8db962766465d76b021a815c8bb5a48c3a42c530154cc155fc496707ade627dbba6745eb8ecd9fa840c1972133c0f7d8811e0a959d languageName: node linkType: hard @@ -1998,6 +1928,15 @@ __metadata: languageName: node linkType: hard +"@csstools/selector-specificity@npm:^5.0.0": + version: 5.0.0 + resolution: "@csstools/selector-specificity@npm:5.0.0" + peerDependencies: + postcss-selector-parser: ^7.0.0 + checksum: 10c0/186b444cabcdcdeb553bfe021f80c58bfe9ef38dcc444f2b1f34a5aab9be063ab4e753022b2d5792049c041c28cfbb78e4b707ec398459300e402030d35c07eb + languageName: node + linkType: hard + "@csstools/utilities@npm:^2.0.0": version: 2.0.0 resolution: "@csstools/utilities@npm:2.0.0" @@ -2187,14 +2126,14 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.48.0": - version: 0.48.0 - resolution: "@es-joy/jsdoccomment@npm:0.48.0" +"@es-joy/jsdoccomment@npm:~0.49.0": + version: 0.49.0 + resolution: "@es-joy/jsdoccomment@npm:0.49.0" dependencies: comment-parser: "npm:1.4.1" esquery: "npm:^1.6.0" jsdoc-type-pratt-parser: "npm:~4.1.0" - checksum: 10c0/8d87c7c0426fade009c30ab429d4ede53fd253d40b55079c02bdacdaa4c0fe904aaea5e3084cd98052f2bed6b3030c381d84f4a3251b343a71fee6f681a08bee + checksum: 10c0/16717507d557d37e7b59456fedeefbe0a3bc93aa2d9c043d5db91e24e076509b6fcb10ee6fd1dafcb0c5bbe50ae329b45de5b83541cb5994a98c9e862a45641e languageName: node linkType: hard @@ -2233,10 +2172,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.57.0": - version: 8.57.0 - resolution: "@eslint/js@npm:8.57.0" - checksum: 10c0/9a518bb8625ba3350613903a6d8c622352ab0c6557a59fe6ff6178bf882bf57123f9d92aa826ee8ac3ee74b9c6203fe630e9ee00efb03d753962dcf65ee4bd94 +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 10c0/b489c474a3b5b54381c62e82b3f7f65f4b8a5eaaed126546520bf2fede5532a8ed53212919fed1e9048dcf7f37167c8561d58d0ba4492a4244004e7793805223 languageName: node linkType: hard @@ -2267,8 +2206,8 @@ __metadata: linkType: hard "@formatjs/cli@npm:^6.1.1": - version: 6.2.15 - resolution: "@formatjs/cli@npm:6.2.15" + version: 6.3.6 + resolution: "@formatjs/cli@npm:6.3.6" peerDependencies: "@glimmer/env": ^0.1.7 "@glimmer/reference": ^0.91.1 || ^0.92.0 @@ -2297,129 +2236,200 @@ __metadata: optional: true bin: formatjs: bin/formatjs - checksum: 10c0/e947aa7f3994251392fe15673752a8d8e3c8a30733bb49de5e617d45a327a3e1d16419e2d6b01f7ef2cbe86e2946024342d5b3301e6a8f17de3de9e2e7aedb29 + checksum: 10c0/55f10699644c8b879d7fcf38660e7d9b0642c5f40ca59076c25ba190f350b48d7edb7f3d8481cc6139d3a708ee73f877c2c0a7d1865f15e80a73667270c9b7e3 languageName: node linkType: hard -"@formatjs/ecma402-abstract@npm:2.0.0": - version: 2.0.0 - resolution: "@formatjs/ecma402-abstract@npm:2.0.0" - dependencies: - "@formatjs/intl-localematcher": "npm:0.5.4" - tslib: "npm:^2.4.0" - checksum: 10c0/94cba291aeadffa3ca416087c2c2352c8a741bb4dcb7f47f15c247b1f043ffcef1af5b20a1b7578fbba9e704fc5f1c079923f3537a273d50162be62f8037625c - 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/icu-messageformat-parser@npm:2.7.8": - version: 2.7.8 - resolution: "@formatjs/icu-messageformat-parser@npm:2.7.8" +"@formatjs/ecma402-abstract@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/ecma402-abstract@npm:2.2.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/icu-skeleton-parser": "npm:1.8.2" - tslib: "npm:^2.4.0" - checksum: 10c0/a3b759a825fb22ffd7b906f6a07b1a079bbc34f72c745de2c2514e439c4bb75bc1a9442eba1bac7ff3ea3010e12076374cd755ad12116b1d066cc90da5fbcbc9 + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" + tslib: "npm:2" + checksum: 10c0/611d12bf320fc5c5b85cb2b57e3dcebe8490a51c6a0459c857c7a3560656cd2bdba5b117e9dd7cf174f5aa120c11eaad7a65a6783637b816caa59a1bc5c727f6 languageName: node linkType: hard -"@formatjs/icu-skeleton-parser@npm:1.8.2": - version: 1.8.2 - resolution: "@formatjs/icu-skeleton-parser@npm:1.8.2" +"@formatjs/fast-memoize@npm:2.2.1": + version: 2.2.1 + resolution: "@formatjs/fast-memoize@npm:2.2.1" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - tslib: "npm:^2.4.0" - checksum: 10c0/9b15013acc47b8d560b52942e3dab2abaaa9c5a4410bbd1d490a4b22bf5ca36fdd88b71f241d05479bddf856d0d1d57b7ecc9e79738497ac518616aa6d4d0015 + tslib: "npm:^2.7.0" + checksum: 10c0/cb8cbf1aba907d395d1fe405f67a8da26686b2fc26eefde7541d49d748d2d9b939f2bc428b7d40d2c31366a6ce42cf16724c966965701186986c5882fdba3c8b languageName: node linkType: hard -"@formatjs/intl-displaynames@npm:6.6.8": - version: 6.6.8 - resolution: "@formatjs/intl-displaynames@npm:6.6.8" +"@formatjs/fast-memoize@npm:2.2.3": + version: 2.2.3 + resolution: "@formatjs/fast-memoize@npm:2.2.3" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/intl-localematcher": "npm:0.5.4" - tslib: "npm:^2.4.0" - checksum: 10c0/1a03e7644022741c1bcf10fcd07da88c434416a13603ace693a038114010463307b4130d3a3f53ad5665bd27fca9a6b19ac8e5bf58e17598b1ea84db173fdfbb + tslib: "npm:2" + checksum: 10c0/f1004c3b280de7e362bd37c5f48ff34c2ba1d6271d4a7b695fed561d1201a3379397824d8bffbf15fecee344d1e70398393bbb04297f242692310a305f12e75b languageName: node linkType: hard -"@formatjs/intl-listformat@npm:7.5.7": - version: 7.5.7 - resolution: "@formatjs/intl-listformat@npm:7.5.7" +"@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.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/icu-skeleton-parser": "npm:1.8.4" + tslib: "npm:^2.7.0" + checksum: 10c0/7f2b9bb31c64d2b45584a77e2e6a7c4185f247eea22c0d8e2257ac95feff36894a0936d31778d17874cd249c39058fcb894c27e13a6cadb056996e7232957655 languageName: node linkType: hard -"@formatjs/intl-localematcher@npm:0.5.4": - version: 0.5.4 - resolution: "@formatjs/intl-localematcher@npm:0.5.4" +"@formatjs/icu-messageformat-parser@npm:2.9.3": + version: 2.9.3 + resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3" dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/c9ff5d34ca8b6fe59f8f303a3cc31a92d343e095a6987e273e5cc23f0fe99feb557a392a05da95931c7d24106acb6988e588d00ddd05b0934005aafd7fdbafe6 + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/icu-skeleton-parser": "npm:1.8.7" + tslib: "npm:2" + checksum: 10c0/519b59f7b4cf90681315c5382f7fcd105eb1974486f0d62d9227b6d0498895114ccc818792c208baae1ef79571d93b0edb9914c676e5ab76924dddb7fd6c28a0 + languageName: node + linkType: hard + +"@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.2.0" + tslib: "npm:^2.7.0" + checksum: 10c0/a6cd90e89b994e6fa2b66f83a80250d17fdddaeb755cd1f38be1d51a737a6f8a9b123912943d3dcad278833e3a04683a9081b187300f1a481791527954e63e82 + languageName: node + linkType: hard + +"@formatjs/icu-skeleton-parser@npm:1.8.7": + version: 1.8.7 + resolution: "@formatjs/icu-skeleton-parser@npm:1.8.7" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.3" + tslib: "npm:2" + checksum: 10c0/e29eb4151580f2d324e6591509dc4543e2326266fc209a08580c94d502acab14acc3560d98b3aaf9ffbd5ff8e2683601ff08c65b32886f22da015c31ca35c5d0 + languageName: node + linkType: hard + +"@formatjs/intl-displaynames@npm:6.8.3": + version: 6.8.3 + resolution: "@formatjs/intl-displaynames@npm:6.8.3" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" + tslib: "npm:2" + checksum: 10c0/54d3ecaabc45dc8494be4cd9633bbf5eb0bc40c5f62ed5e5073aa5b214c4a9a9620d61d1c8a6f0074618474fd9c2ccc42904605078d2f6341c242bf43627bb3a + languageName: node + linkType: hard + +"@formatjs/intl-listformat@npm:7.7.3": + version: 7.7.3 + resolution: "@formatjs/intl-listformat@npm:7.7.3" + dependencies: + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/intl-localematcher": "npm:0.5.7" + tslib: "npm:2" + checksum: 10c0/2683513e86cc7885528f23237079e3ab9e3a8bc7111aa10d4c685dcbe368ef07039573115df240112fb20f2ec0b70c8ea189ea3b79cbfed7e3dc46024a4667ff + 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-localematcher@npm:0.5.7": + version: 0.5.7 + resolution: "@formatjs/intl-localematcher@npm:0.5.7" + dependencies: + tslib: "npm:2" + checksum: 10c0/1ae374ca146a0d7457794926eed808c99971628e594f704a42ae2540b1f38928b26cbf942a7bbcc2796cc9fe8d9d7a603ac422bd9b89b714d2f91b506da40792 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.3.3 + resolution: "@formatjs/intl-pluralrules@npm:5.3.3" 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.3" + "@formatjs/intl-localematcher": "npm:0.5.7" + tslib: "npm:2" + checksum: 10c0/003d33af6f5d902517f230b7038e39b8336da3a84500fe5f4278fa5cac0c9a1b746de484f1c2bb2315026fd771491eafdc0aa59a809bb25189b63093efb8400d languageName: node linkType: hard -"@formatjs/intl@npm:2.10.5": - version: 2.10.5 - resolution: "@formatjs/intl@npm:2.10.5" +"@formatjs/intl@npm:2.10.13": + version: 2.10.13 + resolution: "@formatjs/intl@npm:2.10.13" 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.3" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@formatjs/intl-displaynames": "npm:6.8.3" + "@formatjs/intl-listformat": "npm:7.7.3" + intl-messageformat: "npm:10.7.5" + tslib: "npm:2" peerDependencies: typescript: ^4.7 || 5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/d00ef00e41200947ed22895b73a0863283de4762ec238b4a81e2252e642e30a309cd9c73174e4917b6c675ab6f148eda5a4e3345c3caeef64e090fc8374d27c4 + checksum: 10c0/14edcc45addc181c7a45845bc34cec5c73bb5544dcf8ed455eca916bbd3a5023c7204a8e8e289060545b85006933c6f297c33c4f04a8a4cb3890aa7baae5bfbf languageName: node linkType: hard -"@formatjs/ts-transformer@npm:3.13.14": - version: 3.13.14 - resolution: "@formatjs/ts-transformer@npm:3.13.14" +"@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.8" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" "@types/json-stable-stringify": "npm:^1.0.32" - "@types/node": "npm:14 || 16 || 17" + "@types/node": "npm:14 || 16 || 17 || 18" chalk: "npm:^4.0.0" json-stable-stringify: "npm:^1.0.1" - tslib: "npm:^2.4.0" + tslib: "npm:^2.7.0" typescript: "npm:5" peerDependencies: ts-jest: ">=27" peerDependenciesMeta: ts-jest: optional: true - checksum: 10c0/38450cfce3ec5132f3548c1e9ab098909ca8d2db2b8b6b4b5bb87aa59a4ca1a19bbf6d339ace39bcc931fa80d9946b4c7cf039c9574069b317ae015cd6963bd3 + checksum: 10c0/de03e8bc8c730f2e122970d5843762e0c5183181ba58c9759db2f1ed45fcbfbb8046dbb3318f906574f89026481b9205f5bd6fbf3f410a5e5e1754f575baa489 + languageName: node + linkType: hard + +"@formatjs/ts-transformer@npm:3.13.22": + version: 3.13.22 + resolution: "@formatjs/ts-transformer@npm:3.13.22" + dependencies: + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@types/json-stable-stringify": "npm:1" + "@types/node": "npm:14 || 16 || 17 || 18 || 20 || 22" + chalk: "npm:4" + json-stable-stringify: "npm:1" + tslib: "npm:2" + typescript: "npm:5" + peerDependencies: + ts-jest: ">=27" + peerDependenciesMeta: + ts-jest: + optional: true + checksum: 10c0/42503292248bcae728181fdf68e79eac4169c18064953beb9245097d2c58e5434ae7a7978e6ce2829dfd6eb4b4155f78fecef70ac6820626a338f231c66f60cb languageName: node linkType: hard @@ -2446,14 +2456,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.14": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.2" + "@humanwhocodes/object-schema": "npm:^2.0.3" debug: "npm:^4.3.1" minimatch: "npm:^3.0.5" - checksum: 10c0/66f725b4ee5fdd8322c737cb5013e19fac72d4d69c8bf4b7feb192fcb83442b035b92186f8e9497c220e58b2d51a080f28a73f7899bc1ab288c3be172c467541 + checksum: 10c0/205c99e756b759f92e1f44a3dc6292b37db199beacba8f26c2165d4051fe73a4ae52fdcfd08ffa93e7e5cb63da7c88648f0e84e197d154bbbbe137b2e0dd332e languageName: node linkType: hard @@ -2464,10 +2474,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 10c0/6fd83dc320231d71c4541d0244051df61f301817e9f9da9fd4cb7e44ec8aacbde5958c1665b0c419401ab935114fdf532a6ad5d4e7294b1af2f347dd91a6983f +"@humanwhocodes/object-schema@npm:^2.0.3": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 10c0/80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c languageName: node linkType: hard @@ -2813,7 +2823,7 @@ __metadata: "@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.402" "@reduxjs/toolkit": "npm:^2.0.1" "@svgr/webpack": "npm:^5.5.0" "@testing-library/dom": "npm:^10.2.0" @@ -2875,13 +2885,13 @@ __metadata: eslint: "npm:^8.41.0" eslint-define-config: "npm:^2.0.0" eslint-import-resolver-typescript: "npm:^3.5.5" - eslint-plugin-formatjs: "npm:^4.10.1" + eslint-plugin-formatjs: "npm:^5.0.0" eslint-plugin-import: "npm:~2.30.0" eslint-plugin-jsdoc: "npm:^50.0.0" eslint-plugin-jsx-a11y: "npm:~6.10.0" eslint-plugin-promise: "npm:~7.1.0" eslint-plugin-react: "npm:^7.33.2" - eslint-plugin-react-hooks: "npm:^4.6.0" + eslint-plugin-react-hooks: "npm:^5.0.0" exif-js: "npm:^2.3.0" favico.js: "npm:^0.3.10" file-loader: "npm:^6.2.0" @@ -3115,16 +3125,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.402": + version: 7.1.402 + resolution: "@rails/ujs@npm:7.1.402" + checksum: 10c0/ccab74b8013ed8a8ab8d7497d0fa510a6ec079725b5fcf679936d80c342940e462b60243ad2cb98128f29db5708a094e319767e8f33a18eb63ceb745de63d1e0 languageName: node linkType: hard "@reduxjs/toolkit@npm:^2.0.1": - version: 2.2.8 - resolution: "@reduxjs/toolkit@npm:2.2.8" + version: 2.3.0 + resolution: "@reduxjs/toolkit@npm:2.3.0" dependencies: immer: "npm:^10.0.3" redux: "npm:^5.0.1" @@ -3138,7 +3148,7 @@ __metadata: optional: true react-redux: optional: true - checksum: 10c0/bf1356d71bfb82e5a181692c79c19b7bc19355260a9966f6562604c995f0cd0ce1154177ccd14095e8b319e73f64cfe86a4e46a83d24edba7876d4ae71fd5ae0 + checksum: 10c0/414e90b706331385a2122fc79e33f90c59a9caf9a59419f1bfd7f5e594bc8e4987902fd1bccbc53eb96d22c65ec2981ff5581f3d2df3ecd381a630f391edfc3e languageName: node linkType: hard @@ -3438,8 +3448,8 @@ __metadata: linkType: hard "@testing-library/jest-dom@npm:^6.0.0": - version: 6.5.0 - resolution: "@testing-library/jest-dom@npm:6.5.0" + version: 6.6.3 + resolution: "@testing-library/jest-dom@npm:6.6.3" dependencies: "@adobe/css-tools": "npm:^4.4.0" aria-query: "npm:^5.0.0" @@ -3448,7 +3458,7 @@ __metadata: dom-accessibility-api: "npm:^0.6.3" lodash: "npm:^4.17.21" redent: "npm:^3.0.0" - checksum: 10c0/fd5936a547f04608d8de15a7de3ae26516f21023f8f45169b10c8c8847015fd20ec259b7309f08aa1031bcbc37c6e5e6f532d1bb85ef8f91bad654193ec66a4c + checksum: 10c0/5566b6c0b7b0709bc244aec3aa3dc9e5f4663e8fb2b99d8cd456fc07279e59db6076cbf798f9d3099a98fca7ef4cd50e4e1f4c4dec5a60a8fad8d24a638a5bf6 languageName: node linkType: hard @@ -3493,7 +3503,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: @@ -3515,12 +3525,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 @@ -3534,12 +3544,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 @@ -3587,13 +3597,13 @@ __metadata: languageName: node linkType: hard -"@types/eslint@npm:7 || 8": - version: 8.56.10 - resolution: "@types/eslint@npm:8.56.10" +"@types/eslint@npm:9": + version: 9.6.1 + resolution: "@types/eslint@npm:9.6.1" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 10c0/674349d6c342c3864d70f4d5a9965f96fb253801532752c8c500ad6a1c2e8b219e01ccff5dc8791dcb58b5483012c495708bb9f3ff929f5c9322b3da126c15d3 + checksum: 10c0/69ba24fee600d1e4c5abe0df086c1a4d798abf13792d8cfab912d76817fe1a894359a1518557d21237fbaf6eda93c5ab9309143dee4c59ef54336d1b3570420e languageName: node linkType: hard @@ -3661,7 +3671,7 @@ __metadata: languageName: node linkType: hard -"@types/hoist-non-react-statics@npm:^3.3.1": +"@types/hoist-non-react-statics@npm:3, @types/hoist-non-react-statics@npm:^3.3.1": version: 3.3.5 resolution: "@types/hoist-non-react-statics@npm:3.3.5" dependencies: @@ -3720,12 +3730,12 @@ __metadata: linkType: hard "@types/jest@npm:^29.5.2": - version: 29.5.13 - resolution: "@types/jest@npm:29.5.13" + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" dependencies: expect: "npm:^29.0.0" pretty-format: "npm:^29.0.0" - checksum: 10c0/9c31af0b155387b9860908830de63c6b79011d7c87c8b61b39da124e26e55423dd51b006749aafe4f0ef3a065016619a1f93ef4b055157d43727f448e67824b7 + checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed languageName: node linkType: hard @@ -3747,17 +3757,17 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db languageName: node linkType: hard -"@types/json-stable-stringify@npm:^1.0.32": - version: 1.0.35 - resolution: "@types/json-stable-stringify@npm:1.0.35" - checksum: 10c0/67b50a86478f932c932ba21515b80700a8844d55e0656b3abe2c32c41c1c405c70fcd10b30ff8f38d1869871af2deae63ffdea54ce72cc2ee92e94a9d1cf2b6f +"@types/json-stable-stringify@npm:1, @types/json-stable-stringify@npm:^1.0.32": + version: 1.1.0 + resolution: "@types/json-stable-stringify@npm:1.1.0" + checksum: 10c0/8f69944701510243cd3a83aa44363a8a4d366f11a659b258f69fb3ad0f94ab1e2533206a2c929ac7fd18784d201b663b3f02a45934f545c926f051d8cb4df095 languageName: node linkType: hard @@ -3769,9 +3779,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.17.9 - resolution: "@types/lodash@npm:4.17.9" - checksum: 10c0/54de935e835508b5f835a5dfaedd2b9a299685a21d11e9c5cd2dde57331d03bc2f98b71d2424ca8460f447ecd55a673e45ccdb70e58f9f72745710f6b91abc60 + version: 4.17.13 + resolution: "@types/lodash@npm:4.17.13" + checksum: 10c0/c3d0b7efe7933ac0369b99f2f7bff9240d960680fdb74b41ed4bd1b3ca60cca1e31fe4046d9abbde778f941a41bc2a75eb629abf8659fa6c27b66efbbb0802a9 languageName: node linkType: hard @@ -3796,19 +3806,21 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 20.8.10 - resolution: "@types/node@npm:20.8.10" +"@types/node@npm:*, @types/node@npm:14 || 16 || 17 || 18 || 20 || 22": + version: 22.8.6 + resolution: "@types/node@npm:22.8.6" dependencies: - undici-types: "npm:~5.26.4" - checksum: 10c0/caaa3ae9294f1bfdacb029a916c64af63cbcea613a52f53ea86f93c91779859af177b2b68113ef835194519f5e76cadda08559929b68297f1a8a568c207f9f66 + undici-types: "npm:~6.19.8" + checksum: 10c0/d3a11f2549234a91a4c5d0ff35ab4bdcb7ba34db4d3f1d189be39b8bd41c19aac98d117150a95a9c5a9d45b1014135477ea240b2b8317c86ae3d3cf1c3b3f8f4 languageName: node linkType: hard -"@types/node@npm:14 || 16 || 17": - version: 17.0.45 - resolution: "@types/node@npm:17.0.45" - checksum: 10c0/0db377133d709b33a47892581a21a41cd7958f22723a3cc6c71d55ac018121382de42fbfc7970d5ae3e7819dbe5f40e1c6a5174aedf7e7964e9cb8fa72b580b0 +"@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 @@ -3887,11 +3899,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.2.4": - version: 18.3.0 - resolution: "@types/react-dom@npm:18.3.0" + version: 18.3.1 + resolution: "@types/react-dom@npm:18.3.1" dependencies: "@types/react": "npm:*" - checksum: 10c0/6c90d2ed72c5a0e440d2c75d99287e4b5df3e7b011838cdc03ae5cd518ab52164d86990e73246b9d812eaf02ec351d74e3b4f5bd325bf341e13bf980392fd53b + checksum: 10c0/8b416551c60bb6bd8ec10e198c957910cfb271bc3922463040b0d57cf4739cdcd24b13224f8d68f10318926e1ec3cd69af0af79f0291b599a992f8c80d47f1eb languageName: node linkType: hard @@ -3990,12 +4002,12 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.3.10 - resolution: "@types/react@npm:18.3.10" + version: 18.3.12 + resolution: "@types/react@npm:18.3.12" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10c0/f5be1de1b0331c1fdb33d577f4cf7f1b949d4bded5347b2351a537f03c51dade5be115e21b161dcf1b37061954d320f6a0bdf8d7b70e24eda51071fdd614383d + checksum: 10c0/8bae8d9a41619804561574792e29112b413044eb0d53746dde2b9720c1f9a59f71c895bbd7987cd8ce9500b00786e53bc032dced38cddf42910458e145675290 languageName: node linkType: hard @@ -4023,13 +4035,6 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.5.0": - version: 7.5.8 - resolution: "@types/semver@npm:7.5.8" - checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa - languageName: node - linkType: hard - "@types/send@npm:*": version: 0.17.4 resolution: "@types/send@npm:0.17.4" @@ -4135,8 +4140,8 @@ __metadata: linkType: hard "@types/webpack@npm:^4.41.33": - version: 4.41.39 - resolution: "@types/webpack@npm:4.41.39" + version: 4.41.40 + resolution: "@types/webpack@npm:4.41.40" dependencies: "@types/node": "npm:*" "@types/tapable": "npm:^1" @@ -4144,16 +4149,16 @@ __metadata: "@types/webpack-sources": "npm:*" anymatch: "npm:^3.0.0" source-map: "npm:^0.6.0" - checksum: 10c0/740420d092abb80b70263b02609bde209801b060d8e6f3a399a129945cb09182c2ce63dc816908bfbcdb123b35dc4c4fb51367aac2b5974537694cac2631db21 + checksum: 10c0/ecd530e5db4c21ec61795eec538026f96c126323836249a83e72805afd1d0b1141fc781f14d4a59d77f877523384b4c5d79dc391cfb901e7a781a9aa085f8198 languageName: node linkType: hard "@types/ws@npm:^8.5.9": - version: 8.5.12 - resolution: "@types/ws@npm:8.5.12" + version: 8.5.13 + resolution: "@types/ws@npm:8.5.13" dependencies: "@types/node": "npm:*" - checksum: 10c0/3fd77c9e4e05c24ce42bfc7647f7506b08c40a40fe2aea236ef6d4e96fc7cb4006a81ed1b28ec9c457e177a74a72924f4768b7b4652680b42dfd52bc380e15f9 + checksum: 10c0/a5430aa479bde588e69cb9175518d72f9338b6999e3b2ae16fc03d3bdcff8347e486dc031e4ed14601260463c07e1f9a0d7511dfc653712b047c439c680b0b34 languageName: node linkType: hard @@ -4174,14 +4179,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^8.0.0": - version: 8.1.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.1.0" + version: 8.10.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.1.0" - "@typescript-eslint/type-utils": "npm:8.1.0" - "@typescript-eslint/utils": "npm:8.1.0" - "@typescript-eslint/visitor-keys": "npm:8.1.0" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/type-utils": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -4192,104 +4197,68 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/7bbeae588f859b59c34d6a76cac06ef0fa605921b40c5d3b65b94829984280ea84c4dd3f5cb9ce2eb326f5563e9abb4c90ebff05c47f83f4def296c2ea1fa86c + checksum: 10c0/4b77ba9c865a2a14e238cd330b5901f0274b8ce1c13324fccd0339b8eea82a50a4709394c903fd8cd5bd0d3aebace0761ff9a4a19fa20b00bb61349b7671c035 languageName: node linkType: hard "@typescript-eslint/parser@npm:^8.0.0": - version: 8.1.0 - resolution: "@typescript-eslint/parser@npm:8.1.0" + version: 8.10.0 + resolution: "@typescript-eslint/parser@npm:8.10.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.1.0" - "@typescript-eslint/types": "npm:8.1.0" - "@typescript-eslint/typescript-estree": "npm:8.1.0" - "@typescript-eslint/visitor-keys": "npm:8.1.0" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/b94b2d3ab5ca505484d100701fad6a04a5dc8d595029bac1b9f5b8a4a91d80fd605b0f65d230b36a97ab7e5d55eeb0c28af2ab63929a3e4ab8fdefd2a548c36b + checksum: 10c0/7becb2457c085c239838d301796074b790f46dd38c9fbc14ec1dec8e993c7115cd8a66cdc07983c3a68a2dd92e24e8acc49d69a4ebcc29e9869957eb52d1cb74 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/scope-manager@npm:6.21.0" +"@typescript-eslint/scope-manager@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/scope-manager@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/visitor-keys": "npm:6.21.0" - checksum: 10c0/eaf868938d811cbbea33e97e44ba7050d2b6892202cea6a9622c486b85ab1cf801979edf78036179a8ba4ac26f1dfdf7fcc83a68c1ff66be0b3a8e9a9989b526 + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" + checksum: 10c0/b8bb8635c4d6c00a3578d6265e3ee0f5d96d0c9dee534ed588aa411c3f4497fd71cce730c3ae7571e52453d955b191bc9edcc47c9af21a20c90e9a20f2371108 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/scope-manager@npm:8.1.0" +"@typescript-eslint/type-utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/type-utils@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.1.0" - "@typescript-eslint/visitor-keys": "npm:8.1.0" - checksum: 10c0/2bcf8cd176a1819bddcae16c572e7da8fba821b995a91cd53d64d8d6b85a17f5a895522f281ba57e34929574bddd4d6684ee3e545ec4e8096be4c3198e253a9a - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/type-utils@npm:8.1.0" - dependencies: - "@typescript-eslint/typescript-estree": "npm:8.1.0" - "@typescript-eslint/utils": "npm:8.1.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/62753941c4136e8d2daa72fe0410dea48e5317a6f12ece6382ca85e29912bd1b3f739b61d1060fc0a1f8c488dfc905beab4c8b8497951a21c3138a659c7271ec + checksum: 10c0/1af8fce8394279e6ac7bcef449a132072ee36e374c8d557564246ffe7150230844901ca0305e29525bf37c87010e03bf8bedec76fccbfe1e41931cb4f274e208 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/types@npm:6.21.0" - checksum: 10c0/020631d3223bbcff8a0da3efbdf058220a8f48a3de221563996ad1dcc30d6c08dadc3f7608cc08830d21c0d565efd2db19b557b9528921c78aabb605eef2d74d +"@typescript-eslint/types@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/types@npm:8.10.0" + checksum: 10c0/f27dd43c8383e02e914a254257627e393dfc0f08b0f74a253c106813ae361f090271b2f3f2ef588fa3ca1329897d873da595bb5641fe8e3091b25eddca24b5d2 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/types@npm:8.1.0" - checksum: 10c0/ceade44455f45974e68956016c4d1c6626580732f7f9675e14ffa63db80b551752b0df596b20473dae9f0dc6ed966e17417dc2cf36e1a82b6ab0edc97c5eaa50 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" +"@typescript-eslint/typescript-estree@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/visitor-keys": "npm:6.21.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" - globby: "npm:^11.1.0" - is-glob: "npm:^4.0.3" - minimatch: "npm:9.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/af1438c60f080045ebb330155a8c9bb90db345d5069cdd5d01b67de502abb7449d6c75500519df829f913a6b3f490ade3e8215279b6bdc63d0fb0ae61034df5f - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.1.0" - dependencies: - "@typescript-eslint/types": "npm:8.1.0" - "@typescript-eslint/visitor-keys": "npm:8.1.0" - debug: "npm:^4.3.4" - globby: "npm:^11.1.0" + fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" minimatch: "npm:^9.0.4" semver: "npm:^7.6.0" @@ -4297,58 +4266,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/a7bc8275df1c79c4cb14ef086c56674316dd4907efec53eddca35d0b5220428b69c82178ce2d95138da2e398269c8bd0764cae8020a36417e411e35c3c47bc4b + checksum: 10c0/535a740fe25be0e28fe68c41e3264273d1e5169c9f938e08cc0e3415c357726f43efa44621960108c318fc3305c425d29f3223b6e731d44d67f84058a8947304 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/utils@npm:8.1.0" +"@typescript-eslint/utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/utils@npm:8.10.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.1.0" - "@typescript-eslint/types": "npm:8.1.0" - "@typescript-eslint/typescript-estree": "npm:8.1.0" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/c95503a6bdcd98b1ff04d1adbf46377b2036b1c510d90a4a056401f996f775f06c3108c95fb81cd6babc9c97b73b91b8e848f0337bc508de8a49c993582f0e75 + checksum: 10c0/a21a2933517176abd00fcd5d8d80023e35dc3d89d5746bbac43790b4e984ab1f371117db08048bce7f42d54c64f4e0e35161149f8f34fd25a27bff9d1110fd16 languageName: node linkType: hard -"@typescript-eslint/utils@npm:^6.18.1": - version: 6.21.0 - resolution: "@typescript-eslint/utils@npm:6.21.0" +"@typescript-eslint/visitor-keys@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.10.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@types/json-schema": "npm:^7.0.12" - "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.21.0" - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/typescript-estree": "npm:6.21.0" - semver: "npm:^7.5.4" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: 10c0/ab2df3833b2582d4e5467a484d08942b4f2f7208f8e09d67de510008eb8001a9b7460f2f9ba11c12086fd3cdcac0c626761c7995c2c6b5657d5fa6b82030a32d - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" - dependencies: - "@typescript-eslint/types": "npm:6.21.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10c0/7395f69739cfa1cb83c1fb2fad30afa2a814756367302fb4facd5893eff66abc807e8d8f63eba94ed3b0fe0c1c996ac9a1680bcbf0f83717acedc3f2bb724fbf - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.1.0": - version: 8.1.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.1.0" - dependencies: - "@typescript-eslint/types": "npm:8.1.0" + "@typescript-eslint/types": "npm:8.10.0" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10c0/b7544dbb0eec1ddbfcd95c04b51b9a739c2e768c16d1c88508f976a2b0d1bc02fefb7491930e06e48073a5c07c6f488cd8403bba3a8b918888b93a88d5ac3869 + checksum: 10c0/14721c4ac939640d5fd1ee1b6eeb07604b11a6017e319e21dcc71e7aac2992341fc7ae1992d977bad4433b6a1d0d1c0c279e6927316b26245f6e333f922fa458 languageName: node linkType: hard @@ -4838,7 +4780,7 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:5.3.0, aria-query@npm:^5.0.0": +"aria-query@npm:5.3.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" dependencies: @@ -4847,12 +4789,10 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:~5.1.3": - version: 5.1.3 - resolution: "aria-query@npm:5.1.3" - dependencies: - deep-equal: "npm:^2.0.5" - checksum: 10c0/edcbc8044c4663d6f88f785e983e6784f98cb62b4ba1e9dd8d61b725d0203e4cfca38d676aee984c31f354103461102a3d583aa4fbe4fd0a89b679744f4e5faf +"aria-query@npm:^5.0.0, aria-query@npm:^5.3.2": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: 10c0/003c7e3e2cff5540bf7a7893775fc614de82b0c5dde8ae823d47b7a28a9d4da1f7ed85f340bdb93d5649caa927755f0e31ecc7ab63edfdfc00c8ef07e505e03e languageName: node linkType: hard @@ -4877,7 +4817,7 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": +"array-buffer-byte-length@npm:^1.0.1": version: 1.0.1 resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: @@ -5250,21 +5190,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.24 + resolution: "babel-plugin-formatjs@npm:10.5.24" 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.9.3" + "@formatjs/ts-transformer": "npm:3.13.22" + "@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" + checksum: 10c0/a99c92e62edb30e0b6a5bf1115811eb18336b851109f8c096b5a9aa2be3eb72299eea3a8cb706e03705eb79edfa5a62d69bb52d80a375c1d5a1c963e3d00c40e languageName: node linkType: hard @@ -5920,6 +5860,16 @@ __metadata: languageName: node linkType: hard +"chalk@npm:4, chalk@npm:^4.0, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: "npm:^4.1.0" + supports-color: "npm:^7.1.0" + checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 + languageName: node + linkType: hard + "chalk@npm:^2.4.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -5941,16 +5891,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - "chalk@npm:~5.3.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" @@ -6443,9 +6383,9 @@ __metadata: linkType: hard "core-js@npm:^3.30.2": - version: 3.38.1 - resolution: "core-js@npm:3.38.1" - checksum: 10c0/7df063b6f13a54e46515817ac3e235c6c598a4d3de65cd188a061fc250642be313b895fb9fb2f36e1e31890a1bb4ef61d82666a340413f540b7ce3c65689739b + version: 3.39.0 + resolution: "core-js@npm:3.39.0" + checksum: 10c0/f7602069b6afb2e3298eec612a5c1e0c3e6a458930fbfc7a4c5f9ac03426507f49ce395eecdd2d9bae9024f820e44582b67ffe16f2272395af26964f174eeb6b languageName: node linkType: hard @@ -6612,14 +6552,14 @@ __metadata: languageName: node linkType: hard -"css-blank-pseudo@npm:^7.0.0": - version: 7.0.0 - resolution: "css-blank-pseudo@npm:7.0.0" +"css-blank-pseudo@npm:^7.0.1": + version: 7.0.1 + resolution: "css-blank-pseudo@npm:7.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/74c6c0af773a8d2c8c5a53bcfc2b2c06f9c3fd4a8bd756b7aafc102b91a1060b179a4f0aa21475b54685b62bfd9724fee90778dd992b42e0cd3ea3698132af92 + checksum: 10c0/46c3d3a611972fdb0c264db7c0b34fe437bc4300961d11945145cf04962f52a545a6ef55bc8ff4afd82b605bd692b4970f2b54582616dea00441105e725d4618 languageName: node linkType: hard @@ -6639,16 +6579,16 @@ __metadata: languageName: node linkType: hard -"css-has-pseudo@npm:^7.0.0": - version: 7.0.0 - resolution: "css-has-pseudo@npm:7.0.0" +"css-has-pseudo@npm:^7.0.1": + version: 7.0.1 + resolution: "css-has-pseudo@npm:7.0.1" dependencies: - "@csstools/selector-specificity": "npm:^4.0.0" - postcss-selector-parser: "npm:^6.1.0" + "@csstools/selector-specificity": "npm:^5.0.0" + postcss-selector-parser: "npm:^7.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/2c72602ca9bcdb3afe2cce3b014e7dd17548658904c17560042ebf4bd6727b1ed8706961b1f44bff43bbdb8dc932c30a0b29f536c353df858e300e68e163b872 + checksum: 10c0/13789b08b70169204be786d652190356ace9313099d3656bd2fc38afbdd28f3d9620f0e0b07425480961b7a1ec789794961d0472f205b959d3f64c9a78ce511c languageName: node linkType: hard @@ -6784,10 +6724,10 @@ __metadata: languageName: node linkType: hard -"cssdb@npm:^8.1.1": - version: 8.1.1 - resolution: "cssdb@npm:8.1.1" - checksum: 10c0/d60facfad3bca70e21100fc35b9205cb9d3d0ac642f44f0a687e54bf787f21c43d28ce2d17fcd405f67950fb4709516108fe1f3cb15df570eff1007b5fbbc787 +"cssdb@npm:^8.1.2": + version: 8.1.2 + resolution: "cssdb@npm:8.1.2" + checksum: 10c0/056149e713a78921f56d9ef0cd734577cedb93c27966c3d0eab01956a2aa8d3c260a911766064b57ded8b4d9c55dd5275626cbb022ccd8d2d0b93b53fefd1603 languageName: node linkType: hard @@ -7070,32 +7010,6 @@ __metadata: languageName: node linkType: hard -"deep-equal@npm:^2.0.5": - version: 2.2.3 - resolution: "deep-equal@npm:2.2.3" - dependencies: - array-buffer-byte-length: "npm:^1.0.0" - call-bind: "npm:^1.0.5" - es-get-iterator: "npm:^1.1.3" - get-intrinsic: "npm:^1.2.2" - is-arguments: "npm:^1.1.1" - is-array-buffer: "npm:^3.0.2" - is-date-object: "npm:^1.0.5" - is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" - isarray: "npm:^2.0.5" - object-is: "npm:^1.1.5" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.5.1" - side-channel: "npm:^1.0.4" - which-boxed-primitive: "npm:^1.0.2" - which-collection: "npm:^1.0.1" - which-typed-array: "npm:^1.1.13" - checksum: 10c0/a48244f90fa989f63ff5ef0cc6de1e4916b48ea0220a9c89a378561960814794a5800c600254482a2c8fd2e49d6c2e196131dc983976adb024c94a42dfe4949f - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -7769,26 +7683,9 @@ __metadata: languageName: node linkType: hard -"es-get-iterator@npm:^1.1.3": - version: 1.1.3 - resolution: "es-get-iterator@npm:1.1.3" - dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.1.3" - has-symbols: "npm:^1.0.3" - is-arguments: "npm:^1.1.1" - is-map: "npm:^2.0.2" - is-set: "npm:^2.0.2" - is-string: "npm:^1.0.7" - isarray: "npm:^2.0.5" - stop-iteration-iterator: "npm:^1.0.0" - checksum: 10c0/ebd11effa79851ea75d7f079405f9d0dc185559fd65d986c6afea59a0ff2d46c2ed8675f19f03dce7429d7f6c14ff9aede8d121fbab78d75cfda6a263030bac0 - languageName: node - linkType: hard - -"es-iterator-helpers@npm:^1.0.19": - version: 1.0.19 - resolution: "es-iterator-helpers@npm:1.0.19" +"es-iterator-helpers@npm:^1.0.19, es-iterator-helpers@npm:^1.1.0": + version: 1.1.0 + resolution: "es-iterator-helpers@npm:1.1.0" dependencies: call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" @@ -7797,14 +7694,14 @@ __metadata: es-set-tostringtag: "npm:^2.0.3" function-bind: "npm:^1.1.2" get-intrinsic: "npm:^1.2.4" - globalthis: "npm:^1.0.3" + globalthis: "npm:^1.0.4" has-property-descriptors: "npm:^1.0.2" has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" internal-slot: "npm:^1.0.7" - iterator.prototype: "npm:^1.1.2" + iterator.prototype: "npm:^1.1.3" safe-array-concat: "npm:^1.1.2" - checksum: 10c0/ae8f0241e383b3d197383b9842c48def7fce0255fb6ed049311b686ce295595d9e389b466f6a1b7d4e7bb92d82f5e716d6fae55e20c1040249bf976743b038c5 + checksum: 10c0/84d6c240c7da6e62323b336cb1497781546dab16bebdbd879ccfdf588979712d3e941d41165b6c2ffce5a03a7b929d4e6131d3124d330da1a0e2bfa1da7cd99f languageName: node linkType: hard @@ -7963,24 +7860,24 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-formatjs@npm:^4.10.1": - version: 4.13.3 - resolution: "eslint-plugin-formatjs@npm:4.13.3" +"eslint-plugin-formatjs@npm:^5.0.0": + version: 5.1.1 + resolution: "eslint-plugin-formatjs@npm:5.1.1" dependencies: - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/ts-transformer": "npm:3.13.14" - "@types/eslint": "npm:7 || 8" + "@formatjs/icu-messageformat-parser": "npm:2.7.10" + "@formatjs/ts-transformer": "npm:3.13.16" + "@types/eslint": "npm:9" "@types/picomatch": "npm:^2.3.0" - "@typescript-eslint/utils": "npm:^6.18.1" + "@typescript-eslint/utils": "npm:8.10.0" emoji-regex: "npm:^10.2.1" magic-string: "npm:^0.30.0" picomatch: "npm:^2.3.1" - tslib: "npm:2.6.2" + tslib: "npm:^2.7.0" typescript: "npm:5" unicode-emoji-utils: "npm:^1.2.0" peerDependencies: - eslint: 7 || 8 - checksum: 10c0/5e98f487a097189e3bdc64b678d19f4c83502c32d7c89a8959eda4ed9cb664bf16f13ad8871be89ca192cb39c1007d6a158c39bbf5b23c56962d949dbe9abfab + eslint: 9 + checksum: 10c0/b0cf41208fe1bdcd4e7879c0a7099273753ec1e2c5a855c0989679690a740b92123d1625cea7ce862a19412a588fd16e42c0c196807021f13462585ace719dc1 languageName: node linkType: hard @@ -8013,10 +7910,10 @@ __metadata: linkType: hard "eslint-plugin-jsdoc@npm:^50.0.0": - version: 50.2.2 - resolution: "eslint-plugin-jsdoc@npm:50.2.2" + version: 50.4.3 + resolution: "eslint-plugin-jsdoc@npm:50.4.3" dependencies: - "@es-joy/jsdoccomment": "npm:~0.48.0" + "@es-joy/jsdoccomment": "npm:~0.49.0" are-docs-informative: "npm:^0.0.2" comment-parser: "npm:1.4.1" debug: "npm:^4.3.6" @@ -8029,15 +7926,15 @@ __metadata: synckit: "npm:^0.9.1" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/f41d30246f6a4b6acb55e8cd75cf4fc256315e141ab25f7740fa6fa58cdd24e08cb672b4a350da93aeb126d210bd25981310a50f97cfb108f6a7ce8668b6b90a + checksum: 10c0/96067f8fc3553371e9afdc6d03c166228bfd3cb004fcd70c4357d49185732f384351e20f44c21b0a13ea318c8aabbd584b627804f62a2a80376507646708a786 languageName: node linkType: hard "eslint-plugin-jsx-a11y@npm:~6.10.0": - version: 6.10.0 - resolution: "eslint-plugin-jsx-a11y@npm:6.10.0" + version: 6.10.1 + resolution: "eslint-plugin-jsx-a11y@npm:6.10.1" dependencies: - aria-query: "npm:~5.1.3" + aria-query: "npm:^5.3.2" array-includes: "npm:^3.1.8" array.prototype.flatmap: "npm:^1.3.2" ast-types-flow: "npm:^0.0.8" @@ -8045,17 +7942,17 @@ __metadata: axobject-query: "npm:^4.1.0" damerau-levenshtein: "npm:^1.0.8" emoji-regex: "npm:^9.2.2" - es-iterator-helpers: "npm:^1.0.19" + es-iterator-helpers: "npm:^1.1.0" hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^3.3.5" language-tags: "npm:^1.0.9" minimatch: "npm:^3.1.2" object.fromentries: "npm:^2.0.8" safe-regex-test: "npm:^1.0.3" - string.prototype.includes: "npm:^2.0.0" + string.prototype.includes: "npm:^2.0.1" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - checksum: 10c0/9f8e29a3317fb6a82e2ecd333fe0fab3a69fff786d087eb65dc723d6e954473ab681d14a252d7cb2971f5e7f68816cb6f7731766558e1833a77bd73af1b5ab34 + checksum: 10c0/25bf28e3db4f6789c5d4f9300fc6fc54faca19ecc537d0f46e9c873f80ed37103a033e1f716f608fab5f5813dd38af65a9a6ae2e29dd079763ce539ebecf998e languageName: node linkType: hard @@ -8068,18 +7965,18 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:^4.6.0": - version: 4.6.2 - resolution: "eslint-plugin-react-hooks@npm:4.6.2" +"eslint-plugin-react-hooks@npm:^5.0.0": + version: 5.0.0 + resolution: "eslint-plugin-react-hooks@npm:5.0.0" peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 10c0/4844e58c929bc05157fb70ba1e462e34f1f4abcbc8dd5bbe5b04513d33e2699effb8bca668297976ceea8e7ebee4e8fc29b9af9d131bcef52886feaa2308b2cc + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + checksum: 10c0/bcb74b421f32e4203a7100405b57aab85526be4461e5a1da01bc537969a30012d2ee209a2c2a6cac543833a27188ce1e6ad71e4628d0bb4a2e5365cad86c5002 languageName: node linkType: hard "eslint-plugin-react@npm:^7.33.2": - version: 7.35.2 - resolution: "eslint-plugin-react@npm:7.35.2" + version: 7.37.1 + resolution: "eslint-plugin-react@npm:7.37.1" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -8101,7 +7998,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10c0/5f891f5a77e902a0ca8d10b23d0b800e90a09400187febe5986c5078d6277baa4b974d6acdbba25baae065dbcf12eb9241b5f5782527d0780314c2ee5006a8af + checksum: 10c0/13cf55666f16d2ca45b14aad1b0e14741d1817679c86d20aff0bc1e802439a8541f40a42c4c8e3486ffb710f1bcc2f3e56697f2b5f724306a7fca174e1ad6433 languageName: node linkType: hard @@ -8140,14 +8037,14 @@ __metadata: linkType: hard "eslint@npm:^8.41.0": - version: 8.57.0 - resolution: "eslint@npm:8.57.0" + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.57.0" - "@humanwhocodes/config-array": "npm:^0.11.14" + "@eslint/js": "npm:8.57.1" + "@humanwhocodes/config-array": "npm:^0.13.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" "@ungap/structured-clone": "npm:^1.2.0" @@ -8183,7 +8080,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 10c0/00bb96fd2471039a312435a6776fe1fd557c056755eaa2b96093ef3a8508c92c8775d5f754768be6b1dddd09fdd3379ddb231eeb9b6c579ee17ea7d68000a529 + checksum: 10c0/1fd31533086c1b72f86770a4d9d7058ee8b4643fd1cfd10c7aac1ecb8725698e88352a87805cf4b2ce890aa35947df4b4da9655fb7fdfa60dbb448a43f6ebcf1 languageName: node linkType: hard @@ -8995,7 +8892,7 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": +"get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" dependencies: @@ -9190,12 +9087,13 @@ __metadata: languageName: node linkType: hard -"globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" +"globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: "npm:^1.1.3" - checksum: 10c0/0db6e9af102a5254630351557ac15e6909bc7459d3e3f6b001e59fe784c96d31108818f032d9095739355a88467459e6488ff16584ee6250cd8c27dec05af4b0 + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10c0/9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 languageName: node linkType: hard @@ -9426,7 +9324,7 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:3, hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -9842,7 +9740,7 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7": +"internal-slot@npm:^1.0.7": version: 1.0.7 resolution: "internal-slot@npm:1.0.7" dependencies: @@ -9867,15 +9765,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.5, intl-messageformat@npm:^10.3.5": + version: 10.7.5 + resolution: "intl-messageformat@npm:10.7.5" 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.3" + "@formatjs/fast-memoize": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + tslib: "npm:2" + checksum: 10c0/1aa173a8c16ace50520af3de7d3f0ce9bafda90d47b6d674eb88cc47c12c3460d4d53c97ca412fae1141b00abb8ff2ba313250997a040837f01a25379165c949 languageName: node linkType: hard @@ -9958,7 +9856,7 @@ __metadata: languageName: node linkType: hard -"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1": +"is-arguments@npm:^1.0.4": version: 1.1.1 resolution: "is-arguments@npm:1.1.1" dependencies: @@ -9968,7 +9866,7 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": +"is-array-buffer@npm:^3.0.4": version: 3.0.4 resolution: "is-array-buffer@npm:3.0.4" dependencies: @@ -10233,7 +10131,7 @@ __metadata: languageName: node linkType: hard -"is-map@npm:^2.0.1, is-map@npm:^2.0.2": +"is-map@npm:^2.0.1": version: 2.0.3 resolution: "is-map@npm:2.0.3" checksum: 10c0/2c4d431b74e00fdda7162cd8e4b763d6f6f217edf97d4f8538b94b8702b150610e2c64961340015fe8df5b1fcee33ccd2e9b62619c4a8a3a155f8de6d6d355fc @@ -10358,7 +10256,7 @@ __metadata: languageName: node linkType: hard -"is-set@npm:^2.0.1, is-set@npm:^2.0.2": +"is-set@npm:^2.0.1": version: 2.0.3 resolution: "is-set@npm:2.0.3" checksum: 10c0/f73732e13f099b2dc879c2a12341cfc22ccaca8dd504e6edae26484bd5707a35d503fba5b4daad530a9b088ced1ae6c9d8200fd92e09b428fe14ea79ce8080b7 @@ -10585,16 +10483,16 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" dependencies: define-properties: "npm:^1.2.1" get-intrinsic: "npm:^1.2.1" has-symbols: "npm:^1.0.3" reflect.getprototypeof: "npm:^1.0.4" set-function-name: "npm:^2.0.1" - checksum: 10c0/a32151326095e916f306990d909f6bbf23e3221999a18ba686419535dcd1749b10ded505e89334b77dc4c7a58a8508978f0eb16c2c8573e6d412eb7eb894ea79 + checksum: 10c0/68b0320c14291fbb3d8ed5a17e255d3127e7971bec19108076667e79c9ff4c7d69f99de4b0b3075c789c3f318366d7a0a35bb086eae0f2cf832dd58465b2f9e6 languageName: node linkType: hard @@ -11293,12 +11191,15 @@ __metadata: languageName: node linkType: hard -"json-stable-stringify@npm:^1.0.1": - version: 1.0.2 - resolution: "json-stable-stringify@npm:1.0.2" +"json-stable-stringify@npm:1, json-stable-stringify@npm:^1.0.1": + version: 1.1.1 + resolution: "json-stable-stringify@npm:1.1.1" dependencies: + call-bind: "npm:^1.0.5" + isarray: "npm:^2.0.5" jsonify: "npm:^0.0.1" - checksum: 10c0/502d021c3c59c09587faa40d7693d77c00460fd6c68bae95d6e35804909ec8c4aec71b136d3a09df61a7ebf803eb6e820f23ede76b77e74b8b02c76afb2ada8c + object-keys: "npm:^1.1.1" + checksum: 10c0/3801e3eeccbd030afb970f54bea690a079cfea7d9ed206a1b17ca9367f4b7772c764bf77a48f03e56b50e5f7ee7d11c52339fe20d8d7ccead003e4ca69e4cfde languageName: node linkType: hard @@ -12077,15 +11978,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:9.0.3": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac - languageName: node - linkType: hard - "minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -12554,7 +12446,7 @@ __metadata: languageName: node linkType: hard -"object-is@npm:^1.0.1, object-is@npm:^1.1.5": +"object-is@npm:^1.0.1": version: 1.1.6 resolution: "object-is@npm:1.1.6" dependencies: @@ -13155,8 +13047,8 @@ __metadata: linkType: hard "pg@npm:^8.5.0": - version: 8.13.0 - resolution: "pg@npm:8.13.0" + version: 8.13.1 + resolution: "pg@npm:8.13.1" dependencies: pg-cloudflare: "npm:^1.1.1" pg-connection-string: "npm:^2.7.0" @@ -13172,7 +13064,7 @@ __metadata: peerDependenciesMeta: pg-native: optional: true - checksum: 10c0/1521189063d2293d62f3fac61e797a3096a62a69668c223827d00b83c17a320805f31f0b5316feb80f8d9eed0c6c32f95146d8aca866af05816a66fd2ba8e32a + checksum: 10c0/c13bc661cbdb115337bc8519254836faf4bd79106dfd7ed588c8ece8c8b2dd3b7376bfec9a9a2f7646fa095b0b310cec77a83c3ba2ea4872331446eb93fd9055 languageName: node linkType: hard @@ -13245,13 +13137,12 @@ __metadata: languageName: node linkType: hard -"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:^1.2.0": - version: 1.2.0 - resolution: "pino-abstract-transport@npm:1.2.0" +"pino-abstract-transport@npm:^2.0.0": + version: 2.0.0 + resolution: "pino-abstract-transport@npm:2.0.0" dependencies: - readable-stream: "npm:^4.0.0" split2: "npm:^4.0.0" - checksum: 10c0/b4ab59529b7a91f488440147fc58ee0827a6c1c5ca3627292339354b1381072c1a6bfa9b46d03ad27872589e8477ecf74da12cf286e1e6b665ac64a3b806bf07 + checksum: 10c0/02c05b8f2ffce0d7c774c8e588f61e8b77de8ccb5f8125afd4a7325c9ea0e6af7fb78168999657712ae843e4462bb70ac550dfd6284f930ee57f17f486f25a9f languageName: node linkType: hard @@ -13268,8 +13159,8 @@ __metadata: linkType: hard "pino-pretty@npm:^11.0.0": - version: 11.2.2 - resolution: "pino-pretty@npm:11.2.2" + version: 11.3.0 + resolution: "pino-pretty@npm:11.3.0" dependencies: colorette: "npm:^2.0.7" dateformat: "npm:^4.6.3" @@ -13279,7 +13170,7 @@ __metadata: joycon: "npm:^3.1.1" minimist: "npm:^1.2.6" on-exit-leak-free: "npm:^2.1.0" - pino-abstract-transport: "npm:^1.0.0" + pino-abstract-transport: "npm:^2.0.0" pump: "npm:^3.0.0" readable-stream: "npm:^4.0.0" secure-json-parse: "npm:^2.4.0" @@ -13287,7 +13178,7 @@ __metadata: strip-json-comments: "npm:^3.1.1" bin: pino-pretty: bin.js - checksum: 10c0/3ce1769907886a5584f6c8123d9bc987712ad10a375797733a0fe95a238df587dac8e2b709bab291c4e30d41b0cf65808c708c96f8eb98b2778b6df60afa7e66 + checksum: 10c0/8e4d842bfce5fa3fc69d3a6adb1bca873051e000f0fb4879ae1cc5d1410387b2464a7208f6ecc70ec49bb149a9617ec233cb3ec7a5f017ec141cb482d79917c2 languageName: node linkType: hard @@ -13299,13 +13190,13 @@ __metadata: linkType: hard "pino@npm:^9.0.0": - version: 9.4.0 - resolution: "pino@npm:9.4.0" + version: 9.5.0 + resolution: "pino@npm:9.5.0" dependencies: atomic-sleep: "npm:^1.0.0" fast-redact: "npm:^3.1.1" on-exit-leak-free: "npm:^2.1.0" - pino-abstract-transport: "npm:^1.2.0" + pino-abstract-transport: "npm:^2.0.0" pino-std-serializers: "npm:^7.0.0" process-warning: "npm:^4.0.0" quick-format-unescaped: "npm:^4.0.3" @@ -13315,7 +13206,7 @@ __metadata: thread-stream: "npm:^3.0.0" bin: pino: bin.js - checksum: 10c0/12a3d74968964d92b18ca7d6095a3c5b86478dc22264a37486d64e102085ed08820fcbe75e640acc3542fdf2937a34e5050b624f98e6ac62dd10f5e1328058a2 + checksum: 10c0/b06590c5f4da43df59905af1aac344432b43154c4c1569ebea168e7ae7fd0a4181ccabb769a6568cf3e781e1d1b9df13d65b3603e25ebb05539bcb02ea04215e languageName: node linkType: hard @@ -13369,14 +13260,14 @@ __metadata: languageName: node linkType: hard -"postcss-attribute-case-insensitive@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-attribute-case-insensitive@npm:7.0.0" +"postcss-attribute-case-insensitive@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-attribute-case-insensitive@npm:7.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ce2a96bc29f59a6113953f1f72bfa2d4d34e54b194ff4d49aad0d548aa738835afaf479f22060a2605952b842f63aeae278b44e41f8f3a05731df28d08e2df97 + checksum: 10c0/48945abe2024e2d2e4c37d30b8c1aaf37af720f24f6a996f7ea7e7ed33621f5c22cf247ed22028c0c922de040c58c0802729bc39b903cb1693f4b63c0b49da34 languageName: node linkType: hard @@ -13403,18 +13294,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^7.0.3": - version: 7.0.3 - resolution: "postcss-color-functional-notation@npm:7.0.3" +"postcss-color-functional-notation@npm:^7.0.5": + version: 7.0.5 + resolution: "postcss-color-functional-notation@npm:7.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/5e04c81002512c960784043c096bc91ebc76b8fddb9259a2418b0e121eb65042944cc0f78946f6b7e5774ff1fee087849019655e4848af1f88879e3ab9ff7c17 + checksum: 10c0/5e1771b8a43abd3cb18142842e8ac100b205f37a6757d6686da49e0c61ecf33d09244d256f3802962105e7ef79fbde2dffbfc1eedf1700198c54d2d5e48f3dc1 languageName: node linkType: hard @@ -13468,57 +13359,57 @@ __metadata: languageName: node linkType: hard -"postcss-custom-media@npm:^11.0.3": - version: 11.0.3 - resolution: "postcss-custom-media@npm:11.0.3" +"postcss-custom-media@npm:^11.0.5": + version: 11.0.5 + resolution: "postcss-custom-media@npm:11.0.5" dependencies: - "@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" + "@csstools/cascade-layer-name-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + "@csstools/media-query-list-parser": "npm:^4.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/bd3f0cf17d7422385d26afed510dc2acebb1d8c25fce13e2bbee1c49cdc7fe95ebe7f50b89ef0a88ebdd5f6826e89d99e26b905881ceff788df655670dba93d8 + checksum: 10c0/5ba1ca0383818e83d5f6f398a2b0c12cfda066b5d552adfc0e030a2c5f8690c2cc6224f9a1832a9c780dae3fd8d00d78c4a5c88eb36b731da1752f0c3917d488 languageName: node linkType: hard -"postcss-custom-properties@npm:^14.0.2": - version: 14.0.2 - resolution: "postcss-custom-properties@npm:14.0.2" +"postcss-custom-properties@npm:^14.0.4": + version: 14.0.4 + resolution: "postcss-custom-properties@npm:14.0.4" dependencies: - "@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/cascade-layer-name-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/utilities": "npm:^2.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ea2e0cb60c558bb1afb4e601dcc64a38e1b28e5df3e47b83b858fc12d909d0e3453013e6b368fc05a7db7098ffcdc702a30a92f1a3c0ef67dfb97bf089021f1a + checksum: 10c0/5b101ee71289657cc2e5a16f4912009c10441052e2c54bd9e4f3d4d72b652bab56adb662ddaa96881413e375cf9852e2159b3c778d953442ce86efb781c3b2bf languageName: node linkType: hard -"postcss-custom-selectors@npm:^8.0.2": - version: 8.0.2 - resolution: "postcss-custom-selectors@npm:8.0.2" +"postcss-custom-selectors@npm:^8.0.4": + version: 8.0.4 + resolution: "postcss-custom-selectors@npm:8.0.4" dependencies: - "@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" + "@csstools/cascade-layer-name-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/81673ffb0874f63c0f5e14315a5808259ec80ae8452aaf10d28112d30a9aaabbf61d13edb02f8be2965f44b943968c7eda051a1693da436ef157e77fcff0d752 + checksum: 10c0/09d494d2580d0a99f57684f79793d03358286c32460b61a84063c33bdde24865771cb1205efe9a8e26a508be24eba4fb93fc7f1e96ba21ca96a5d17fadb24863 languageName: node linkType: hard -"postcss-dir-pseudo-class@npm:^9.0.0": - version: 9.0.0 - resolution: "postcss-dir-pseudo-class@npm:9.0.0" +"postcss-dir-pseudo-class@npm:^9.0.1": + version: 9.0.1 + resolution: "postcss-dir-pseudo-class@npm:9.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/debae71bf508c0e494ebb1892ce6b3c1c4eeb6b23231180151a93920a12fec771815510cdec54db54605e090ae56af9f07c68ef6a61260d0c837adc719f9e1e4 + checksum: 10c0/da9d3387648c5c3161a653d354c8f3e70a299108df3977e8aa65cf10793e4dd58a2711b3426cd63716245b13584ca8d95adcd6e10e3c9adbc61d08743e2d8690 languageName: node linkType: hard @@ -13573,25 +13464,25 @@ __metadata: languageName: node linkType: hard -"postcss-focus-visible@npm:^10.0.0": - version: 10.0.0 - resolution: "postcss-focus-visible@npm:10.0.0" +"postcss-focus-visible@npm:^10.0.1": + version: 10.0.1 + resolution: "postcss-focus-visible@npm:10.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/b86b825bac597092b300127c2686c0669ce0766165716ecda42f298f21ca69dda721e44917732cbcb2611a4ab650f1231bf8c5d4d07c9daefef815329251ae8a + checksum: 10c0/c5ecc8536a708a49a99d0abd68a88a160664e6c832c808db8edd9f0221e7017a258daa87e49daf2cb098cb037005d46cf492403c8c9c92ad8835d30adaccf665 languageName: node linkType: hard -"postcss-focus-within@npm:^9.0.0": - version: 9.0.0 - resolution: "postcss-focus-within@npm:9.0.0" +"postcss-focus-within@npm:^9.0.1": + version: 9.0.1 + resolution: "postcss-focus-within@npm:9.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/1d6f1b4f4d12e23a2824f394652d520942f00fd582d3016c933a492fe0ba38aaf26bc1855576878aaeaeda1d6fc38da39bb51e8e6470c50ef03f3ea9a286b3d1 + checksum: 10c0/d6ab49d2a7f33485a9e137dc77ec92c5619a3ec92e1e672734fc604853ff1f3c0c189085c12461614be4fcb03ea0347d91791a45986a18d50b5228d161eda57a languageName: node linkType: hard @@ -13625,18 +13516,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^7.0.3": - version: 7.0.3 - resolution: "postcss-lab-function@npm:7.0.3" +"postcss-lab-function@npm:^7.0.5": + version: 7.0.5 + resolution: "postcss-lab-function@npm:7.0.5" dependencies: - "@csstools/css-color-parser": "npm:^3.0.3" - "@csstools/css-parser-algorithms": "npm:^3.0.2" - "@csstools/css-tokenizer": "npm:^3.0.2" + "@csstools/css-color-parser": "npm:^3.0.5" + "@csstools/css-parser-algorithms": "npm:^3.0.4" + "@csstools/css-tokenizer": "npm:^3.0.3" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/c50a73a9ed54b4194998c4627599d1f42074235f572edbbcdb0e00717f3ae2121dc8378d917792b281860c5650a617d923823da6f395515f610b5760d115354d + checksum: 10c0/b688f6332ac12974452c97c5a40f4d0a604ce16b074124a1106add9cf9c25fbe7717d23423d6e92d937dc6e288e03e885b70e0793b96f41d28d2f7403bce7bf5 languageName: node linkType: hard @@ -13793,16 +13684,16 @@ __metadata: languageName: node linkType: hard -"postcss-nesting@npm:^13.0.0": - version: 13.0.0 - resolution: "postcss-nesting@npm:13.0.0" +"postcss-nesting@npm:^13.0.1": + version: 13.0.1 + resolution: "postcss-nesting@npm:13.0.1" dependencies: - "@csstools/selector-resolve-nested": "npm:^2.0.0" - "@csstools/selector-specificity": "npm:^4.0.0" - postcss-selector-parser: "npm:^6.1.0" + "@csstools/selector-resolve-nested": "npm:^3.0.0" + "@csstools/selector-specificity": "npm:^5.0.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/b82a3c7010f7c6097bd3f3fe6c03f3f3af9a63a58e255f120dadd506a0ea9444aeeaba994f2a3fa34fb26e666dc72032edf5786c5fbdade790b02ad07d91ef95 + checksum: 10c0/549307c272cdd4cb5105d8fbcd582f15a1cb74e5bba240b05b27f77fe0422730be966699a49a9ad15fd9d1bc551c1edbaefb21a69686a9b131b585dbc9d90ebf languageName: node linkType: hard @@ -13957,84 +13848,84 @@ __metadata: linkType: hard "postcss-preset-env@npm:^10.0.0": - version: 10.0.7 - resolution: "postcss-preset-env@npm:10.0.7" + version: 10.0.9 + resolution: "postcss-preset-env@npm:10.0.9" dependencies: - "@csstools/postcss-cascade-layers": "npm:^5.0.0" - "@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-cascade-layers": "npm:^5.0.1" + "@csstools/postcss-color-function": "npm:^4.0.5" + "@csstools/postcss-color-mix-function": "npm:^3.0.5" + "@csstools/postcss-content-alt-text": "npm:^2.0.4" + "@csstools/postcss-exponential-functions": "npm:^2.0.4" "@csstools/postcss-font-format-keywords": "npm:^4.0.0" - "@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-gamut-mapping": "npm:^2.0.5" + "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.5" + "@csstools/postcss-hwb-function": "npm:^4.0.5" "@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.5" + "@csstools/postcss-is-pseudo-class": "npm:^5.0.1" + "@csstools/postcss-light-dark-function": "npm:^2.0.7" "@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.2" - "@csstools/postcss-media-minmax": "npm:^2.0.2" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.2" + "@csstools/postcss-logical-viewport-units": "npm:^3.0.3" + "@csstools/postcss-media-minmax": "npm:^2.0.4" + "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.4" "@csstools/postcss-nested-calc": "npm:^4.0.0" "@csstools/postcss-normalize-display-values": "npm:^4.0.0" - "@csstools/postcss-oklab-function": "npm:^4.0.3" + "@csstools/postcss-oklab-function": "npm:^4.0.5" "@csstools/postcss-progressive-custom-properties": "npm:^4.0.0" - "@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.2" + "@csstools/postcss-relative-color-syntax": "npm:^3.0.5" + "@csstools/postcss-scope-pseudo-class": "npm:^4.0.1" + "@csstools/postcss-stepped-value-functions": "npm:^4.0.4" "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.1" - "@csstools/postcss-trigonometric-functions": "npm:^4.0.2" + "@csstools/postcss-trigonometric-functions": "npm:^4.0.4" "@csstools/postcss-unset-value": "npm:^4.0.0" autoprefixer: "npm:^10.4.19" browserslist: "npm:^4.23.1" - css-blank-pseudo: "npm:^7.0.0" - css-has-pseudo: "npm:^7.0.0" + css-blank-pseudo: "npm:^7.0.1" + css-has-pseudo: "npm:^7.0.1" css-prefers-color-scheme: "npm:^10.0.0" - cssdb: "npm:^8.1.1" - postcss-attribute-case-insensitive: "npm:^7.0.0" + cssdb: "npm:^8.1.2" + postcss-attribute-case-insensitive: "npm:^7.0.1" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^7.0.3" + postcss-color-functional-notation: "npm:^7.0.5" postcss-color-hex-alpha: "npm:^10.0.0" postcss-color-rebeccapurple: "npm:^10.0.0" - 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-custom-media: "npm:^11.0.5" + postcss-custom-properties: "npm:^14.0.4" + postcss-custom-selectors: "npm:^8.0.4" + postcss-dir-pseudo-class: "npm:^9.0.1" postcss-double-position-gradients: "npm:^6.0.0" - postcss-focus-visible: "npm:^10.0.0" - postcss-focus-within: "npm:^9.0.0" + postcss-focus-visible: "npm:^10.0.1" + postcss-focus-within: "npm:^9.0.1" 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.3" + postcss-lab-function: "npm:^7.0.5" postcss-logical: "npm:^8.0.0" - postcss-nesting: "npm:^13.0.0" + postcss-nesting: "npm:^13.0.1" postcss-opacity-percentage: "npm:^3.0.0" postcss-overflow-shorthand: "npm:^6.0.0" postcss-page-break: "npm:^3.0.4" postcss-place: "npm:^10.0.0" - postcss-pseudo-class-any-link: "npm:^10.0.0" + postcss-pseudo-class-any-link: "npm:^10.0.1" postcss-replace-overflow-wrap: "npm:^4.0.0" - postcss-selector-not: "npm:^8.0.0" + postcss-selector-not: "npm:^8.0.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/f789000e0504fd827e854bb0feb8b4c218d381314e4d863c5a36df925df412d0844c912952fe27892a320433640aeaff03ee94a3057b42011bf5d32b3963f333 + checksum: 10c0/985ef4cfd2dd6a94d8a802db8e392c4b4c47ae0de8fd5224c60d8172cac3d7ce9011e63ab80470cddc77f21f09b2be850f97ac2478f651bc0a8956b538b079fe languageName: node linkType: hard -"postcss-pseudo-class-any-link@npm:^10.0.0": - version: 10.0.0 - resolution: "postcss-pseudo-class-any-link@npm:10.0.0" +"postcss-pseudo-class-any-link@npm:^10.0.1": + version: 10.0.1 + resolution: "postcss-pseudo-class-any-link@npm:10.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/8357716e0ba0f01c70dba65a1efd268f610249ac2fbd41833e5e87dc19ffa7911c8d5e234d0d7c77d94ba6cdfa04fe7f0f98461c34f64cdbb59abd9737ab7d32 + checksum: 10c0/95e883996e87baf14fc09d25f9a763a2e9d599eb3b9c6b736e83a8c3d0b55841bcb886bccdf51b5b7fefc128cbd0187ad8841f59878f85bd1613642e592d7673 languageName: node linkType: hard @@ -14095,18 +13986,18 @@ __metadata: languageName: node linkType: hard -"postcss-selector-not@npm:^8.0.0": - version: 8.0.0 - resolution: "postcss-selector-not@npm:8.0.0" +"postcss-selector-not@npm:^8.0.1": + version: 8.0.1 + resolution: "postcss-selector-not@npm:8.0.1" dependencies: - postcss-selector-parser: "npm:^6.1.0" + postcss-selector-parser: "npm:^7.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/677f2cd9d0cd481d276663b57001b2ba96db94ad5bba397f277e53d560ccb074b27c21792deff44720a9f2d96da85fa34f438bb1d33198305b5866b35f1a4708 + checksum: 10c0/491ea3dcc421cd90135be786078521605e2062fb93624ea8813cfd5ba0d35143f931e2e608d5f20effd5ea7d3f4786d2afea2afa42d117779a0288e135f132b6 languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.0, postcss-selector-parser@npm:^6.1.2": +"postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.2": version: 6.1.2 resolution: "postcss-selector-parser@npm:6.1.2" dependencies: @@ -14116,6 +14007,16 @@ __metadata: languageName: node linkType: hard +"postcss-selector-parser@npm:^7.0.0": + version: 7.0.0 + resolution: "postcss-selector-parser@npm:7.0.0" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 10c0/e96e096afcce70bf5c97789f5ea09d7415ae5eb701d82b05b5e8532885d31363b484fcb1ca9488c9a331f30508d9e5bb6c3109eb2eb5067ef3d3919f9928cd9d + languageName: node + linkType: hard + "postcss-svgo@npm:^7.0.1": version: 7.0.1 resolution: "postcss-svgo@npm:7.0.1" @@ -14597,26 +14498,26 @@ __metadata: linkType: hard "react-intl@npm:^6.4.2": - version: 6.7.0 - resolution: "react-intl@npm:6.7.0" + version: 6.8.6 + resolution: "react-intl@npm:6.8.6" dependencies: - "@formatjs/ecma402-abstract": "npm:2.0.0" - "@formatjs/icu-messageformat-parser": "npm:2.7.8" - "@formatjs/intl": "npm:2.10.5" - "@formatjs/intl-displaynames": "npm:6.6.8" - "@formatjs/intl-listformat": "npm:7.5.7" - "@types/hoist-non-react-statics": "npm:^3.3.1" + "@formatjs/ecma402-abstract": "npm:2.2.3" + "@formatjs/icu-messageformat-parser": "npm:2.9.3" + "@formatjs/intl": "npm:2.10.13" + "@formatjs/intl-displaynames": "npm:6.8.3" + "@formatjs/intl-listformat": "npm:7.7.3" + "@types/hoist-non-react-statics": "npm:3" "@types/react": "npm:16 || 17 || 18" - hoist-non-react-statics: "npm:^3.3.2" - intl-messageformat: "npm:10.5.14" - tslib: "npm:^2.4.0" + hoist-non-react-statics: "npm:3" + intl-messageformat: "npm:10.7.5" + tslib: "npm:2" peerDependencies: react: ^16.6.0 || 17 || 18 typescript: ^4.7 || 5 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/210088bf0e934ad5f09d8e7c6d7d72682bb806583645fb333d4efd8ae55585b675ea8e47bb240140d5143ca15ecc0457c3ddc3e8ca45e9b576bce1fa2f9886b3 + checksum: 10c0/ec88cc2b1d0edf089f04c8061ffda730840fb3317177d0dc1a6df208245ec278f52b4ca8546ff9511b0b28ff2d89863c5837a274d33731d4c8f75a3b3baafbe2 languageName: node linkType: hard @@ -14777,8 +14678,8 @@ __metadata: linkType: hard "react-select@npm:^5.7.3": - version: 5.8.1 - resolution: "react-select@npm:5.8.1" + version: 5.8.2 + resolution: "react-select@npm:5.8.2" dependencies: "@babel/runtime": "npm:^7.12.0" "@emotion/cache": "npm:^11.4.0" @@ -14792,7 +14693,7 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 10c0/0fd73e1e472105f980e09c86f0e6adbdc9f2f5c1befa275b08c71653becdd1829f596155a81b5085cb86f18b20bf4f4cc439ab5fe23e68f326e169dcfe00ccf6 + checksum: 10c0/3089b8bfb23f556a7b1de07ea654fc5f5976f531a731a0231bbcbc195afb9294c36f49d712712f2deefc13eb6d7ede4aa1d80cb45b80afd3e26fde2f09db35eb languageName: node linkType: hard @@ -14882,15 +14783,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 @@ -15134,7 +15035,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": +"regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.5.2": version: 1.5.2 resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: @@ -16352,15 +16253,6 @@ __metadata: languageName: node linkType: hard -"stop-iteration-iterator@npm:^1.0.0": - version: 1.0.0 - resolution: "stop-iteration-iterator@npm:1.0.0" - dependencies: - internal-slot: "npm:^1.0.4" - checksum: 10c0/c4158d6188aac510d9e92925b58709207bd94699e9c31186a040c80932a687f84a51356b5895e6dc72710aad83addb9411c22171832c9ae0e6e11b7d61b0dfb9 - languageName: node - linkType: hard - "stream-browserify@npm:^2.0.1": version: 2.0.2 resolution: "stream-browserify@npm:2.0.2" @@ -16445,13 +16337,14 @@ __metadata: languageName: node linkType: hard -"string.prototype.includes@npm:^2.0.0": - version: 2.0.0 - resolution: "string.prototype.includes@npm:2.0.0" +"string.prototype.includes@npm:^2.0.1": + version: 2.0.1 + resolution: "string.prototype.includes@npm:2.0.1" dependencies: - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.17.5" - checksum: 10c0/32dff118c9e9dcc87e240b05462fa8ee7248d9e335c0015c1442fe18152261508a2146d9bb87ddae56abab69148a83c61dfaea33f53853812a6a2db737689ed2 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.3" + checksum: 10c0/25ce9c9b49128352a2618fbe8758b46f945817a58a4420f4799419e40a8d28f116e176c7590d767d5327a61e75c8f32c86171063f48e389b9fdd325f1bd04ee5 languageName: node linkType: hard @@ -17155,13 +17048,6 @@ __metadata: languageName: node linkType: hard -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: 10c0/b214d21dbfb4bce3452b6244b336806ffea9c05297148d32ebb428d5c43ce7545bdfc65a1ceb58c9ef4376a65c0cb2854d645f33961658b3e3b4f84910ddcdd7 - languageName: node - linkType: hard - "to-object-path@npm:^0.3.0": version: 0.3.0 resolution: "to-object-path@npm:0.3.0" @@ -17271,7 +17157,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": +"ts-api-utils@npm:^1.3.0": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" peerDependencies: @@ -17292,17 +17178,10 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.6.2": - version: 2.6.2 - resolution: "tslib@npm:2.6.2" - checksum: 10c0/e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb - languageName: node - linkType: hard - -"tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2": - version: 2.7.0 - resolution: "tslib@npm:2.7.0" - checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 +"tslib@npm:2, tslib@npm:^2.0.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.7.0": + version: 2.8.0 + resolution: "tslib@npm:2.8.0" + checksum: 10c0/31e4d14dc1355e9b89e4d3c893a18abb7f90b6886b089c2da91224d0a7752c79f3ddc41bc1aa0a588ac895bd97bb99c5bc2bfdb2f86de849f31caeb3ba79bbe5 languageName: node linkType: hard @@ -17484,6 +17363,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.8": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -17737,12 +17623,12 @@ __metadata: linkType: hard "utf-8-validate@npm:^6.0.3": - version: 6.0.4 - resolution: "utf-8-validate@npm:6.0.4" + version: 6.0.5 + resolution: "utf-8-validate@npm:6.0.5" dependencies: node-gyp: "npm:latest" node-gyp-build: "npm:^4.3.0" - checksum: 10c0/f7042d94aec6ca02461b64e725bdc7262266610dbb787331e5bbd49374ef6f75fe9900600df3fc63d97906c23614a965c8989b4bf95d70bf35dc617da99215e7 + checksum: 10c0/6dc63c513adb001e47a51819072cdd414158430091c49c21d4947ea99f16df5167b671f680df8fb2b6f2ae6a7f30264b4ec111bd3e573720dfe371da1ab99a81 languageName: node linkType: hard @@ -18296,7 +18182,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.9": +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.9": version: 1.1.15 resolution: "which-typed-array@npm:1.1.15" dependencies: @@ -18356,28 +18242,28 @@ __metadata: languageName: node linkType: hard -"workbox-background-sync@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-background-sync@npm:7.1.0" +"workbox-background-sync@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-background-sync@npm:7.3.0" dependencies: idb: "npm:^7.0.1" - workbox-core: "npm:7.1.0" - checksum: 10c0/9538c49a377d8eb06acee3848fbca09bac1940a2ca9e904fed765c39aa32f77c20d72c3ba6fa1eb47bee81289b1d527556a1cd3e02728960a4c40400ce6d0e91 + workbox-core: "npm:7.3.0" + checksum: 10c0/cc982d62702847fb16c4ef372a8bd243348a80c2d5da1649a860b0187b45060a799a65582c2d36f1a32e31d5d68dedcb037698c41d3b2f171ea5d54d73453cf1 languageName: node linkType: hard -"workbox-broadcast-update@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-broadcast-update@npm:7.1.0" +"workbox-broadcast-update@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-broadcast-update@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/4a6e201cedcbc11b9d2f63f63477ba4564a35ce07bd54640198db6ff6a3b8347a65e0b4973c8f8463e8a622fd1ad93d7b3bab42338608811d23c7db01fef475e + workbox-core: "npm:7.3.0" + checksum: 10c0/25007acd3e845b5ca1f4c9ac9888ce661431723f7419cfa56b3029b6c56cbeca24902dae015c42a2d6f554f956274743e331d03ceeb4b0e3879cb7b908d0e82f languageName: node linkType: hard -"workbox-build@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-build@npm:7.1.0" +"workbox-build@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-build@npm:7.3.0" dependencies: "@apideck/better-ajv-errors": "npm:^0.3.1" "@babel/core": "npm:^7.24.4" @@ -18401,163 +18287,163 @@ __metadata: strip-comments: "npm:^2.0.1" tempy: "npm:^0.6.0" upath: "npm:^1.2.0" - workbox-background-sync: "npm:7.1.0" - workbox-broadcast-update: "npm:7.1.0" - workbox-cacheable-response: "npm:7.1.0" - workbox-core: "npm:7.1.0" - workbox-expiration: "npm:7.1.0" - workbox-google-analytics: "npm:7.1.0" - workbox-navigation-preload: "npm:7.1.0" - workbox-precaching: "npm:7.1.0" - workbox-range-requests: "npm:7.1.0" - workbox-recipes: "npm:7.1.0" - workbox-routing: "npm:7.1.0" - workbox-strategies: "npm:7.1.0" - workbox-streams: "npm:7.1.0" - workbox-sw: "npm:7.1.0" - workbox-window: "npm:7.1.0" - checksum: 10c0/c482fde713bad582bd7d4861113d7367ab4722eba9c102864c71048815792c623e9117a8f79957e0388d0c08e8303962d1fb23931456da73909e87d06638d101 + workbox-background-sync: "npm:7.3.0" + workbox-broadcast-update: "npm:7.3.0" + workbox-cacheable-response: "npm:7.3.0" + workbox-core: "npm:7.3.0" + workbox-expiration: "npm:7.3.0" + workbox-google-analytics: "npm:7.3.0" + workbox-navigation-preload: "npm:7.3.0" + workbox-precaching: "npm:7.3.0" + workbox-range-requests: "npm:7.3.0" + workbox-recipes: "npm:7.3.0" + workbox-routing: "npm:7.3.0" + workbox-strategies: "npm:7.3.0" + workbox-streams: "npm:7.3.0" + workbox-sw: "npm:7.3.0" + workbox-window: "npm:7.3.0" + checksum: 10c0/cb396f9c2a53429d1e11b4c1da2e21c9e1c98473ce15f20ae53277e47bd7ccbcb3f1f843694e588bb70b12d9332faafd098ca05b93abb0293d373f38a8de3ca8 languageName: node linkType: hard -"workbox-cacheable-response@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-cacheable-response@npm:7.1.0" +"workbox-cacheable-response@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-cacheable-response@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/52ea73bb184c9ef9280cc8f00a1ab7d103d495e12a7a6378fae02fd0aa1a9b893aac5d8074f14ed8c198527123e4401f4703fbfd2be98e184ca783b9216cb4c5 + workbox-core: "npm:7.3.0" + checksum: 10c0/192c8a8878c53a205c55398bac78f2c32c0f36e55c95cab282d8a716ddf2fa72563afaed690d34d3438cc8df5fb0df4d98dcb2d93cc6d67c69a9ae592f7bf246 languageName: node linkType: hard -"workbox-core@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-core@npm:7.1.0" - checksum: 10c0/fb0b6e23a52e085da00b7a74b1f1854f06c695eb2bd4c244aa335165f59156a4febb4f116b9893b9fb7e0e8bac092d32eecceb4d00f930a93f64737cb2be9531 +"workbox-core@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-core@npm:7.3.0" + checksum: 10c0/b7dce640cd9665ed207f65f5b08a50e2e24e5599790c6ea4fec987539b9d2ef81765d8c5f94acfee3a8a45d5ade8e1a4ebd0b8847a1471302ef75a5b93c7bd04 languageName: node linkType: hard -"workbox-expiration@npm:7.1.0, workbox-expiration@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-expiration@npm:7.1.0" +"workbox-expiration@npm:7.3.0, workbox-expiration@npm:^7.0.0": + version: 7.3.0 + resolution: "workbox-expiration@npm:7.3.0" dependencies: idb: "npm:^7.0.1" - workbox-core: "npm:7.1.0" - checksum: 10c0/669d76f87c1550ce9b425232c3202a26fdea4c4c9bdc1b71c1cee741a5d011423098994452e508576174d3c0b4bec0f4b35012b6d7257e300684c87fdddb7949 + workbox-core: "npm:7.3.0" + checksum: 10c0/6040d72122ece901becfcc59974586e9cc9b6309840b83b652c9f9aafe32ff89783404a431cadf6f888f80e5371252820e425ced499742964d6d68687f6fad1a languageName: node linkType: hard -"workbox-google-analytics@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-google-analytics@npm:7.1.0" +"workbox-google-analytics@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-google-analytics@npm:7.3.0" dependencies: - workbox-background-sync: "npm:7.1.0" - workbox-core: "npm:7.1.0" - workbox-routing: "npm:7.1.0" - workbox-strategies: "npm:7.1.0" - checksum: 10c0/4178d94fb7f3f7b789f117c104b2ff33945256dc550418b0e9c81130c1e2c2bcd72ec6a1661d91326c04de360e6592edd505f0e2142e8e1043fe0c45f9c1a3fe + workbox-background-sync: "npm:7.3.0" + workbox-core: "npm:7.3.0" + workbox-routing: "npm:7.3.0" + workbox-strategies: "npm:7.3.0" + checksum: 10c0/5317a4bcc01f1aa87480f9708d7d382c15fb37d6119e71e0a2909dfd683f6060b5cc4f7b016a81fc67098f51a5d0cfd1cda20e228f2f3778ee3caf649b59996b languageName: node linkType: hard -"workbox-navigation-preload@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-navigation-preload@npm:7.1.0" +"workbox-navigation-preload@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-navigation-preload@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/b667a3ba0cae4d43a53a6e211f0f33f6ebc1d9fec6cbb93de83f72a37b81cc39d887b969db9b1cd5c396a1ce34636c89c3b157cc64a5265635d0b274e362db0e + workbox-core: "npm:7.3.0" + checksum: 10c0/69e4d43c68c06889987e9fa437995378b0632c83bad8c7044b4ed812b05b94b3a4aa8700ea4c26b2ecf68ee6858e94ff41dfa3279815c1bc385ac19c0edfb200 languageName: node linkType: hard -"workbox-precaching@npm:7.1.0, workbox-precaching@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-precaching@npm:7.1.0" +"workbox-precaching@npm:7.3.0, workbox-precaching@npm:^7.0.0": + version: 7.3.0 + resolution: "workbox-precaching@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - workbox-routing: "npm:7.1.0" - workbox-strategies: "npm:7.1.0" - checksum: 10c0/53b2d0a658109b4d83ee2b1913f884ee1c757a12b8931a7102272bd1e228d29f9430e7d060f328f465bca2aa24bf0719d026eef4f4d21395fa1f678f8d6a3c06 + workbox-core: "npm:7.3.0" + workbox-routing: "npm:7.3.0" + workbox-strategies: "npm:7.3.0" + checksum: 10c0/15c4c5cf5dfec684711ce3536bbfa6873f7af16b712d02ded81d3ff490ea4097e46602705548f5872c49f06e3516fd69f17e72a7fc60631ff6d68460e48f7648 languageName: node linkType: hard -"workbox-range-requests@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-range-requests@npm:7.1.0" +"workbox-range-requests@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-range-requests@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/bf4aa597d04cbb533796af64f4006a1f472f8a14ea91f96fe37b2d5e63ffe86dcb944dab9a41317e69d368d83bee20f03ff32b339ae5addef50f325703ad4b77 + workbox-core: "npm:7.3.0" + checksum: 10c0/d48e1484866442864d66b1891c4965b71e997a83a7634f11452ec1a73a30a5e642e6a95d5cff45578bef4dec7a5f57bc598aeedb6189d17ca210e2c5f2898244 languageName: node linkType: hard -"workbox-recipes@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-recipes@npm:7.1.0" +"workbox-recipes@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-recipes@npm:7.3.0" dependencies: - workbox-cacheable-response: "npm:7.1.0" - workbox-core: "npm:7.1.0" - workbox-expiration: "npm:7.1.0" - workbox-precaching: "npm:7.1.0" - workbox-routing: "npm:7.1.0" - workbox-strategies: "npm:7.1.0" - checksum: 10c0/5a8c2444f6338c6092be87cc6fd69c8b0cbb413bfc0a11a8f10961bfb2b8059359c4be0264ffa0c01deff3ab5dba15bbcf61d4dedbc93d8bfe1f8a2841b1657c + workbox-cacheable-response: "npm:7.3.0" + workbox-core: "npm:7.3.0" + workbox-expiration: "npm:7.3.0" + workbox-precaching: "npm:7.3.0" + workbox-routing: "npm:7.3.0" + workbox-strategies: "npm:7.3.0" + checksum: 10c0/c8146ece4247cbcbefba36a14f2cb65b5f74b2412f64cfc7955ff75ff653857161a1f1d94c987fbae4812f5b770eedcf99af965e512cc375fbc7fb5421bdc99c languageName: node linkType: hard -"workbox-routing@npm:7.1.0, workbox-routing@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-routing@npm:7.1.0" +"workbox-routing@npm:7.3.0, workbox-routing@npm:^7.0.0": + version: 7.3.0 + resolution: "workbox-routing@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/efd630fff594bd50276770840bce274660972587e79c097a9f1a84e8347351736aac13f11c6d7655ff550b13195d370d5c3b81a075bf452f358fc144ee868ad9 + workbox-core: "npm:7.3.0" + checksum: 10c0/8ac1824211d0fbe0e916ecb2c2427bcb0ef8783f9225d8114fe22e6c326f2d8a040a089bead58064e8b096ec95abe070c04cd7353dd8830dba3ab8d608a053aa languageName: node linkType: hard -"workbox-strategies@npm:7.1.0, workbox-strategies@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-strategies@npm:7.1.0" +"workbox-strategies@npm:7.3.0, workbox-strategies@npm:^7.0.0": + version: 7.3.0 + resolution: "workbox-strategies@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - checksum: 10c0/b08712a69b1b13e354345cc228c29f0c759043f7ca7cf6ce9b82fe79c9d423142bfa4a118f91f1a57054047a730127fa4474d59d9306fb2ed42fe9ef568be01a + workbox-core: "npm:7.3.0" + checksum: 10c0/50f3c28b46b54885a9461ad6559010d9abb2a7e35e0128d05c268f3ea0a96b1a747934758121d0e821f7af63946d9db8f4d2d7e0146f12555fb05c768e6b82bb languageName: node linkType: hard -"workbox-streams@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-streams@npm:7.1.0" +"workbox-streams@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-streams@npm:7.3.0" dependencies: - workbox-core: "npm:7.1.0" - workbox-routing: "npm:7.1.0" - checksum: 10c0/1d75c046fcb7b25e1cf85457e3610309dd5513f68752ef333529fcf155df2114b72f3d6f416bb68393e51b5396e3f6df7171e8e2889d0e9e1805e315754b771e + workbox-core: "npm:7.3.0" + workbox-routing: "npm:7.3.0" + checksum: 10c0/2ae541343d187eb7a50da2cfd74051f15771d1ddd1cad6856ffd530f7cccdb8eed9a8af94ff7540b710fef73eeec37d652123ae42b0206fbbd0679dc25e66ff4 languageName: node linkType: hard -"workbox-sw@npm:7.1.0": - version: 7.1.0 - resolution: "workbox-sw@npm:7.1.0" - checksum: 10c0/2084f1b58c8509d7ca53ce8a13d93e57d1f13307e0279fedc87942e83c8cb96bc2e5ed3992a89af6245ad2a66897a92908cb60d0717fb90492056eb6fbf20dc6 +"workbox-sw@npm:7.3.0": + version: 7.3.0 + resolution: "workbox-sw@npm:7.3.0" + checksum: 10c0/9ae275e31dd5ec51245773b6d90fda16d0b7f70d59f3a71aec732814b5aedf08aedc7fcce57739e7e89d9e1479ef97e3a202a542a511d732cf5e8b5d1c293870 languageName: node linkType: hard "workbox-webpack-plugin@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-webpack-plugin@npm:7.1.0" + version: 7.3.0 + resolution: "workbox-webpack-plugin@npm:7.3.0" dependencies: fast-json-stable-stringify: "npm:^2.1.0" pretty-bytes: "npm:^5.4.1" upath: "npm:^1.2.0" webpack-sources: "npm:^1.4.3" - workbox-build: "npm:7.1.0" + workbox-build: "npm:7.3.0" peerDependencies: webpack: ^4.4.0 || ^5.91.0 - checksum: 10c0/516fa68a6a6958ee1560299dd1146032dda68474a2ab01643cbde78fc65b75a3157aef60cb45dcc1984cc458ce44d4e3090cda08dd7cefd0952351270e963a00 + checksum: 10c0/dd3625544fe08b099fd2b783584c6c2c5da3f0e0c3096fc1a86a0b96a26df5055dd178d3c60ab4cde4099474ab23d51c292356c6910dfa16a974c8a95f351c93 languageName: node linkType: hard -"workbox-window@npm:7.1.0, workbox-window@npm:^7.0.0": - version: 7.1.0 - resolution: "workbox-window@npm:7.1.0" +"workbox-window@npm:7.3.0, workbox-window@npm:^7.0.0": + version: 7.3.0 + resolution: "workbox-window@npm:7.3.0" dependencies: "@types/trusted-types": "npm:^2.0.2" - workbox-core: "npm:7.1.0" - checksum: 10c0/c989a6e3a0488f049eead3892f8249387604fb04898aa79d0cf14cd7b684f0758f1edf1996745f4755bd30c31c449f628803e507d39b2ea91cc9c36f7d5e9c72 + workbox-core: "npm:7.3.0" + checksum: 10c0/dbda33c4761ec40051cfe6e3f1701b2381b4f3b191f7a249c32f683503ea35cf8b42d1f99df5ba3b693fac78705d8ed0c191488bdd178c525d1291d0161ec8ff languageName: node linkType: hard